jQuery Plugin Development with the jQuery BoilerPlate
I gave a talk last night to the Fredericton Developer User Group on jQuery Fundamentals, Plugins and UI with Troy Coburn. During my talk I outlined plugin creation using the jQuery Boilerplate.
Check out the meeting page for more presentation resources. here
Please, rate my performance as a speaker on speakerrate.com
Since it was after the break, brains were starting to shutdown. Even unicorns couldn't keep folks awake, so I will post it here for those who weren't fully with it.
In my example, I created a simple plugin that added a drop shadow to an object. Also, I wanted to showcase having a plugin with multiple methods, as i was curious myself as to how to make this happen:
//Apply the plugin to a selection
$('h1').fdugshadow();
//Remove the plugin from the selection
$('h1').fdugshadow('undo');
In this case I wanted both a method to apply the shadow and another to remove it.
Here is the plugin that I came up with, it might be a little rough, but I think it got my point across. Comments are welcome and appreciated.
I have left the jQuery Boilerplate comments in and added some of my own.
I borrowed the multiple method code from Mark Dalgleish and from his fork of the jQuery Boilerplate on GitHub
// the semi-colon before function invocation is a safety net against concatenated
// scripts and/or other plugins which may not be closed properly.
;(function ( $, window, document, undefined ) {
// undefined is used here as the undefined global variable in ECMAScript 3 is
// mutable (ie. it can be changed by someone else). undefined isn't really being
// passed in so we can ensure the value of it is truly undefined. In ES5, undefined
// can no longer be modified.
// window and document are passed through as local variables rather than globals
// as this (slightly) quickens the resolution process and can be more efficiently
// minified (especially when both are regularly referenced in your plugin).
// Create the defaults once
var pluginName = 'fdugshadow',
defaults = {
copies: 5,
opacity: 0.1,
copyOffset: function(index) {
return {x: index, y: index};
}
};
// The actual plugin constructor
function Plugin( element, options ) {
this.element = element;
this.options = $.extend( {}, defaults, options) ;
this._defaults = defaults;
this._name = pluginName;
//our own custom local variable, to store the associated shadow copies.
this._shadows = [];
this.init();
}
//Additional Plugin Methods
$.extend(Plugin.prototype, {
init: function () {
// Place initialization logic here
// You already have access to the DOM element and the options via the instance,
// e.g., this.element and this.options
if(this._shadows.length > 0) return;
if($(this.element).attr('data-' + pluginName)) return;
var $originalElement = $(this.element);
for (var i = 0; i < this.options.copies; i++) {
var offset = this.options.copyOffset(i);
var shadowItem = $originalElement
.clone()
.css({
position: 'absolute',
left: $originalElement.offset().left + offset.x,
top: $originalElement.offset().top + offset.y,
margin: 0,
//zIndex: -1,
opacity: this.options.opacity
})
.attr('data-' + pluginName, true)
.appendTo('body');
this._shadows.push(shadowItem);
}
},
//remove all associated shadow objects.
undo : function(){
//if there are shadow objects associated with the current
// element, remove them.
for(var i = 0; i < this._shadows.length; i++){
$(this._shadows[i]).remove();
$(this.element).removeData('plugin_' + pluginName);
}
}
});
// A really lightweight plugin wrapper around the constructor,
// preventing against multiple instantiations and allowing any
// public function (ie. a function whose name doesn't start
// with an underscore) to be called via the jQuery plugin,
// e.g. $(element).defaultPluginName('functionName', arg1, arg2)
$.fn[pluginName] = function ( options ) {
var args = arguments;
if (options === undefined || typeof options === 'object') {
return this.each(function () {
if (!$.data(this, 'plugin_' + pluginName)) {
$.data(this, 'plugin_' + pluginName, new Plugin( this, options ));
}
});
} else if (typeof options === 'string' && options[0] !== '_' && options !== 'init') {
return this.each(function () {
var instance = $.data(this, 'plugin_' + pluginName);
if (instance instanceof Plugin && typeof instance[options] === 'function') {
instance[options].apply( instance, Array.prototype.slice.call( args, 1 ) );
}
});
}
}
})( jQuery, window, document );





