Use Your Fn jQuery Namespace
By Ryan Florence, published 2010-10-05
Part of the issue Thoughtful jQuery Plugin Development.
Every plugin gets a namespace on the jQuery prototype. If you keep all of your functions, methods, and variables scoped inside the jQuery.fn
function, others can’t extend or alter the functionality of your plugin. Instead, take advantage of your block on jQuery street and let other developers take advantage of your plugin.
Hang your members on your $.fn namespace
If we make a tiny change to the plugin discussed in Providing options in jQuery plugins, we make it ridiculously more flexible. Pay attention to how the defaults are assigned in this example.
// ex. 7
(function($){
$.fn.disables = function(selector, options){
options = $.extend({}, $.fn.disables.defaults, options);
// ... blah blah blah
};
$.fn.disables.defaults = {
attr: 'checked',
expected: true,
onChange: function(){}
};
})(jQuery);
I’ve placed the defaults on $.fn.disables.defaults
instead of just var defaults
this time. This object oriented approach exposes the defaults to the developer. Now s/he can change the default behavior of all instances with one block of code, rather than having to do it with every instance.
Consider that across my application I want to add the “disabled” class to the elements when they are disabled. If I var
-ed my defaults the developer would have to do this all over the place:
$('#my-checkbox').disables('.group', {
onChange: function(isEqual, els){
els[((isEqual) ? 'add' : 'remove') + 'Class']('disabled'); // adds or removes disabled className
}
});
$('#my-other-checkbox').disables('.group', {
onChange: function(isEqual, els){
els[((isEqual) ? 'add' : 'remove') + 'Class']('disabled'); // adds or removes disabled className
}
});
// all over the place
Some of you are saying “or just store it in a function somewhere.” You’re right, but I still have to define the onChange
for each instance. Others might even reach for the source and change the default onChange function.
Since this plugin is more thoughtful, and exposes the defaults on it’s effin’ namespace, I have a better option. I can just change the default without hacking the plugin’s source code.
Overriding default behavior is easy, now
$.fn.disables.defaults.onChange = function(isEqual, els){
els[((isEqual) ? 'add' : 'remove') + 'Class']('disabled'); // adds or removes disabled className
};
Now I can support some styling in browsers that don’t support the :disabled
CSS selector with 3 measly lines of code. If I had 20 instances of disables
(which I did), I would have had 4 more lines of code per instance, or 80 lines total of identical code–what a waste. Additionally, I don’t need to worry about forgetting to add the option to an instance here or there. If you’re still not convinced, imagine, now, that we want to change the disabled
className to something else, or change the default onChange
later. Find and replace only works for a while.
This tip doesn’t just apply to options either. You can put any number of your plugin’s methods on it’s effin’ namespace, giving developers a place to make adjustments without poking your code with a stick.
While this is a huge step in the right direction, if you start hanging everything off of jQuery.fn.namespace.member
or adding every method you use as an option with jQuery.fn.namespace.defaults.member
, the code starts to suffer from readability and non-brevity. There’s another way to author a plugin: Use objects and then simply add them to the jQuery prototype