The
available third-party plugins provide a bevy of options for enhancing
our coding experience, but sometimes we need to reach a bit farther.
When we write code that could be reused by others, or even ourselves,
we may want to package it up as a new plugin. Fortunately, the process
of developing a plugin is not much more involved than writing the code
that uses it.
In this article, we cover
how to create many different kinds of plugins, from the simple to the
complex. We'll start with plugins that simply make new global functions
available, and move on to cover jQuery object methods of various types.
We will also cover extending the jQuery selector engine with new
expressions, and conclude with some tips on distributing a plugin for
other developers to use.
Adding new global functions
Some of the built-in capabilities of jQuery are provided via what we have been calling global functions. As we've seen, these are actually methods of the jQuery object, but practically speaking, they are functions within a jQuery
A prime example of this technique is the $.ajax() function. Everything that $.ajax() does could be accomplished with a regular global function called simply ajax(), but this approach would leave us open for function name conflicts. By placing the function within the jQuery namespace, we only have to worry about conflicts with other jQuery methods.
To add a function to the jQuery namespace, we can just assign the new function as a property of the jQuery object:
jQuery.globalFunction = function() {
alert('This is a test. This is only a test.');
};
Now in any code which uses this plugin, we can write:
We can also use the $ alias and write:
This will work just like a basic function call, and the alert will be displayed.
Adding multiple functions
If our plugin needs to provide more than one global function, we could declare them independently:
jQuery.functionOne = function() {
alert('This is a test. This is only a test.');
};
jQuery.functionTwo = function(param) {
alert('The parameter is "' + param + '".');
};
Now both methods are defined, so we can call them in the normal fashion:
$.functionOne();
$.functionTwo('test');
We can also employ an alternate syntax in defining our functions, using the $.extend() function:
jQuery.extend({
functionOne: function() {
alert('This is a test. This is only a test.');
},
functionTwo: function(param) {
alert('The parameter is "' + param + '".');
}
});
This produces the same results.
We risk a different kind of
namespace pollution here, though. Even though we are shielded from most
JavaScript function and variable names by using the jQuery
namespace, we could still have a conflict with function names defined
in other jQuery plugins. To avoid this, it is best to encapsulate all
of the global functions for a plugin into an object:
jQuery.myPlugin = {
functionOne: function() {
alert('This is a test. This is only a test.');
},
functionTwo: function(param) {
alert('The parameter is "' + param + '".');
}
};
This pattern essentially creates another namespace for our global functions, called jQuery.myPlugin. Though we will still informally call these functions "global," they are now methods of the myPlugin object, itself a property of the global jQuery object. We therefore have to include the plugin name in our function calls:
$.myPlugin.functionOne();
$.myPlugin.functionTwo('test');
With this
technique (and a sufficiently unique plugin name), we are fully
protected from namespace collisions in our global functions.
What's the point?
We now have the basics of plugin development in our bag of tricks. After saving our functions in a file called jquery.myplugin.js,
we can include this script and use the functions from other scripts on
the page. But how is this different from any other JavaScript file we
could create and include?
We already discussed the namespace benefits of gathering our code inside the jQuery
object. There is another advantage of writing our function library as a
jQuery extension, however: because we know that jQuery will be
included, the functions can use jQuery itself.
Even though jQuery will be included, we shouldn't assume that the $ shortcut is available. Recall that the $.noConflict() method can relinquish control of this shortcut. To account for this, our plugins should always call jQuery methods using jQuery or internally define $ themselves, as described later.
Creating a utility method
Many of the global functions provided by the core jQuery library are utility methods;
that is, they provide shortcuts for tasks that are frequently needed,
but not difficult to do by hand. The array-handling functions $.each(), $.map(), and $.grep() are good examples of these. To illustrate the creation of such utility methods, we'll add a new $.sum() function to their number.
Our new method will accept
an array, add the values in the array together, and return the result.
The code for our plugin is quite brief:
jQuery.sum = function(array) {
var total = 0;
jQuery.each(array, function(index, value) {
total += value;
});
return total;
};
Note that here, we have used the $.each() method to iterate over the array's values. We could certainly use a simple for()
loop here, but since we can be assured that the jQuery library has been
loaded before our plugin, we can use the syntax we've grown comfortable
with.
To test our plugin, we'll build a simple page to display the inputs and outputs of the function:
<body>
<p>Array contents:</p>
<ul id="array-contents"></ul>
<p>Array sum:</p>
<div id="array-sum"></div>
</body>
Now we'll write a short script that appends the array values and the array sum to the placeholders we've created.
$(document).ready(function() {
var myArray = [52, 97, 0.5, -22];
$.each(myArray, function(index, value) {
$('#array-contents').append('<li>' + value + '</li>');
});
$('#array-sum').append($.sum(myArray));
});
A look at the rendered HTML page verifies that our plugin is working correctly:
So we've now seen the
namespace protection and guaranteed library availability that jQuery
plugins grant. These are just organizational benefits, though. To
really tap into the power of jQuery plugins, we need to learn how to
create new methods on individual jQuery object instances.