The Definitive Guide to Creating a Practical jQuery Plugin
In this article we’re going to be building our very own jQuery plugin step-by-step from scratch; jQuery makes this task exceptionally easy for us, giving us a simple method of packaging up our scripts and exposing their functionality, and encouraging the use of scalable and reusable object-oriented techniques.
Turning code that we find ourselves using time and time again into a jQuery plugin makes sense; it means that we can drop scripts into sites and have them work straight away with little or no customization, and it means that we can share our code with other developers. Because of the common syntax when using jQuery plugins most developers should be able to pick them up and use them intuitively given some simple documentation listing the configurable properties.
Our plugin will be a simple image loader; once a page has loaded, which could be the home page or another common landing page into our site, we load a series of images. These images are saved in the visitor’s browser cache and are therefore usable throughout the rest of the site. They will load much quicker than normal so this is a good way of pre-loading big images so that the visitor doesn’t have to wait for them to render when opening the page that contains them.
Getting Started
We’ll create a new directory to keep all of the necessary files in.
- Create a new folder called jLoader, then inside this create two more new folders called scripts and loaderImages.
- We’ll also need a copy of jQuery; download the latest version now if you don’t already have it, and unpack it to the scripts folder we just created.
- In the accompanying code download for this tutorial, you should find 18 images, half numbered 1.jpg, 2.jpg, etc, and half with proper file names like ant.jpg. These images should be placed in the loaderImages folder.
Now that we have everything in place we can start scripting; in a new file in your text editor start with the following code:
(function($) {
//plugin code will go here...
})(jQuery);
Save the new file in the scripts folder as jquery.jloader.js. We start out by creating an anonymous wrapper function which is self-executing. The function accepts a single argument which is the dollar symbol. The function is followed by a second set of parenthesis; we use these to pass the jQuery library into our plugin. This means that we can use any standard jQuery functionality using the $ sign as an alias. This second set of parenthesis are also what makes our function self-executing.
Adding Configurable Properties
Within our anonymous function add the following code:
$.jLoader = {
defaults: {
imgDir: "loaderImages/",
imgContainer: "",
imgTotal: 9,
imgFormat: ".jpg",
simpleFileNames: true
}
};
With this code we create a new object which is added as a property to the jQuery object. Nested within this object is a second object called defaults; this second object is used to store the different configuration settings for our plugin. These settings are properties of our plugin and form the main API with which it can be used programmatically. Once the plugin has been coded, it will appear in the DOM tab of Firebug as a property of the $ or jQuery objects:
The Constructor Method
Next we have to add our constructor method to jQuery so that we can target specific elements or groups of elements and apply our plugin to them. Directly after the configurable properties add the following code:
$.fn.extend({
jLoader:function(config, fileNames) {
var config = $.extend({}, $.jLoader.defaults, config);
config.imgContainer = this.attr("id");
(config.simpleFileNames == true) ? simpleLoad(config) : complexLoad(config, fileNames) ;
return this;
}
});
jQuery’s extend method takes an object and applies its properties to another object. When making plugins we apply the object representing our plugin to the fn object, which is a special jQuery construct made for authoring plugins.
The jLoader property in the object we apply to fn has an anonymous function as its value; within this function we first add our configurable properties. We do this using the extend method of jQuery once again. Our constructor function accepts two optional arguments, a developer-created configuration object and an array of file names.
This allows us to use the default properties, but to also accept a configuration object when we call the constructor method from external code. Any properties supplied in the constructor’s configuration object will override the values of any matching properties in the defaults configuration object.
It’s useful to other developers to provide as many configurable properties as possible to make our plugins more robust and customizable. The resulting set of properties is stored in the config variable so that we can easily pass it on to other functions.
We get the id of the selected element, which we can obtain by querying the id attribute of the current jQuery object, which will point to the element(s) that our constructor function is attached to.
We then determine whether we are using simple (numerical) or complex (alphanumerical) file names; we can find out from the simpleFileNames property of our config object. By default this is set to true so we check whether its value is still true and call the appropriate function using standard JavaScript’s ternary conditional statement. Each function is passed the config object so that we can make use of its properties inside of the function, if we didn’t do this, we wouldn’t be able to access any of the configuration properties from within our methods.
Finally, we use the return statement to return our plugin object; this is an important factor in the plugin code and means that we can chain additional jQuery methods onto the end of the call to our constructor method making it behave exactly as other methods internal to jQuery itself.
Additional Methods
Our plugin features two additional methods following the constructor method; these two methods are used internally by the plugin and do not need to be called from external code, think of them as protected methods. The first of these is the simpleLoad method and consists of the following code:
function simpleLoad(config) {
for (var x = 1; x < config.imgTotal + 1; x++) {
$("
").attr({
id: "image" + x,
src: config.imgDir + x + config.imgFormat,
title: "Image" + x
}).appendTo("#" + config.imgContainer).css({ display: "none" });
}
};
Using a standard JavaScript for loop we can create the required number of img elements according to the imgTotal property, which we set to 9 in our defaults object. It may seem cumbersome to have to tell the plugin how many images we want to load, but unfortunately there is no way to query the folder for its contents using JavaScript. This property helps keep the plugin from requiring server side support.
We create each image using jQuery’s excellent DOM node creation facility and set the basic attributes that any image needs; an id, src and a title. To make each element’s id unique we can use the count variable of our for loop. The src of each new img element is the most complex; for this attribute we fist add the path to the image using the imgDir property. With simple file names we can also use the count variable to add each specified image. Finally, we add the file extension using the imgFormat property. The title attribute simply matches the id.
Once each image has been created and given the appropriate attributes, we then append it to the container element specified in the imgContainer property. The pre-loaded images are not meant to be seen at this stage so we can use jQuery’s css method to set their display property to none. The final function, complexLoad, makes use of both the optional configuration object and the fileNames array; the code should appear as follows:
function complexLoad(config, fileNames) {
for (var x = 0; x < fileNames.length; x++) {
$("
").attr({
id: fileNames[x],
src: config.imgDir + fileNames[x] + config.imgFormat,
title: "The " + fileNames[x] + " nebula"
}).appendTo("#" + config.imgContainer).css({ display: "none" });
}
};
We still use a for loop in this method, although the number of times it will run is based on the number of items in the fileNames array instead of the imgTotal property. We still create a series of img elements and we set the same attributes on these elements that we did before, although we use different values for the attributes this time.
The id of each new image is simply set to the contents of the current array item. The image is loaded by concatenating the path, file name and file extension together once again, although this time we use the contents of the current array item as the file name instead of an integer. The title attribute has a slightly more detailed value than before and again makes use of the array item instead of a configuration property.
Using Our Plugin
We’ve now added all of the code that makes up our plugin. It’s time to put it to the test. Create a blank HTML file such as the following:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>jLoader Demo Page</title>
</head>
<body>
<div id="simpleImageContainer"></div>
<div id="complexImageContainer"></div>
<script type="text/javascript" src="scripts/jquery.js"></script>
<script type="text/javascript" src="scripts/jquery.jloader.js"></script>
<script type="text/javascript">
$("#simpleImageContainer").jLoader();
$("#complexImageContainer").jLoader({
simpleFileNames: false,
imgContainer:"complexImageContainer"
}, [
"ant",
"boomerang",
"catsEye",
"crab",
"helix",
"horsehead",
"redSpider",
"ring",
"witchHead"
]);
</script>
</body>
</html>
Save this page in the main project folder (jLoader) as something like jLoader.demo.html. In the body of the page we have our two container elements which we will populate with the preloaded images. We link to jQuery and to the source file for our widget and then following this we have two constructor methods for our plugin.
The first get’s the simpleImageContainer using the standard jQuery DOM retrieval method and calls our plugin with no additional configuration. This invokes the default implementation and should fill the container with the numerically named images. You won’t see this on the page because we set them all to display:none, but you should be able to see them in Firebug:
The second constructor method makes use of both a configuration object and the fileNames array. We set two properties here; first we set the simpleFileNames property to false so that our second protected method in our plugin is used, secondly we set the imgContainer property to the id of the element we are going to add the images to. We then provide an array of all of the image file names we want to preload in string format. Again, you won’t see the images; that’s the whole point, but Firebug will prove their existence:
Summary
In this tutorial we’ve looked at the individual steps that are needed to make a simple jQuery plugin; we looked at how to add properties to our plugin’s API and how to add methods that perform different behaviors. We also saw the methods that jQuery gives us to make authoring plugins easier and techniques we can use to make our creations more robust.
Additional Resources
-

jQuery Plugins
Be sure to visit the jQuery site in order to review the available plugins. There’s no use reinventing the wheel unless you’re learning!
-

Developing a jQuery Plugin
“Sometimes we get it in our heads that a task is too complex that we just ignore doing it. That’s been my mindset when thinking about developing a plugin for jQuery. I’ve always thought that some of the code I developed would make more sense as a plugin but I just didn’t have time to figure it out.”
-

Your First jQuery Plugin
“So you were out on your quest to find the answer to life, the universe, and everything, when blam, you found jQuery. Yes, I know, you were expecting 42, but too all of our surprise, it was jQuery. So what’s next? Build your own plugin!”
- Subscribe to the NETTUTS RSS Feed for more daily web development tuts and articles.










jQuery Lightbox Evolution only $12.00
Events Calendar Pro - Wordpr ... only $30.00 
Not bad… I like this one.
Ya….not bad…i also like that…
Nice introductory tutorial, thanks Dan!
I am curious, why are you injecting the images into the DOM at all? Surely creating the image using the Image() constructor would be easier, and nothing would have to be injected.
For example. this is a much simpler “plugin” which accepts an array of image locations:
$.preload = function(imgArray){
$.each(imgArray, function(){
(new Image()).src = this;
});
};
Also, there’s no need for you to specify the “imgContainer” as an option because when you call the plugin you can just reference it as ‘this’ or ‘$(this)’.
I don’t really get the difference between ‘simpleLoad’ and ‘complexLoad’ – surely counting the amount of images in the array is ALWAYS the right option?
another nice article about jQuery. thanks for sharing
hello
@Zy: Thanks for reading
@James: Thanks for reading, personally, I’m in the habit of avoiding the new constructor for anything (probably as a result of working with literal objects/arrays for so long) unless I’m working with the YUI. I guess there’s no real reason not to do this and I can look at incormporating your suggestion into future releases of the plugin
I encountered problems using both this and $(this) in the context of the plugin, I didn’t do any real trouble-shooting on the issue but I found using the imgContainer property resolved the issue so I was happy to go with it for this simple plugin
The simpleLoad function doesn’t accept an array, for small implementations I thought it would be more flexible to use as few parameters as possible and work with the imgTotal property instead. The complexLoad function doesn’t use this property, but relies on counting the items in the developer-supplied array instead.
Thanks for your feedback and suggestions
Thanks for the tutorial Dan.
Interesting point you make James – it certainly sounds cleaner, but I guess the overall points made by Dan about plugin creation are still valid regardless.
Nice TUT. Good use of Fire Bug there!
Very nice, ill have to make some time to get in depth into this one…
Educational and Inspirational Tut.
I’ve attempted a few little creations but had to put them on the back burner. After reading through this though, I have a bit of inspiration to digg those files out again I think.
Thanks for the article!
Alex
Thanks again for reading everyone, all comments appreciated =D
Looks good. Thanks.
Boo. Boo to jQuery! (i am biased)
How do you submit a plugin to jQuery?
I agree with James, but for the purpose of showing how to create a plugin, not bad at all.
jquery rules.
Looks like a great resource for future work. I am thrilled to see some much support for creating sites using jquery, mootools and the like.
@John McMullen – You can submit plugins at http://plugins.jquery.com/ once logged in.
Nice tutorial.
Good addition to the library!
It’s a shame that “F12″ on a Mac triggers Dashboard
I tested it on my PC (via VMware Fusion) and it worked.
Good job.
Are we looking at the script and a demo of the script or just the script. I just tried looking at it and all I saw was the h2 content. Not the example of it working.
Thank.
Very cool… Even better would be to create a function that reads the folder and passes an array into Jquery (using Ajax) and then spits out the images.
Maybe I should write a tutorial on that……
@carlos: its the script and a basic example of the script. In the demo page, you should be able to see the simple and complex containers, filled with the preloaded images, but you need to have firebug (or other generic DOM eplorer) installed and open to see the images
@jonny: I didn’t want to have to worry about using PHP + AJAX for this tutorial, hence not reading the contents of the folder and passing back a list of images
Really cool, thanks
One friend ask me some help about your really good example, I recommend she (and now, everyone who want test this) change the css property from ‘none’ to ‘block’ into simplex & complexLoad def, to browse preloaded pictures if you don’t have Firebug.
It certainly sounds cleaner. Thanks for the tutorial Dan.