Using namespaces with jQuery widgets
Creating plugins for jQuery is a relatively straightforward task, however poorly named plugins can conflict with one another (or even with core jQuery functionality). I have seen numerous attempts at solving this problem which each have their advantages and disadvantages.
My take on this is to define widgets in a completely separate namespace and then refer to
them using a single jQuery plugin widget
. This plugin depends upon the following jQuery
variant of my $namespace
function from here.
/*!
* (c) 2010-2011 Rotorz Limited. All rights reserved.
* License: BSD
* Author: Lea Hayes
* Website: http://leahayes.co.uk
*/
$global = window;
$namespace = function(ns, extension) {
if (ns == '') {
return $global;
}
if (typeof ns === 'string') {
var fragments = ns.split('.');
var node = $global;
for (var i = 0; i < fragments.length; ++i) {
var f = fragments[i];
node = !node[f] ? (node[f] = {}) : node[f];
}
}
else {
node = ns;
}
if (extension) {
$.extend(node, extension);
}
return node;
};
Each widget can be defined as a class within a vendor specific namespace (like my
for
example) using something like the following:
$namespace('my').SpecialWidget = function(options) {
this.color = options.color;
};
// Invoked automatically when element is attached to object.
my.SpecialWidget.prototype.attach = function(element) {
this.element = element;
element.css('color', this.color);
};
my.SpecialWidget.prototype.enable = function() {
this.element.css('opacity', 1.0);
};
my.SpecialWidget.prototype.disable = function() {
this.element.css('opacity', 0.5);
};
The following jQuery widget
plugin will then make the above work in a fairly standard
jQuery fashion:
(function($) {
$.fn.widget = function(name, a, b) {
if (!name) return this.data('widget');
this.each(function() {
var widget;
if (message === 'init') {
a = $namespace(a);
widget = new a(b || {});
widget.attach(this);
this.data('widget', widget);
}
else {
widget = this.data('widget');
widget[message].apply(widget, Array.prototype.slice.call(arguments, 1));
}
});
return this;
};
})(jQuery);
The special widget can then be used as follows:
// Attach widget to element.
$('div.my-special-widget')
.widget('init', my.SpecialWidget, { color: 'red' });
// Disable widget.
$('div.my-special-widget')
.widget('disable');
// Interact with widget object directly.
var widget = $('div.my-special-widget').widget();
widget.enable();