KEMBAR78
jQuery Namespace Pattern | KEY
namespace design
pattern for jQuery
     Diego Fleury - June 2010
  http://www.diegofleury.com.br
  http://twitter.com/diegofleury
what we know


design pattern default to write a selector based plugin

jQuery.fn.myPlugin = function() {
 return this.each(function() {
   // Do something with each element
 });
};
problems

• Name conflict
• Big plugins need other means to organize
• Communication and data share between
  smaller parts is harder
name conflict
validate, valid, removeAttrs, form, element,
resetForm, showErrors, required, remote,
minlength, maxlength, email, url, date, number

Generic names can cause headaches, change of
             plugins and desist
plugins grandes

• Bigger plugins must be sliced into parts
• Alternatively as in jQuery UI
      $(“foo”).bar(“myAction”, “myArgument”);


• Event-driven programming
   $(“foo”).trigger(“myAction”, [“myArgument”]);
communicaty of parts

• Contexts too 
permissive (globals)
• Exposure (no encapsulation)
• Over-parametrization
current options

• Continue as
• Use existing alternatives
• Namespace plugins
namespace plugins

• Expensive price to be paid
• Experimental solutions
• Far from natural
Object Augmentation


• Simple     var foo = {};
• Flexible   foo.bar = “baz”;
jQuery namespace
     pattern
$.fn.MyPlugin = function() {

     this.firstMethod = function() {
         return this.each(function() {
             "This method persists the namespaced chain";
         });
     };

     return this; // Returns the jQuery's modified object

};



$(“foo”).MyPlugin(); // returns namespaced jQuery object

$(“foo”).MyPlugin().firstMethod(); // returns namespaced jQuery object

$(“foo”).MyPlugin().firstMethod().hide(); // returns namespaced jQuery object

$(“foo”).firstMethod(); // Error: firstMethod is not a function
Stopping the
             namespace chain
$.fn.MyPlugin = function() {

     this.firstMethod = function() {
         return this.each(function() {
             "This method persists the namespaced chain";
         });
     };

     this.secondMethod = function() {                          This serves to specific
         return $(this.each(function() {                      cases where we want to
             "This method persists the namespaced chain";       force the use of the
         }));                                                    namespace to each
     };                                                              invocation
     return this; // Returns the jQuery's modified object

};



$(“foo”).MyPlugin().secondMethod().hide(); // Pure jQuery object

$(“foo”).MyPlugin().firstMethod().secondMethod(); // Pure jQuery object

$(“foo”).MyPlugin().secondMethod().firstMethod(); // firstMethod is not a function
optimizing
(function() {

    $.fn.MyPlugin = function() {

         this.firstMethod = parts.firstMethod;
         this.secondMethod = parts.secondMethod;

         return this; // Returns the jQuery's modified object

    };                                                           Now, we only reference
                                                                for functions already built
    var parts = {                                                    by the JavaScript
         firstMethod: function() {                                interpreter to execute
             return this.each(function() {                         the outer anonymous
                 "This method persists the namespaced chain";            function
             });
         },

         secondMethod: function() {
             return $(this.each(function() {
                 "This method persists the namespaced chain";
             }));
         }

    };

})();
global options
(function() {

    var parts, globalOptions = {foo: “default”};
                                                           This can be very useful
    $.fn.MyPlugin = function(globalConfig) {

         $.extend(globalOptions, globalConfig);

         this.firstMethod = parts.firstMethod;
         this.secondMethod = parts.secondMethod;

         return this; // Returns the jQuery's modified object

    };

    parts = {

         firstMethod: function(config) {

              var options = $.extend({}, globalOptions, config);

              return this.each(function() {
                  "This method persists the namespaced chain";
              });
         },

         secondMethod: function() { /* ... */ }

    };                                               $(“foo”)
                                                         .MyPlugin({foo: “global”})
})();                                                        .firstMethod({foo: “especific”});
many methods
(function() {

    var parts, globalOptions = {foo: “default”};         I recommend doing this
    $.fn.MyPlugin = function(globalConfig) {               only when there are
         $.extend(globalOptions, globalConfig);
                                                            many methods. This
                                                          operation is expensive.
         $.extend(this, parts);

         return this; // Returns the jQuery's modified object

    };

    parts = {

         firstMethod: function(config) {

              var options = $.extend({}, globalOptions, config);

              return this.each(function() {
                  "This method persists the namespaced chain";
              });
         },

         secondMethod: function() { /* ... */ }

    };

})();
Advantages

• Organization
• Simple to employ
• Natural
• Global parameterization
  “This is nice - it's a simple pattern to employ, for sure.”
                                                    - John Resig

jQuery Namespace Pattern

  • 1.
    namespace design pattern forjQuery Diego Fleury - June 2010 http://www.diegofleury.com.br http://twitter.com/diegofleury
  • 2.
    what we know designpattern default to write a selector based plugin jQuery.fn.myPlugin = function() { return this.each(function() { // Do something with each element }); };
  • 3.
    problems • Name conflict •Big plugins need other means to organize • Communication and data share between smaller parts is harder
  • 4.
    name conflict validate, valid,removeAttrs, form, element, resetForm, showErrors, required, remote, minlength, maxlength, email, url, date, number Generic names can cause headaches, change of plugins and desist
  • 5.
    plugins grandes • Biggerplugins must be sliced into parts • Alternatively as in jQuery UI $(“foo”).bar(“myAction”, “myArgument”); • Event-driven programming $(“foo”).trigger(“myAction”, [“myArgument”]);
  • 6.
    communicaty of parts •Contexts too permissive (globals) • Exposure (no encapsulation) • Over-parametrization
  • 7.
    current options • Continueas • Use existing alternatives • Namespace plugins
  • 8.
    namespace plugins • Expensiveprice to be paid • Experimental solutions • Far from natural
  • 9.
    Object Augmentation • Simple var foo = {}; • Flexible foo.bar = “baz”;
  • 10.
  • 11.
    $.fn.MyPlugin = function(){ this.firstMethod = function() { return this.each(function() { "This method persists the namespaced chain"; }); }; return this; // Returns the jQuery's modified object }; $(“foo”).MyPlugin(); // returns namespaced jQuery object $(“foo”).MyPlugin().firstMethod(); // returns namespaced jQuery object $(“foo”).MyPlugin().firstMethod().hide(); // returns namespaced jQuery object $(“foo”).firstMethod(); // Error: firstMethod is not a function
  • 12.
    Stopping the namespace chain $.fn.MyPlugin = function() { this.firstMethod = function() { return this.each(function() { "This method persists the namespaced chain"; }); }; this.secondMethod = function() { This serves to specific return $(this.each(function() { cases where we want to "This method persists the namespaced chain"; force the use of the })); namespace to each }; invocation return this; // Returns the jQuery's modified object }; $(“foo”).MyPlugin().secondMethod().hide(); // Pure jQuery object $(“foo”).MyPlugin().firstMethod().secondMethod(); // Pure jQuery object $(“foo”).MyPlugin().secondMethod().firstMethod(); // firstMethod is not a function
  • 13.
    optimizing (function() { $.fn.MyPlugin = function() { this.firstMethod = parts.firstMethod; this.secondMethod = parts.secondMethod; return this; // Returns the jQuery's modified object }; Now, we only reference for functions already built var parts = { by the JavaScript firstMethod: function() { interpreter to execute return this.each(function() { the outer anonymous "This method persists the namespaced chain"; function }); }, secondMethod: function() { return $(this.each(function() { "This method persists the namespaced chain"; })); } }; })();
  • 14.
    global options (function() { var parts, globalOptions = {foo: “default”}; This can be very useful $.fn.MyPlugin = function(globalConfig) { $.extend(globalOptions, globalConfig); this.firstMethod = parts.firstMethod; this.secondMethod = parts.secondMethod; return this; // Returns the jQuery's modified object }; parts = { firstMethod: function(config) { var options = $.extend({}, globalOptions, config); return this.each(function() { "This method persists the namespaced chain"; }); }, secondMethod: function() { /* ... */ } }; $(“foo”) .MyPlugin({foo: “global”}) })(); .firstMethod({foo: “especific”});
  • 15.
    many methods (function() { var parts, globalOptions = {foo: “default”}; I recommend doing this $.fn.MyPlugin = function(globalConfig) { only when there are $.extend(globalOptions, globalConfig); many methods. This operation is expensive. $.extend(this, parts); return this; // Returns the jQuery's modified object }; parts = { firstMethod: function(config) { var options = $.extend({}, globalOptions, config); return this.each(function() { "This method persists the namespaced chain"; }); }, secondMethod: function() { /* ... */ } }; })();
  • 16.
    Advantages • Organization • Simpleto employ • Natural • Global parameterization “This is nice - it's a simple pattern to employ, for sure.” - John Resig