jQuery Plugin Patterns
So, you've tried out jQuery Boilerplate or written a few of your own plugins before. They work to a degree and are readable, but you're interested in learning if there are better ways your plugin can be structured.
Perhaps you're just looking for something that works better with the jQuery UI Widget factory, RequireJS or has built-in support for Publish/Subscribe. This repo hopes to provide a number of alternative boilerplates for kick-starting your jQuery plugin development catered towards the intermediate to advanced developer.
This project won't seek to provide implementations for every possible pattern, but will attempt to cover popular patterns developers often use in the wild.
Patterns
- A lightweight start: perfect as a generic template for beginners and above, uses a basic defaults object, simple constructor for assigning the element to work with and extending options with defaults and a lightweight wrapper around the constructor to avoid issues with multiple instantiations
- Widget factory: for building complex, stateful plugins based on object-oriented principles. The majority of jQueryUI heavily relies on the widget factory as a base for components and this template covers almost all supported default methods including triggering events
- Widget factory + RequireJS: for wrapping jQueryUI widgets inside RequireJS compatible modules. Also demonstrates very basic widget templating
- Widget factory for jQuery mobile - demonstrating best practices for building mobile widgets, includes many of the same concepts as the widget factory boilerplate, but also JQM specific usage advice/tips in the comments
- Namespaced pattern: to avoid collisions and improve code organization when working with components under another namespace
- Best options: globally/Per-call overridable options for greater option customization, based on Ben Almans pluginization talk
- Custom events (Publish/Subscribe): for better application decoupling. Uses the Widget factory, but could be applied to the generic template
- Extend pattern: Extended options
- Non Widget-factory widget: if you wish to stay away from the widget factory. Uses Ben Alman’s simplewidget including coverage for creation, instantiation and other best practices that may be helpful
- Prototypal inheritance pattern: use a bridge to generate a plugin from an object (literal). Useful for code organization, readability, functionality heavily based around DOM element selection
- Universal Module Definition pattern: create AMD and CommonJS compatible plugin modules which are compatible with a number of different script loaders. You may also be interested in the UMD project.
Principles of Writing Consistent, Idiomatic JavaScript
You may checkout this link (https://github.com/rwaldron/idiomatic.js)
Style Manifesto for jQueryfied Modules
Just like in Idiomatic JavaScript Style Manifesto we will summarize some examples, how you can build up your JavaScript or better jQuery modules.
- Module/Constructor/Factories
1.1. AMD compatible factory
If you use stricly jQuery loaded by RequireJS you can do this:
// the usual definition how to define a RequireJs compatible module
define(["jquery", "jqueryui"], function ($) {
$.fn.extend({
pluginName: function( options ) {
this.defaultOptions = {};
var settings = $.extend({}, this.defaultOptions, options);
return this.each(function() {
var $this = $(this);
});
}
});
});
1.2. AMD and CommonJS compatible module factory
But if you want to use your modules also in other projects, where RequireJS is not available, you can add this factory pattern to provide your module
// Examples of a AMD and CommonJS compatible module with a prefaced factory
// Hint: The semi-colon before the function invocation is a safety net against
// concatenated scripts and/or other plugins that are not closed properly.
;(function (factory) {
if (typeof define === 'function' && define.amd) {
// AMD
define(['jquery'], factory);
} else if (typeof exports === 'object') {
// CommonJS
factory(require('jquery'));
} else {
// Browser globals
factory(jQuery);
}
}(function ($, window, document){
$.fn.extend({
pluginName: function( options ) {
this.defaultOptions = {};
var settings = $.extend({}, this.defaultOptions, options);
return this.each(function() {
var $this = $(this);
});
}
});
});
}()));
Further reading
More information about the patterns in this repo can be found in Learning JavaScript Design Patterns.
Contributing
If you have ideas for improvements that can be made to patterns currently in the repo, please feel free to create a new issue for discussion or send a pull request upstream. The same can be said about new patterns you wish to propose being added; for the sake of limiting confusion and complexity, I would ideally like to keep the number of overall patterns in the repo, but there are plans to separate these out into folders based on concerns.
Team
jQuery Patterns was made with love by these people and a bunch of awesome contributors.
| --- | --- | --- | --- | --- | --- | --- Addy Osmani | Zeno Rocha
Credits
Thanks to @peol, @ajpiano, @mathias, @cowboy, @dougneiner and others for their previous work (or tips) in this area. Some of this work is used as a basis for further improvements.