Description

If you are not using the jQueryUI Widget Factory to build stateful jQuery widgets, you might feel lost about how to properly organize your jQuery plugin code. jqBoilerplate uses the Revealing Module Design Pattern to organize and provide structure to a stateful jQuery widget.

The Code

//      jqBoilerPlate - jQuery Stateful Plugin Boilerplate


//		(c) 2012 Greg Franko

//		jqBoilerplate may be freely distributed
//		under the MIT license

/* 
Immediately-Invoked Function Expression (IIFE) [Ben Alman Blog Post]
(http://benalman.com/news/2010/11/immediately-invoked-function-expression/)
that locally passes in `jQuery`, the `window` object, the `document` object,
and an `undefined` variable.  The `jQuery`, `window` and `document` objects 
are passed in locally to improve performance (JavaScript first searches for 
a variable match within the local variables set before searching the global 
variables set).  All of the global variables are also passed in locally to 
be minifier friendly. `undefined` can be passed in locally, because it is not
a reserved word in JavaScript
*/
(function ($, window, document, undefined) {

    /*
    ECMAScript 5 Strict Mode: [John Resig Blog Post]
    (http://ejohn.org/blog/ecmascript-5-strict-mode-json-and-more/)
    */
    "use strict";

    //Plugin name (Change this)
    var pluginName = "defaultName",

    //Plugin version number (Change this)
    pluginVersion = "0.1.0",

    //Plugin Object
    // ------------
    //		Holds all of the plugin logic

    /*
    **Convention:** Methods or properties starting with `_` are meant to be 
    private. You can make them public by including them in the return statement
    at the bottom of the Constructor
    */
    Plugin = function(element, options, dataName) {

        //Self (Add to this)
        // -----------------
        //		Stores all of the `Plugin` object instance variables
        var self = {

            //The DOM element that called the plugin
            element: element,

            //The DOM element that called the plugin (wrapped in a jQuery object)
            $element: $(element),

            //The plugin options object
            options: options,

            //The name of the plugin
            dataName: dataName
        },

        //_Callback Support
        // ----------------
        //      Calls the function passed in as the parameter
        _callbackSupport = function(callback) {

            //Checks to make sure the parameter passed in is a function
            if($.isFunction(callback)) {

                /*
                Calls the method passed in as a parameter and sets the context to 
                the `Plugin` object, which is stored in the jQuery `data()`
                method.  This allows for the `this` context to reference the 
                Plugin API Methods in the callback function. The original element 
                that called the plugin(wrapped in a jQuery object) is the only 
                parameter passed back to the callback
                */
                callback.call(self.$element.data(dataName), self.$element);
            }

            //Maintains chainability
            return this;
        },  

        //_Events (Add to this)
        // --------------------
        //      Adds plugin event handlers
        _events = function() {

            //Maintains chainability
            return this;
        },

        //Get Option
        // ---------
        //      Returns a single plugin option
        getOption = function(key, callback) {

            /*
            Returns the plugin option if it exists, and returns undefined if the 
            option does not exist
            */
            return self.options[key] || undefined;    
        },

        //Get Options
        // ----------
        //      Returns all of the plugin options      
        getOptions = function(callback) {
        
            //Returns an object of all of the plugin's options
            return self.options || undefined;
        },

        //Set Option
        // ---------
        //      Replaces a single existing plugin option
        setOption = function(key, value, callback) {

            //Makes sure a string is passed in
            if(typeof key === "string") {
                //Sets the plugin option to the new value provided by the user
                self.options[key] = value;    
            }
            //Provides callback function support
            _callbackSupport(callback);

            //Maintains chainability
            return this;
        },

        //Set Options
        // ----------
        //      Accepts an object to replace plugin options properties
        setOptions = function(newOptions, callback) {
        
            //If the passed in parameter is an object literal
            if($.isPlainObject(newOptions)) {
        
                /*
                Uses the jQuery `extend` method to merge the user specified 
                options object with the self.options` object to create a new 
                object.  The options variable is set to the newly created 
                object.
                */
                self.options = $.extend({}, self.options, newOptions);
            }
  
            //Provide callback function support
            _callbackSupport(callback);

            //Maintains chainability
            return this;
        },

        //Disable (Add to this)
        // --------------------
        //      Disables the DOM element created by the plugin
        disable = function(callback) {
        
            //Provides callback function support
            _callbackSupport(callback);
        
            //Maintains chainability
            return this;
        },

        //Enable (Add to this)
        // -------------------
        //      Enables the DOM element created by the plugin
        enable = function(callback) {
        
            _callbackSupport(callback);
        
            //Maintains chainability
            return this;
        },

        //Destroy (Add to this)
        // --------------------
        //      Brings the page back to it's intial state
        destroy = function(callback) {
        
            //Provides callback function support
            _callbackSupport(callback);
        
            //Maintains chainability
            return this;
        },

        //Create (Add to this)
        // -------------------
        //      Constructs the plugin
        create = function(callback) {

            //Provides callback function support
            _callbackSupport(callback);
              
            //Maintains chainability
            return this;
        };

        //Public API (Add to this if you create custom public methods/properties)
        // -----------------------
        //		All of these methods or properties are public
        
        return {
            
            //**version**: The current version of the plugin
            version: pluginVersion,

            //**self**: Object holding all of the plugin instance properties
            self: self,

            /*
            **getOption**: Returns a single plugin option.
            Accepts one parameter (String key)
            */
            getOption: getOption,

            /*
            **getOptions**: Returns an object containing all of the current 
            plugin options
            Does not accept parameters
            */
            getOptions: getOptions,

            /*
            **setOption**: Sets a single plugin option.
            Accepts two parameters (String key, value)
            */
            setOption: setOption,

            /*
            **setOptions**: Sets or adds new plugin option settings.
            Accepts one parameter (Object newOptions)
            */
            setOptions: setOptions,

            /*
            **disable**: Disables the DOM element associated with the plugin
            Does not accept parameters 
            */
            disable: disable,

            /*
            **enable**: Enables the DOM element associated with the plugin
            Does not accept parameters
            */
            enable: enable,

            /*
            **destroy**: Removes all plugin events, data, and DOM elements
            Does not accept parameters
            */
            destroy: destroy,

            /*
            **create**: Constructs the plugin
            Does not accept parameters
            */
            create: create

            };
        };

        //PLUGIN DEFINITION
        // ----------------
       //		Adds the plugin method to the jQuery prototype object
        $.fn[pluginName] = function (options) {
        
            //Maintains chainability for all calling elements
            return this.each(function () {
        
                /*
                Stores the calling element and the data name into local variables,
                instantiates the plugin variable (which will hold the Plugin 
                object), and instantiates an empty object literal (which will be 
                used to dynamically create a jQuery custom pseudo selector)
                */
                var element = $(this), plugin, dataName = pluginName, obj = {};
        
                /* 
                Returns early if the calling element already has a plugin 
                instance associated with it inside of the jQuery `data` method
                */
                if ($.data(element[0], dataName)) { 
        
                    return;
        
                }
        
                /*
                Uses the jQuery `extend` method to merge the user specified 
                options object with the `self.options`object to create a new 
                object. The options variable is set to the newly created 
                object.
                */
                options = $.extend({}, $.fn[pluginName].options, options);
            
                // Instantiates a new `Plugin` object and creates the plugin
                plugin = new Plugin(this, options, dataName).create();
            
                /*
                Stores the new `Plugin` object in the calling element's 
                jQuery `data` method
                */
                $.data(element[0], dataName, plugin);

                /*
                Uses the name of the plugin to create a dynamic property 
                of an empty object literal
                */
                obj[pluginName] = function(elem) {
                    /*
                    Returns all DOM elements that have jQuery `data()`
                    created by the plugin
                    */
                    return $(elem).data(dataName) !== undefined;
                };

                //Adds custom jQuery pseudo selectors
                $.extend($.expr[":"], obj); 
                //end extending jQuery pseudo selectors
        
            }); //end return statement

        };  //end plugin
    
    //Default plugin Options (Add to this)
    // -----------------------------------
    //		Adds default options to the plugin
    $.fn[pluginName].options = {
   
    };

//      End of Plugin
}(jQuery, window, document));
//passes in the `jQuery`, `window`, and `document` global objects locally

The Revealing Module Pattern

The Revealing Module Pattern uses closures to allow both private and public plugin properties and methods. Privacy is very useful when you want to provide a public API while also hiding certain plugin functionality from a user.


Notable Features

-Provides a ready-made public API and private methods (All private methods are preceded with an underscore)

-Protects against multiple plugin instances being created

-Provides a custom jQuery pseudo-selector for your plugin

-Default plugin options can be retrieved and set at any time using the 4 completed methods provided (getOption(), getOptions(), setOption(), and setOptions)

-Callback function and chaining support are built-in

-A solution for dealing with the context of the this keyword (all instance properties are inside of an object literal called self)

-Common methods used with stateful plugins are included (events, disable, enable, destroy, create). These methods are blank, since your custom jQuery plugin logic will go here.


Getting Started

1. Download jq-boilerplate.js

2. Change the pluginName and pluginVersion variables at the top of the file to your jQuery plugin name and version.

3. Write the custom logic for the create(), destroy(), enable(), disable(), and _events().

4. You just created a stateful jQuery widget! Celebrate!


How to Use Your New jQuery Plugin

Call your plugin method on a jQuery object. This example is assuming your plugin is named coolPlugin, so replace the name coolPlugin with the name of your plugin.

	//Creating your plugin!
    var plugin = $("#someElement").coolPlugin().data("coolPlugin");

Test out your new jQuery pseudo selector

	/*
	The jQuery pseudo selector that was created for the coolPlugin that tells you which
	elements have been called by the coolPlugin
	*/
	$(":coolPlugin").each(function() {
        console.log(this.id);
    });

Set options when the plugin is created or after the plugin is created

Setting an option when the plugin is created
	//Creating your plugin and setting options!
    var plugin = $("#someElement").coolPlugin({ someOption: false }).data("coolPlugin");
Setting an option after the plugin is created
	//Creating your plugin!
    var plugin = $("#someElement").coolPlugin().data("coolPlugin");

    //Setting an option after the plugin is created!
    plugin.setOption("someOption", false);

Frequently Asked Questions

Questions will be added here from the Github Issues Page. Also, more demos/documentation will be provided on request.