Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / Javascript

Simple jQuery Plugin in Detail

4.94/5 (35 votes)
6 Aug 2013CPOL8 min read 61.4K   548  
Understanding Simple jquery Plugin

Introduction

jQuery is the most popular JavaScript library amongst web developers. If you have some knowledge of jQuery, you may be familiar with code like

JavaScript
$("#someId").text("Something");
$("someTagName").hide();

Here text() and hide() are built-in jQuery functions. We will try to create something by which we can call our own defined function to do some cool stuff using jQuery. The statement will look just like a normal jQuery statement. Example :

JavaScript
$("someTagName").myFunction(options) ;

Here myFunction() is a user defined function.

These user defined functions bundled together are known as jQuery plugin. Many times during developing a web project we need to create our own jQuery plugin. This tutorial will help you understand how to create a basic jQuery plugin with well known standards.

Prerequisite

Before going to start creating the plugin we need to understand some topics.

  1. Function Declaration and Function Expression. 
  2. Immediately Invoked Function Expression
  3. jQuery in no conflict mode

Let's understand one by one.

In any JavaScript file if you write something like:

JavaScript
justFunction();
 
//function declaration    
function justFunction() 
{ 
    alert("something");
}

This will call the justFunction() and show an alert. Defining a function like that is known as function declaration.

Now there is another way to define a function

JavaScript
var anotherFunction = function() { alert ("something")}

Now if you write something like

JavaScript
anotherFunction(); 
 
// Function Expression 
var anotherFunction = function() { alert ("something"); }

Although anotherFunction is a function here this will give an error in console. This is known as function expression.

The reason behind that is function declarations loads before any code is executed. While function expressions loads only when the interpreter reaches that line of code. So if you try to call a function expression before it's loaded, you'll get an error.

But if you call a function declaration, it'll always work. Because no code can be called until all declarations are loaded. So you will have to always call the function expression after it is defined.

JavaScript
// Function Expression 
var anotherFunction = function() { alert ("something"); } 
anotherFunction();

Now a function expression can be called immediately by adding parenthesis after the anonymous function like

JavaScript
var anotherFunction = function() { alert ("something"); }(); //paranthesis added

This code snippet and the above does the same thing (shows the alert). Now the anotherFunction variable is not the same as above because it is now assigned with the value , that the anonymous function will return. Right now it is not returning anything so anotherFunction  is undefined. So if you write something like

JavaScript
var anotherFunction = function() { alert ("something"); }();
anotherFunction(); //error

This will give an error, because the anonymous function does not return any function. If its returns something like

JavaScript
var anotherFunction = 
  function() { alert ("something"); return "some string"; }(); //returns string

anotherFunction is now a string variable. And if:

JavaScript
var anotherFunction = function() { alert ("something"); return function(){
        alert("somethingElse")
        }; }();  // returns function

Now anotherFunction is a function and can be called like anotherFunction().

You can pass parameters to this function expression like

JavaScript
var anotherFunction = function(p1,p2) { console.log(p1); 
        console.log(p2); }(param1,param2 ); //param1,param2 are parameters

One of the main difference between a function expression and a function declaration is that A function expression can be called (invoked) immediately by using a set of parentheses, but a function declaration cannot be.

Now if we don't want to assign the function expression to a variable, then we have to write it inside parenthesis.

JavaScript
(function() { alert ("something");});

And to call it we need to add another set of parenthesis at the end like

JavaScript
(function() { alert ("something"); }());

And same as earlier, we can also pass parameters to it like:

JavaScript
( function(param){ console.log(param); }(param));

This type of functions are called IIFE (Immediately Invoked Function Expression).

IFFE is just an anonymous function (no name attached to it) that is wrapped inside of a set of parentheses and called (invoked) immediately.

JavaScript
( function(){ }());

Now the reason behind discussing this is, all our plugins code will be inside a IIFE. To understand why this is done we have to understand another topic that is jQuery in noConlict mode.

jQuery has a shorthand notation for the jQuery object that is the $ sign. Many JavaScript libraries use $ as a function or variable name, just as jQuery does. If you need to use another JavaScript library alongside jQuery, you can replace the jQuery's default $ sign by any other name. If you have included the jQuery file in the head section of your html page like this:

XML
<head>
    <script src="jquery-1.7.1.js" type="text/javascript"></script>
    <script src="index.js" type="text/javascript"></script>
</head>

The index.js page loads immediately after the jQuery file. So you can change the '$' sign by using this code

JavaScript
var jq = jQuery.noConflict(); 
 
//In all other codes you have to use the 'jq' to access the jquery codes  instead of the 
//default '$' sign, like document load event below 

jq(function()
{
// Do something with jquery
jq("div p").hide();
}
);

This way there would not occur any conflict between, jQuery $ sign and other JavaScript libraries $ sign.

Changing the default $ of jQuery may not be a matter of pleasure for many software developers because they are so much used to write jQuery codes using the $ sign. There is a solution to this. If you don't need to mix codes of jQuery and other JavaScript library then you can wrap all of your jQuery code in an IIFE (Immediately Invoked Function Expression). Because our plugin is dependant only on jQuery, all our plugin codes will be inside this code block.

JavaScript
(function ($) 
{ 
} (jQuery));

Here we pass the jQuery object as parameter and receive it using the $ sign. So all the codes are inside a local scope and it will not conflict with other libraries $ sign. There are more benefits to using IIFE’s than just local scoping. Here is a good article. Now we are set to create our jQuery plugin. In the next section we will create our own plugin.

Creating the jquery Plugin

For this short tutorial we need four files.

  1. index.html
  2. index.js
  3. jquery.myPlugin.js
  4. jquery-1.7.1.js

In the index.html file write some simple HTML code like this:

HTML
<html>
<head>
 
    <title>Index</title>
    <script src="jquery-1.7.1.js" type="text/javascript"></script>
    <script src="index.js" type="text/javascript"></script>
    <script src="jquery.myPlugin.js" type="text/javascript"></script>
</head>
 
<body>
 
    <h1>First Header</h1>
    <h1>Second Header</h1> 
    <h1>Third Header</h1>
 
    <input id="btnChange" type="button" value="Change" />
</body>
</html>

jquery.myPlugin.js is the file where we will write all our jQuery plugin code. OK, let's do a simple thing like changing the color of the headers to red. So our plugin code will look like

JavaScript
(function($){
        
    $.fn.makeChange = function(){
        this.css({color : "red"});
    };

}(jQuery));

and in the index.js file inside the form load event we bind the change button click event and call our makeChamge plugin function.

JavaScript
$(function(){
    
    $("#btnChange").click(function(){
        
            $("h1").makeChange();
    });
});

If we now double click the index.html file then the page will look like this in browser:

Image 1

Now if you click the Change button, it will look like this:

Image 2

Yes, that means our plugin code is working. Now let's take a look at the plugin code again:

JavaScript
(function($){
        
    $.fn.makeChange = function(){
        this.css({color : "red"});
    };
 
}(jQuery));

You can see that we have assigned the makeChange function in to $.fn.

$.fn points to the jQuery.prototype. Any method or property you add to it becomes available to all instances of the jQuery wrapped objects. Notice that to use .css(), we use this, not $( this ). This is because our makeChange function is a part of the same object as .css().

Now let's add some more features like changing the text and font-style.

JavaScript
(function($){
    
    $.fn.makeChange = function(){
    this.css({color : "red",fontStyle: "italic"});
    this.text("Header Text Changed");
};

}(jQuery));

Now if you load the page and click the Change button again you will see something like this

Image 3

Now, jQuery supports a technique called chaining, that allows us to run multiple jQuery commands, one after the other, on the same element(s). Statements like this is example of chaining:

JavaScript
$("#someId").css("color","red").slideUp(2000).slideDown(2000);

Because we are creating a jQuery plugin our makeChange function should support chaining.

Lets try a chained statement in our index.js file

JavaScript
$("h1").makeChange().slideUp(2000);

Now now let's reload the index.html page and click the Change button:

Image 4

As our chained statement suggests the headers should have been slid up and become invisible but this is not happening. So our makeChange function does not support chaining. To make it support chaining we need to return the element like this:

JavaScript
(function($){
        
    $.fn.makeChange = function(){
        this.css({color : "red",fontStyle: "italic"});
        this.text("Header Text Changed");
        
        return this;
    };
 
}(jQuery));

Now if you reload the index.html page and click the Change button again, you will see the headers are sliding up with the speed you have given (here 2000 ms). And eventually they will disappear.

Image 5

So now we have added the chaining feature to our plugin.

Now let's try to get text of each header individually and edit it. So this simple peace of code should do it.

JavaScript
(function($){
        
    $.fn.makeChange = function(){
        
        var hText= this.text(); //get the element text 
        
        this.css({color : "red",fontStyle: "italic"});
        this.text(hText+" With New Added Text");
        
        return this;
    };
 
}(jQuery));

Now after reloading the index.html page and clicking the Change button, we will see something like this:

Image 6

This does not serve our purpose because we want the header text like "First Header With New Added Text".

What happening here is this.text() function returning all text from the 3 headers. Now to solve this we need to use the jQuery each iterator.

JavaScript
(function($){
        
    $.fn.makeChange = function(){
        
        return this.each( function(){
            
            var hText= $(this).text();
            $(this).css({color : "red",fontStyle: "italic"});
            $(this).text(hText+" With New Added Text");
        });
    };

}(jQuery));

And now reloading the index.html page and clicking the Change button will give you:

Image 7

It's important to use each loop because our typical jQuery object will contain references to any number of DOM elements. If you want to manipulate specific element then you must need each loop.

Notice that the this element is inside the each function is a jQuery wrapped element now because function context has changed. We have wrapped the element three times here. The best practice is to wrap the this element and assign it to a variable then reuse it.

JavaScript
(function($){
        
    $.fn.makeChange = function(){
        
        return this.each( function(){
            
            var self= $(this);
            
            var hText= self.text();
            self.css({color : "red",fontStyle: "italic"});
            self.text(hText+" With New Added Text");
        });
    };
 
}(jQuery));

Till now our jQuery plugin performs some static change upon elements. Now let's give the user opportunity to pass parameters. That means let's accept some options.

In the index.js file you can supply options like this:

JavaScript
$(function(){
    
    $("#btnChange").click(function(){
        
           $("h1").makeChange({color: "green", 
                               text: "Text Supplied By Option" , 
                               fontStyle: "italic"
            });
    });
});

and in jquery.myPlugin.js, you can accept and use options like this:

JavaScript
(function($){
        
    $.fn.makeChange = function(options){
        
        return this.each( function(){
            
            var self= $(this);
            
            var hText= self.text();
            self.css({color : options.color,fontStyle: options.fontStyle});
            self.text(hText+" "+ options.text );
        });
    };
 
}(jQuery));

Now if you reload the index.html page and click the Change button, you will see this:

Image 8

Now our plugin should have some default settings if no value is supplied. If a value is supplied then the default value will be overridden. For this purpose we can use the $.extend method. Now let's look at the code

JavaScript
(function($){

    $.fn.makeChange = function(options){
        
		var defaults = {
				 text: "Default Text",
				 color: null,
				 fontStyle: null
			        };
					   
		var settings = $.extend(defaults, options);
		
        return this.each( function(){
            
            var self= $(this);
            
            var hText= self.text();
			
            self.css({color : settings.color,fontStyle: settings.fontStyle});
            self.text(hText+" "+ settings.text );
        });
    };
 
}(jQuery));

Here we have a defaults variable which contains our default settings. options contains the user defined settings.

$.extend method merges the contents of two or more objects together into the first object. so the variable settings contains the overall settings for the plugin.

Another important thing is that the default value for color and fontStyle is null. So it's better to check if a value is passed to the options before performing any modification. So our plugin code will look like this

JavaScript
function($){

    $.fn.makeChange = function(options){
        
		var defaults = {
				  text: "Default Text",
				  color: null,
				  fontStyle: null
			       };
					   
		var settings = $.extend(defaults, options);
		
        return this.each( function(){
            
            var self= $(this);
            
            var hText= self.text();
	self.text(hText+" "+ settings.text );
			
			if(settings.color) //check if a value is passed or not
			{
				self.css({color : settings.color});
			}
			
			if(settings.fontStyle)
			{
				self.css({fontStyle: settings.fontStyle});
			}
		});
    };
 
}(jQuery));

Last thing is we can also pass functions in options. So in the index.js page, you can send your function like this:

JavaScript
$(function(){
    
    $("#btnChange").click(function(){
        
        $("h1").makeChange({color: "green",
                text: "Text Supplied By Option",
                fontStyle: "italic",
                complete: function(){
                    alert("Done");
                }
            });
    });
});

Here complete is a function that you are supplying to the options. Now in our plugin code we need to call this function like this:

JavaScript
(function($){
        
    $.fn.makeChange = function(options){
        
        var defaults = {
                         text: "Default Text",
                         color: null,
                         fontStyle: null
                       };
                       
        var settings = $.extend(defaults, options);
        
        return this.each( function(){
            
            var self= $(this);
            
            var hText= self.text();
            self.text(hText+" "+ settings.text );
            
            if(settings.color)
            {
                self.css({color : settings.color});
            }
            
            if(settings.fontStyle)
            {
                self.css({fontStyle: settings.fontStyle});
            }
            
            if($.isFunction( settings.complete )) //check if its a function
            {
                settings.complete.call(this);
            }
        });
    };
}(jQuery));

Here first we have checked that if settings.complete is supplied and it's a function and then call it.

So if you reload index.html and click the Change button we will get three alerts for three headers.

Image 9

So that's all for the article. Hope this will be of some help to you.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)