I have implemented several jQuery plugins for my current project.
Since some plugins have functions with the same name, the one called in the last one defined.
Here is the definition of my first plugin:
$(function($)
{
$.fn.initPlugin1 = function(parameters)
{
var defaultParameters = {};
$(this).data('parameters', $.extend(defaultParameters, parameters));
return $(this);
};
$.fn.function1 = function(){ console.log('Function 1.'); };
$.fn.callFunction = function(){ $(this).function1(); };
});
And here is the definition of my second plugin:
$(function($)
{
$.fn.initPlugin2 = function(parameters)
{
var defaultParameters = {};
$(this).data('parameters', $.extend(defaultParameters, parameters));
return $(this);
};
$.fn.function2 = function(){ console.log('Function 2.'); };
$.fn.callFunction = function(){ $(this).function2(); };
});
I have also this scenario :
$("#div1").initPlugin1().callFunction();
$("#div2").initPlugin2().callFunction();
For this specific scenario the consoles shows: Function 2. Function 2.
In fact, since the callFunction() is also defined in the second plugin, this is the one used.
I would like some advise on what is the best way to solve this problem.
Is it possible to create a thing similiar to a namespace ?
Thank to #syms answer, I have created the following example.
Plugin1:
$(function($) {
$.fn.initPlugin1 = function() {
console.log('Initialized Plugin1');
return $(this);
};
$.fn.initPlugin1.testFunction = function() {
$(this).append('Function 1.');
};
});
Plugin2:
$(function($) {
$.fn.initPlugin2 = function() {
console.log('Initialized Plugin2');
return $(this);
};
$.fn.initPlugin2.testFunction = function() {
$(this).append('Function 2.');
};
});
Main:
(function($)
{
$(document).ready(
function()
{
$("#div1").initPlugin1(); //Run correctly
$("#div2").initPlugin2(); //Run correctly
$("#div1").initPlugin1.testFunction(); //Fail
$("#div2").initPlugin2.testFunction(); //Fail
});
})(jQuery);
When I run my code, I got the following error: Cannot read property 'createDocumentFragment' of null.
Apparently, the this object is corrupted.
you can try this,
$(function($) {
$.fn.initPlugin1 = function() {
console.log('Initialized Plugin1');
return $(this);
};
});
$(function($) {
$.fn.initPlugin2 = function() {
console.log('Initialized Plugin2');
return $(this);
};
$.fn.callFunction = function(param) {
$(this).append(param);
};
});
(function($) {
$(document).ready(
function() {
$("#div1").initPlugin1(); //Run correctly
$("#div2").initPlugin2(); //Run correctly
$("#div1").initPlugin1().callFunction('function1');
$("#div2").initPlugin2().callFunction('function2');
});
})(jQuery);
Related
I am developing a JQuery plugin. I need to use OOP inside my plugin. However, the class not working as I expected. When I initiate a new instance of the class, it is only the first line of its code that is executing. What is wrong with this code and how to execute a constructor of this class on initiation?
(function ($) {
var FunClass;
FunClass = function () {
console.log("FunGlobal");
function FunClass() {
console.log("FunConstructor");
}
FunClass.prototype.letsFun = function () {
console.log("FunMethod");
}
}();
$.fn.fun = function () {
var funClass;
return this.each(function () {
funClass = new FunClass();
funClass.letsFun();
});
};
}(jQuery));
Here is the console output: Console Output
Thanks for help.
Seems you've forgot to return FunClass:
(function($) {
var FunClass;
FunClass = (function() {
console.log("FunGlobal");
function FunClass() {
console.log("FunConstructor");
}
FunClass.prototype.letsFun = function() {
console.log("FunMethod");
}
return FunClass; // you missed this line
})();
$.fn.fun = function() {
var funClass;
return this.each(function() {
funClass = new FunClass();
funClass.letsFun();
});
};
}(jQuery));
// Usage
$(function() {
$('body').fun();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
The below is not running and I am constantly getting the Uncaught TypeError: $(...) is not a function(anonymous function) # global.js:80j # jquery.min.js:2k # jquery.min.js:2' which is targeting the line with ' })(jQuery); called. I have tried reorganizing my external scripts in the <head> of the document, and tried using a JS lint, alas I continue to get this error.
$(document).ready(function() {
$(function($, undefined) {
$.widget("app.autocomplete", $.ui.autocomplete, {
_create: function() {
if(this.element.is("select")) {
var self = this;
this.original = this.element.hide();
this.element = $("<input/>").insertAfter(this.original);
this.options.source = function(request, response) {
var filter = $.ui.autocomplete.filter,
$options = self.original.find("option"),
result = $options.map(function() {
return $(this).val();
});
response(filter(result, request.term));
};
}
this._super("_create");
},
_destroy: function() {
this._super("_destroy");
this.element.remove();
this.original.show();
}
});
})(jQuery);
$(function() {
$("#autocomplete").autocomplete();
});
});
You don't need to pass jQuery variable to a newly created function because $ already has the reference to jQuery function. You got an error because function $ doesn't return a function when a function is passed as the first argument.
$(document).ready(function() {
$.widget("app.autocomplete", $.ui.autocomplete, {
_create: function() {
if(this.element.is("select")) {
var self = this;
this.original = this.element.hide();
this.element = $("<input/>").insertAfter(this.original);
this.options.source = function(request, response) {
var filter = $.ui.autocomplete.filter,
$options = self.original.find("option"),
result = $options.map(function() {
return $(this).val();
});
response(filter(result, request.term));
};
}
this._super("_create");
},
_destroy: function() {
this._super("_destroy");
this.element.remove();
this.original.show();
}
});
$(function() {
$("#autocomplete").autocomplete();
});
});
I need to know how is possible to get a plugin variable outside the plugin, to test it with some test framework.
So this is my simplified plugin:
(function ($) {
$.fn.extend({
myPlugin: function (argumentOptions) {
var defaults = {
image: 'img/default.png',
};
this.textSend = '';
var options = $.extend(defaults, argumentOptions);
var globalHere = this;
return this.each(function () {
obj.mouseup(function(e) {
globalHere.textSend = 'test';
});
});
}
});
})(jQuery);
I need to the variable this.textSend outside the plugin.
I have tried in this way:
$(document).ready(function(){
var testfield = $('.txt');
testfield.myPlugin({
image:"../img/twitter.png"
});
testfield.focus();
testfield.trigger($.Event( "mouseup"));
console.log($.fn.myPlugin.textSend);
});
but the console.log return me undefined
How can i get that variable outside?
Thanks
You will want to make sure you are returning this like so:
(function($) {
$.fn.extend({
myPlugin: function(argumentOptions) {
var self = this;
self.textSend = 'something';
self.inc = 0;
self.mouseup(function(e) {
self.textSend = 'new thing #' + self.inc;
self.inc++;
});
return self;
}
});
})(jQuery);
var instantiated = $('button').myPlugin({});
$('input').val(instantiated.textSend);
$('button').click(function(e) {
$('input').val(instantiated.textSend);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<label>Current textSend:</label>
<input />
<br/>
<button>Change textSend</button>
Hopefully will get you on the right track.
Update
Try new code.
You can store it inside the closed scope you created around your plugin and expose it through another function. Of course it'll need some refactoring, but this is the general idea:
(function ($) {
var whateverNameYouWant; //here
$.fn.extend({
myPlugin: function (argumentOptions) {
var defaults = {
image: 'img/default.png',
};
this.textSend = '';
whateverNameYouWant = this.textSend; //here
var options = $.extend(defaults, argumentOptions);
var globalHere = this;
return this.each(function () {
obj.mouseup(function(e) {
globalHere.textSend = 'test';
whateverNameYouWant = this.textSend; //here
});
});
}
});
$.extend({
getWhateverNameYouWant: function() {
return whateverNameYouWant;
}
})
})(jQuery);
var value = $.getWhateverNameYouWant();
At line console.log($.fn.myPlugin.textSend);
use testfield.textSend . now it has become proprty of selector via myplugin.
See my example below:
(function() {
// Initialize the socket & handlers
var connectToServer = function() {
var warbleSocket = new SockJS('http://url.com:5555/warble');
warbleSocket.onopen = function() {
clearInterval(connectRetry);
$('.connect-status')
.removeClass('disconnected')
.addClass('connected')
.text('Connected');
};
warbleSocket.onmessage = function(e) {
$('#warble-msg').text(e.data);
};
warbleSocket.onclose = function() {
clearInterval(connectRetry);
connectRetry = setInterval(connectToServer, 1000);
$('.connect-status')
.removeClass('connected')
.addClass('disconnected')
.text('Disconnected');
};
// Connect the text field to the socket
$('.msg-sender').off('input').on('input', function() {
warbleSocket.send($('.msg-sender input').val());
});
};
var connectRetry = setInterval(connectToServer, 1000);
connectRetry.warbleSocket.send("Hi there");
})();
What i would like is to be able to access warbleSocket.send from outside of connectRetry
How can i accomplish this?
to expose API from IIFE in JS:
...
return {
send: warbleSocket.send
}
})();
http://benalman.com/news/2010/11/immediately-invoked-function-expression/
I know java script doesn't have call by reference. So how can I solve this?
(function($){
$.fn.extend({
something: function(options) {
var Status;
var defaults = {
regex:/^([\u0600-\u06FF]|\s)*$/,
errortxt:"Invalid input",
emptytxt:"It should not be empty"
}
var options = $.extend(defaults, options);
$(this).bind('change', function () {
Status = true;
$(this).each(function() {
/*variables*/
var necessaryElement;
if (options.regex && options.errortxt && options.errorsection)
{
var filter = options.regex;
var $this = $(this);
var wrongMessage = options.errortxt;
var $errordiv = $("[ID$="+options.errorsection+"]");
} else{
console.log("Error : Not enough arguments for invoking something Plugin");
}
if (options.emptytxt)
{
var noMessage = options.emptytxt;
necessaryElement = true;
}
else
{
necessaryElement = false;
}
var elementvalue = $this.val();
/* Methods */
if (elementvalue != "" && necessaryElement) {
if (filter.test(elementvalue)){
$this.removeClass("error").addClass("ok");
$errordiv.fadeOut(300);
} else {
Status = false;
$this.removeClass("ok").addClass("error");
$errordiv.fadeIn(200);
$errordiv.text(wrongMessage);
}
} else if (elementvalue == "" && necessaryElement) {
Status = false;
$this.removeClass("ok").addClass("error");
$errordiv.fadeIn(200);
$errordiv.text(noMessage);
}
});
});
return Status;
}
});
})(jQuery);
and I call it in another js in this way:
var myarray=new Array();
myarray[0] = $('#selector').something({
regex:/^([\u0600-\u06FF]|\s)*$/,
// another options
});
$('#selector').change(function (){
alert (myarray[0]);
});
but it alerts undefined.
If I change var Status to var Status= true Then it always alerts true.
Can anyone help me? How I can change the code to return the desired Status?
Edit : Trying to be clearer.
Something() returns a value which is modified by change.
So when you call something you return the value unmodified.
Then you call change that will change the value, but it's not passed by reference in the array so it won't change anything.
You may want to use the data function available on JQuery objects for keeping data.
Here is a simplified version:
(function($){
$.fn.extend({
something: function(options) {
$(this).bind('change', function () {
$(this).data('status','true');
});
}
});
})(jQuery);
$(document).ready(function() {
var myarray=new Array();
myarray[0] = $('#selector').something({
regex:/^([\u0600-\u06FF]|\s)*$/
});
$('#selector').change(function (){
alert ($(this).data('status'));
});
});