Authoring your First jQuery Plugin

Posted by: Suprotim Agarwal , on 1/9/2015, in Category jQuery and ASP.NET
Views: 20172
Abstract: With the jQuery Boilerplate Plugin and some simple guidelines, we all can build simple to very complex and structured plugins in no time. This article shows you how to create your first jQuery plugin.

One of the key aspects of jQuery is the possibility to extend it. A jQuery plugin is a method that extends the jQuery object. You can create a simple plugin by adding a method to $.fn in the following manner:

$.fn.plugin = function() {
}

If you look at the jQuery documentation, line 36 you will find that the fn property is an alias to the prototype property, which returns the current jQuery version

s8-jquery-plugin

The jQuery Boilerplate plugin by Zeno Rocha and Addy Osmani is a good starting point to start creating your own plugin. Here’s the structure of the plugin:

/*
 *  jQuery Boilerplate - v3.3.3
 *  A jump-start for jQuery plugins development.
 *  http://jqueryboilerplate.com
 *
 *  Made by Zeno Rocha
 *  Under MIT License
 */; (function ($, window, document, undefined) {

    var pluginName = "defaultPluginName",
            defaults = {
                propertyName: "value"
            };

    function Plugin(element, options) {
        this.element = element;
        this.settings = $.extend({}, defaults, options);
        this._defaults = defaults;
        this._name = pluginName;
        this.init();
    }

    $.extend(Plugin.prototype, {
        init: function () {
            console.log("xD");
        },
        yourOtherFunction: function () {
            // some logic
        }
    });

    $.fn[pluginName] = function (options) {
        this.each(function () {
            if (!$.data(this, "plugin_" + pluginName)) {
                $.data(this, "plugin_" + pluginName,
                    new Plugin(this, options));
            }
        });

        return this;
    };

})(jQuery, window, document);

Although the boilerplate plugin comes with some useful inline comments (not included in the above code) which you must read, I will try to simplify things for you by walking through this structure by creating our own plugin based on this template.

 

Create a new file ‘SimplePlugin.html’. We will create a simple highlight plugin which can highlight a textbox or a div by giving it a background color and a border. This plugin is saved as ‘jquery.highlighttextbox.js’ in the scripts folder of the source code that comes with this article.

Once it is ready, we will be calling our plugin in the following manner:



The first step is to understand the following structure of the boilerplate plugin:

;(function ($, window, document, undefined) {
...

})(jQuery, window, document);

What you see here is an Immediately Invoked Function Expression a.k.a IIFE. An IIFE is a function that is immediately defined and then invoked. Since JavaScript has a function scope, IIFE lets you create a ‘private scope’ which is safe from outside tampering. This separates your variables and other code from the global scope.

To make it simpler, think of it as an anonymous function wrapped within a function call. The function is invoked using the closing brackets ()

;(function() {
// Function body 
})();

Also observe there is a semi-colon (;) before function invocation. The semi-colon is a safety net against concatenated scripts and/or other plugins which may not be closed properly.

Let us now briefly talk about the arguments ($, window, document, undefined).

‘$’ here simply represents a reference to a jQuery object that is passed in to the wrapper function and avoids plugin conflicts with other languages like Prototype, that also use $.

window, document and undefined are passed as local variables to the function. Passing these as arguments, shorten the time it takes to resolve these variables. However in my personal opinion, the time saved by using these local variables is negligible. So if your plugin does not reference window or document too many times in your code, you can skip passing these variables. For knowledge purpose, another reason undefined is passed is because the undefined global property in ECMAScript 3, is mutable; so that means someone could change its value from outside. However in ECMAScript 5, undefined has been made immutable (read only).

To access the actual window and document objects, you are passing (jQuery, window, document) parameters at the end of your anonymous function.

Our next step is to define the plugin name and create defaults for it.

;(function ($, window, document, undefined) {
    var pluginName = "highlight",
    // plugin defaults:
     defaults = {
         bgColor: "AliceBlue",
         border: "3px solid #cdcdcd"
};

Our plugin will be called ‘highlight’. defaults allows users to pass options to the plugin. You can even send a single argument as an object literal, which is a standard jQuery practice. It is also a best practice to set default options using the defaults object, hence we are setting the default background color and border in case the user does not pass any option.

The next step is to define the plugin constructor which does all the heavy lifting and creates a few instance properties and calls init().

function Plugin(element, options) {
    this.element = element;
    this.settings = $.extend({}, defaults, options);
    this._defaults = defaults;
    this._name = pluginName;
    this.init();
} 

Observe how the boilerplate stores the custom settings of the user in this.settings. This is done to ensure that the plugin's default settings aren't overwritten by the user's custom settings.

The next step is the init() function which is called during initialization and contains the logic associated with the plugin initialization.

$.extend(Plugin.prototype, {
    init: function () {
        $(this.element).css({
            'background-color': this.settings.bgColor,
            'border': this.settings.border
        });
    }
});

To access the default or custom settings, we simply need to access this.settings.

The final step is to define a really lightweight plugin wrapper around the constructor, which prevents against multiple instantiations.

$.fn[pluginName] = function (options) {
    this.each(function () {
        if (!$.data(this, "plugin_" + pluginName)) {
            $.data(this, "plugin_" + pluginName, new Plugin(this, options));
        }
    });

    // chainable jQuery functions
    return this;
};

Within the function, this represents the jQuery object on which your function was called. That means that when you say $("#myText").highlight(), the value of this refers to the jQuery object containing the result of $("#myText"). Here you are referring to just one textbox but you could always do $(‘div’).highlight() which will contain all the divs on the page. By doing this.each, you are looping over every element within this, and thus highlighting every div/text on the page.

Within this.each, we check to see if the textbox object has been assigned a plugin. If yes, that means the plugin is already up and running. In case we haven't, then we create a new Plugin() object and add it to the textbox element.

At the end of it, this is returned making your plug-in chainable. This means someone could do the following:

$("#myText").highlight().fadeOut();

That’s it. Your plugin is ready to be used. Define a textbox on the page:


..and call our plugin in the following manner:



You will see that the textbox gets a background color and a border:

s8-jquery-plugin-highlight

An additional point I want to make here is that there are some jQuery plugins that act as Singletons. They define themselves directly on $ and do not return this. Eg: $.somePlugin = function(). Check the jQuery Cookie plugin for an example.

Summarizing the pattern, some points to keep in mind are as follows:

  • Always wrap your plugin in a self-invoking function
  • Add a semi-colon before the function’s invocation
  • Use a basic defaults object and extend the options with defaults
  • Use a simple plugin constructor for defining the logic for initial creation and assignment of the DOM element to work with
  • Always return the this keyword to maintain chainability unless you want to create a Singleton plugin
  • Use a lightweight wrapper around the constructor, which helps to avoid issues such as multiple instantiations.

With the jQuery Boilerplate Plugin and these simple guidelines in mind, we can build simple to very complex and structured plugins in no time.

Update: Here's another away to create a jQuery Plugin without using the Boilerplate template Create a jQuery Plugin to display a Running Counter

Further Reading: http://api.jquery.com/jQuery.extend/

This article has been editorially reviewed by Suprotim Agarwal.

Absolutely Awesome Book on C# and .NET

C# and .NET have been around for a very long time, but their constant growth means there’s always more to learn.

We at DotNetCurry are very excited to announce The Absolutely Awesome Book on C# and .NET. This is a 500 pages concise technical eBook available in PDF, ePub (iPad), and Mobi (Kindle).

Organized around concepts, this Book aims to provide a concise, yet solid foundation in C# and .NET, covering C# 6.0, C# 7.0 and .NET Core, with chapters on the latest .NET Core 3.0, .NET Standard and C# 8.0 (final release) too. Use these concepts to deepen your existing knowledge of C# and .NET, to have a solid grasp of the latest in C# and .NET OR to crack your next .NET Interview.

Click here to Explore the Table of Contents or Download Sample Chapters!

What Others Are Reading!
Was this article worth reading? Share it with fellow developers too. Thanks!
Share on LinkedIn
Share on Google+

Author
Suprotim Agarwal, MCSD, MCAD, MCDBA, MCSE, is the founder of DotNetCurry, DNC Magazine for Developers, SQLServerCurry and DevCurry. He has also authored a couple of books 51 Recipes using jQuery with ASP.NET Controls and The Absolutely Awesome jQuery CookBook.

Suprotim has received the prestigious Microsoft MVP award for Sixteen consecutive years. In a professional capacity, he is the CEO of A2Z Knowledge Visuals Pvt Ltd, a digital group that offers Digital Marketing and Branding services to businesses, both in a start-up and enterprise environment.

Get in touch with him on Twitter @suprotimagarwal or at LinkedIn



Page copy protected against web site content infringement 	by Copyscape




Feedback - Leave us some adulation, criticism and everything in between!