jQuery Plugin Development Boilerplate

jQuery Plugin Development BoilerplateThe 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

// 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 Plugins
10 Simple Guidelines for Writing jQuery Plugins
16 Step jQuery Plugin Development Lifecycle

This entry was posted in jQuery. Bookmark the permalink.

10 comments on “jQuery Plugin Development Boilerplate

  1. Thomas Traub on said:

    Here’s the linted version:
    https://gist.github.com/7461f96601a12b698724

  2. Corey Ballou (@cballou) on said:

    I would suggest that default settings, rather than being privately scoped, get moved to $.fn.wTooltip.defaultSettings to allow for global user overrides.

  3. Joel Meador on said:

    Thanks for writing this down and sharing it. Much clearer than previous versions of this concept I’ve seen. :)

  4. John Strickler on said:

    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.

  5. Lorenzo Stoakes on said:

    Not to be a colossal pedant, but should:-

    else if(typeof option == \'string\')

    Use === rather than == for consistency?

    Unless I’m missing something :)

  6. Russ Porosky on said:

    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!

  7. stereobooster on said:

    take a look https://github.com/zenorocha/jquery-boilerplate

  8. 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).

  9. 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)

Leave a Reply

Your email address will not be published. Required fields are marked *

*

HTML tags are not allowed.