How do I create a jQuery plugin so that I can use namespaces in my plugin ?
$("#id1").amtec.foo1(); $("#id1").amtec.foo2();
None of these seem to work.
(function($) { var amtec = { $.fn.foo1 : function(){ return this.each(function(){}); }, $.fn.foo2 : function(){ return this.each(function(){}); } }; })(jQuery);
(function($) { $.fn.amtec = function(){ var foo1 = function(){ return this.each(function(){}); }; var foo2 = function(){ return this.each(function(){}); }; } })(jQuery);
(function($) { $.fn.amtec = function () { var jq = this; return { foo1: function(){ return jq.each(function(){}); }, foo2: function(){ return jq.each(function(){}); } } }; })(jQuery);
I know I'm almost three years late to the party, but hopefully future readers of this question can benefit from my answer. The answer by GSto looks great from a jQuery plugin design standpoint, but has one small issue: calling mynamespace()
clobbers the returned jQuery instance with new methods. Here is an example of that being an issue:
$myDiv = $('.mydiv'); $myDiv.mynamespace().height(); // this will be `height' from mynamespace $myDiv.height(); // this will STILL be `height' from mynamespace // because it has overwritten $myDiv.height
The chosen answer does not have this issue because there amtec()
is not a jQuery instance and is instead an object that calls its methods with the jQuery instance as context. I have taken concepts from both answers and written the namespace plugin below:
(function($) { $.namespace = function(namespaceName, closures) { if ($.fn[namespaceName] === undefined) { $.fn[namespaceName] = function executor(context) { if (this instanceof executor) { this.__context__ = context; } else { return new executor(this); } }; } $.each(closures, function(closureName, closure) { $.fn[namespaceName].prototype[closureName] = function() { return closure.apply(this.__context__, arguments); }; }); }; })(jQuery);
Example usage:
$.namespace('milosz', { redify: function() { $(this).css('color', '#ff0000'); }, greenify: function() { $(this).css('color', '#00ff00'); } }); $.namespace('milosz', { blueify: function() { $(this).css('color', '#0000ff'); } }); $('.mydiv').milosz().redify(); // The HTML elements with class `mydiv' are now red
The code uses some pretty low-level details of JavaScript that are well-explained by John Resig's Advanced JavaScript tutorial, but loosely speaking what is happening in the example is this:
When milosz
(internally $.fn[namespaceName]
) is called, this
points to the jQuery
instance returned by $('.mydiv')
. Hence, the if
statement falls through to the else
block and the constructor version of milosz
is called (referred-to internally as executor
for reasons that are about to become apparent). The constructor is passed a single parameter: this
, a pointer to the jQuery
the instance that is going to be the execution context for all members of the milosz
namespace. We enter back into the if
statement, this time executing the first block, wherein the passed-in jQuery
instance is stored in a member variable called __context__
(which hopefully has a low chance of being overwritten). The constructed object is returned, complete with a reference to the original jQuery
instance and any wrappers added to its prototype by invocations of $.namespace
. These wrappers simply execute the methods passed into the milosz
namespace with the original jQuery
object as context, as happens when redify
is executed.
Bah, I know it's a mouthful, anyway the point is it works like the accepted answer but looks like the jQueryish answer, which to me is the best of both worlds.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With