in jQuery

Simple jQuery Plugin Example

4. Keeping your options open

Your plugin may require some settings that will change depending on the context in which it is used. As a responsible developer, you know better than to hard-code values if it can be avoided and you want to allow users of your plugin to customize the look and/or behavior of the output to fit their needs, right?

Again, allowing for customization is very simple to implement. On the jQuery site, it is recommended that an object containing the various settings options be used as a single argument to the plugin rather than defining a long list of arguments. So we will pass a single argument named “options” to our plugin function.

(function($) {
    $.fn.explainify = function(options) {
        /**
         * Return the object to preserve method chaining
         */
        return this.each(function(i) {
            // Do some kick-ass stuff here
        });
    };
})(jQuery);

Didn’t I say it was simple?

We can’t just stop there, however. We want to make sure that there is a known default value of any settings.

(function($) {
    $.fn.explainify = function(options) {
        /**
         * Define some default settings
         */
        var defaults = {
            "color": "#F00",
            "font-weight": "bold"
        };
        /**
         * Return the object to preserve method chaining
         */
        return this.each(function(i) {
            // Do some kick-ass stuff here
        });
    };
})(jQuery);

Next, we need to merge any runtime options with the plugin’s default options.

(function($) {
    $.fn.explainify = function(options) {
        /**
         * Define some default settings
         */
        var defaults = {
            "color": "#F00",
            "font-weight": "bold"
        };
        /**
         * Merge the runtime options with the default settings
         */
        var options = $.extend({}, defaults, options);
        /**
         * Return the object to preserve method chaining
         */
        return this.each(function(i) {
            // Do some kick-ass stuff here
        });
    };
})(jQuery);

This next part can be a little tricky to follow if you are not very familiar with scoping in JavaScript. The this object in JavaScript refers to the current scope of execution. By current, I mean the scope in which the this keyword is used. It can also be a little tricky to keep track of which objects are and are not instances of the jQuery object.

If you look at line #17 in the code above, you will notice that the each method is being called on the this object. There is no native each method in JavaScript. The this object is an instance of the jQuery object, which defines the each method.

However, a reference to the this object inside the function being passed to the loop, does not refer to the same object as the this on which we are calling the each method. The outer reference to this refers to the instance of our plugin. Inside the function, this will refer to the current element in the iteration through the selected elements.

We can (and want to) wrap the current element in a jQuery instance by doing the following:

(function($) {
    $.fn.explainify = function(options) {
        /**
         * Define some default settings
         */
        var defaults = {
            "color": "#F00",
            "font-weight": "bold"
        };
        /**
         * Merge the runtime options with the default settings
         */
        var options = $.extend({}, defaults, options);
        /**
         * Return the object to preserve method chaining
         */
        return this.each(function(i) {
            var $this = $(this);
            // Do some kick-ass stuff here
        });
    };
})(jQuery);

We now have a fully-functional, albeit completely useless, jQuery plugin. I’m going to go ahead and finish this simple plugin to change the color and weight of any text contained in elements matching the selectors specified when the plugin is called, so you can see a finished plugin, but you can use the code above as the basis for creating a plugin to do anything you want. Just change the properties of the defaults object and add your code where it reads “Do something kick-ass here”.

/**
 * Create an anonymous function to avoid library conflicts
 */
(function($) {
    /**
     * Add our plugin to the jQuery.fn object
     */
    $.fn.explainify = function(options) {
        /**
         * Define some default settings
         */
        var defaults = {
            "color": "#F00",
            "font-weight": "bold"
        };
        /**
         * Merge the runtime options with the default settings
         */
        var options = $.extend({}, defaults, options);
        /**
         * Iterate through the collection of elements and
         * return the object to preserve method chaining
         */
        return this.each(function(i) {
            /**
             * Wrap the current element in an instance of jQuery
             */
            var $this = $(this);
            /**
             * Do our kick-ass thing
             */
            $this.css("color", options.color);
        });
    };
})(jQuery);