Providing Options in jQuery Plugins
By Ryan Florence, published 2010-10-05
Part of the issue Thoughtful jQuery Plugin Development.
Nothing new or extraordinary here, but I run across enough jQuery plugins that don’t provide options to warrant writing an article about it. You can meet a lot more use cases for your plugin if you provide the developer with some options.
Here’s a plugin called disables
that I recently wrote for a project. It disables form elements based on the value of another, a checkbox by default.
(function($){
// add it to the jQuery prototype
$.fn.disables = function(selector, options){
// set options, YES!
options = $.extend({}, defaults, options);
// cache els
var els = $(selector);
// check if the attribute of my element matches what I'm looking for
// and then disable or enable the subject elements accordingly
var test = function(){
var isEqual = $(this).attr(options.attr) == options.expected;
els.attr('disabled', isEqual);
// fire an optional function for kicks
options.onChange.apply(this, [isEqual, els]);
};
// keep the chain alive and bind the events
return this.each(function(){
$(this).bind({
change: test,
keyup: test
});
});
};
// create some sane defaults, please and thank you
var defaults = {
attr: 'checked',
expected: true,
onChange: function(){}
};
})(jQuery);
Take a look at line 6. The extend
method merges the defaults
with the user supplied options
, giving precedence to the options. Now look at var defaults
on line 30. It’s important to choose sane defaults. By providing these defaults, and merging them with the developer’s options, the developer has the ability to use this plugin in a number of different scenarios.
// ex. 1
$('#my-checkbox').disables('.some-group-of-elements'); // uses defaults
// ex. 2
$('#my-input').disables('.group', {
attr: 'value',
expected: 'dog' // disables when a text input value is 'dog'
})
// ex. 3
$('#my-checkbox').disables('.group', {
onChange: function(isEqual, els){
els[((isEqual) ? 'add' : 'remove') + 'Class']('disabled'); // adds or removes disabled className
}
});
There’s something not right here …
Because the defaults are tucked behind a self-invoking anonymous function, this plugin is not as flexible and reusable as it could be. Imagine you wanted every instance of disables to behave like ex 3. You’d have to copy and paste that onChange
code block every time (lines 10-12). Or, you hack the source, and I really hate doing that
Instead, plugin developers could use the $.fn
namespace, let me show you what I mean here.