The following is a great starting boilerplate template to use when creating a jQuery plugin. It contains all the major pieces you will need to build out and provide functionality for your plugins. I’ve used it to create many plugins and it has been a working progress for over two years as such I’ve worked out many kinks in it allowing me to greatly speed up my development.
Resources
- GitHub page where you can get a clean version of the boilerplate
- GitHub Page for various plugin based on the boilerplate
- The Ultimate Guide to Writing jQuery Plugins
// keep all your code in a closure.
(function($)
{
// make your plugin names unique.
$.fn.wBoiler = function(option, settings)
{
// check if user is setting/getting properties manually after plugin creation.
if(typeof option === 'object')
{
settings = option;
}
else if(typeof option === 'string')
{
var values = []; // return 0 or more values if getting settings.
// even when setting/getting values we don't want to break jQuery method
// chaining, so run what we need to and return the element except when
// returning values in which case we will return 0 or more values.
var elements = this.each(function()
{
var data = $(this).data('_wBoiler');
if(data)
{
// we can create any special cases and call necessary functions.
if(option === 'reset') { data.reset(); }
else if(option === 'theme') { data.setTheme(settings); }
else if($.fn.wBoiler.defaultSettings[option] !== undefined)
{
if(settings !== undefined) { data.settings[option] = settings; }
else { values.push(data.settings[option]); }
}
}
});
if(values.length === 1) { return values[0]; }
if(values.length > 0) { return values; }
else { return elements; }
}
// iterate through all elements and return them to maintain jQuery method chaining.
return this.each(function()
{
var $elem = $(this);
// create a local copy of settings extending the defaults
// this ensures that only values for current element are changed.
var $settings = $.extend({}, $.fn.wBoiler.defaultSettings, settings || {});
// create a plugin object
var boiler = new Boiler($settings, $elem);
// typically some generation code for the plugin will be run around here.
var $el = boiler.generate();
// run some code here, try to keep as much of the main code in the prototype
// methods as possible focus on just setting up the plugin and calling proper
// methods from here.
$('body').append($el);
// store the object for later reference
$elem.data('_wBoiler', boiler);
});
}
// provide default settings, keeping it one spot like this makes it much
// easier for developers to understand how your plugin works. It also makes
// it simpler for developers to modify the defaults like so:
// $.fn.wBoiler.defaultSettings.theme = 'green';
$.fn.wBoiler.defaultSettings = {
theme : 'red',
onClick : null
};
// create our plugin "class"
// this will store the unique individual properties for each instance of the plugin
function Boiler(settings, $elem)
{
this.boiler = null;
this.settings = settings;
this.$elem = $elem;
return this;
}
// prototype the plugin class
// this will contain methods shared amongst all plugin instances
// DO NOT keep any unique plugin properties here
Boiler.prototype =
{
generate: function()
{
// set local reference of this
// this will be important when using in other closures like event closures
var $this = this;
// return the plugin incase it has already been created
if($this.boiler) return $this.boiler;
// write some code
$this.boiler = $('<div class="_wBoiler_holder"></div>');
$this.boiler
.click(function()
{
$this.boiler.html('you clicked me!');
if($this.settings.onClick) $this.settings.onClick.apply($this, []);
})
.mousedown(function() //works on mobile too
{
$this.boiler.html('you mouse downed me!');
});
$this.bindMobile($this.boiler);
$this.setTheme($this.settings.theme);
$this.reset();
// return the plugin object (sometimes this might be the elment itself)
return $this.boiler;
},
setTheme: function(theme)
{
this.settings.theme = theme;
this.boiler.attr('class', '_wBoiler_holder _wBoiler_' + this.settings.theme);
},
reset: function()
{
this.boiler.html('click me');
},
// bind mobile events to an element
bindMobile: function($el, preventDefault)
{
$el.bind('touchstart touchmove touchend touchcancel', function ()
{
var touches = event.changedTouches, first = touches[0], type = "";
switch (event.type)
{
case "touchstart": type = "mousedown"; break;
case "touchmove": type = "mousemove"; break;
case "touchend": type = "mouseup"; break;
default: return;
}
var simulatedEvent = document.createEvent("MouseEvent");
simulatedEvent.initMouseEvent(
type, true, true, window, 1,
first.screenX, first.screenY, first.clientX, first.clientY,
false, false, false, false, 0/*left*/, null
);
first.target.dispatchEvent(simulatedEvent);
if(preventDefault) event.preventDefault();
});
}
}
})(jQuery);
10 Coding Tips to Write Superior jQuery Plugins10 Simple Guidelines for Writing jQuery Plugins
16 Step jQuery Plugin Development Lifecycle
Here’s the linted version:
https://gist.github.com/7461f96601a12b698724
Thanks Thomas for linting.
I would suggest that default settings, rather than being privately scoped, get moved to $.fn.wTooltip.defaultSettings to allow for global user overrides.
Thanks for writing this down and sharing it. Much clearer than previous versions of this concept I’ve seen.
Consider using -
$.fn.wTooltip.defaultSettings = {};
This way if I want to override the defaults for every call, I only have to do it once.
$.wTooltip.defaultSettings.color = ‘white’;
$(‘div’).wTooltip({ color: ‘white’ });
$(‘ul’).wTooltip({ color: ‘white’ });
$(‘li’).wTooltip({ color: ‘white’ });
I know it’s not as pretty as using a simple var statement up top.
Not to be a colossal pedant, but should:-
else if(typeof option == \'string\')
Use === rather than == for consistency?
Unless I’m missing something
Just wanted to let you know I used your boilerplate for my first jQuery plugin at https://github.com/indyarmy/jQuery.awesomeCloud.plugin/
Worked great! Thanks!
take a look https://github.com/zenorocha/jquery-boilerplate
This is almost perfect boilerplate but it does not provide a way of creating public methods for Jquery Plug-in; the Jquery Plug-In authoring guide does mention how it should be done. Preserving the context and calling private methods of the widget from the public method is non trivial exercise (and something I still haven’t been able to get right).
Used your boilerplate to make my first simple jQuery plug-in awhile back. It was a great way to learn plug-in development.
Thanks for sharing it.
https://github.com/ericrallen/jq-def-text (credits for your boilerplate are in the documentation)