Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

jQuery Plugin Namespace

Tags:

jquery

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); 
like image 957
MotionGrafika Avatar asked Oct 08 '09 13:10

MotionGrafika


2 Answers

(function($) {     $.fn.amtec = function () {         var jq = this;         return {             foo1: function(){                 return jq.each(function(){});             },              foo2: function(){                 return jq.each(function(){});            }        }     }; })(jQuery); 
like image 52
Alex Gyoshev Avatar answered Sep 23 '22 18:09

Alex Gyoshev


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.

like image 20
Milosz Avatar answered Sep 20 '22 18:09

Milosz