Channels ▼
RSS

Tools

The jQuery Plugin Mechanism


The jQuery library has many merits and, in the end, it has changed the way we code client Web pages. One of its best selling points is the integration of the CSS query syntax with the page DOM. Another nice move is the chain syntax, which allows developers to concatenate multiple calls in a single line. A natural extension of the chain syntax is the plugin mechanism, through which you can add new capabilities to the core library.

The jQuery library is centered on a root object, which exposes a number of methods. After doing whatever tasks it was called to do, each method just returns the instance of its parent object. In this way, a new call to another method can be arranged on the same expression. The jQuery root object is jQuery.fn and it's precisely there that you intervene to create your own plugins. At its core, a jQuery plugin is simply a new function property added to the jQuery.fn object. When creating a plugin, you should follow a specific pattern to avoid possible conflicts between the $ symbol of jQuery and the same symbol being potentially used by other libraries. Here's the approach to take for writing a self-executing function:

(function( $ ){
  $.fn.yourPluginName = function() {
     // your code here
  };
})(jQuery)

A few years ago, Microsoft had to restructure a bit their Ajax library to avoid collisions with jQuery. But that happened at a time in which only a few people were actively using jQuery. Frankly, it is hard to believe that some code can still conflict with the $ sign nowadays. At any rate, the pattern above keeps you on the safe side, and allows you use the $ sign everywhere in the source code of the plugin.

Because a plugin is invoked on a wrapped set — a collection of DOM elements selected by the query — its code should process all selected items. The most common way of doing this is using the each function. Subsequently, the pattern for building a jQuery plugin changes as below:

(function( $ ){
   $.fn.yourPluginName = function() {
       return this.each(function() {
            // your code here
       });
  };
})(jQuery)

Note that by returning the output of the each function, you contribute to maintaining the "chainability" of calls. There might be circumstances in which this is not possible — for example, when the plugin is expected to return a scalar value — but you should endeavor to always return the jQuery object (the this object) from any plugins.

As you may know, the this keyword has a different meaning in different parts of your jQuery-based code. In the scope of the plugin core function, this refers to the jQuery object the plugin was invoked on. The same is not true if you look at it from within the each callback or any other callback.

(function( $ ){
  $.fn.yourPluginName = function() {
       // “this” here refers to jQuery object
       return this.each(function() {
            // “this” here refers to the DOM object in the wrapped set
            var _target;
     
            // Extract and save a reference to the jQuery object
            _target = $(this);
            :
       });
  };
})(jQuery)

In the callback, the keyword this refers to the nth element in the wrapped set being processed. To dereference it to the jQuery object, you use $(this).

It is a good idea to maintain the state of the plugin scoped to the core plugin function. If you need to reference it outside the core function — for example, from within helpers — you can pass members as arguments. The following code snippet registers a handler for the blur DOM event.

_target.blur(function(e) {
     var currentInput = _target.val();
     _validate(currentInput, _target, _state);
});

The code first grabs the value of the element the plugin is attached to (i.e., an input element) and next invokes an internal function, passing value and state. Keeping the state scoped to the plugin saves you from a bunch of globals and possible conflicts when the plugin is used for multiple elements in the same page.

At this point, the basic behavior of a jQuery plugin is set up. What remains is actually defining its behavior. Many plugins perform tasks over one or more DOM elements. In doing so, they register handlers for events. The code below shows a handler for a plugin that applies to input boxes and limits valid input to numbers.

_target.keydown(function(e) {
    var key = e.charCode || e.keyCode || 0;            
    return (key >= 48 && key <= 57);        
})    

Once defined, the plugin is deployed as a regular script file and, of course, requires the parent jQuery library to work. Here's a quick example of how to invoke a plugin named numberOnly in a chainable expression.

$(document).ready(function () {
    $("#quantity").numbersOnly().css("background-color", "yellow");

Plugins are an excellent way to group related functionality and build highly reusable and well-packaged components. The huge number of free plugins for the jQuery library is the direct proof of the effectiveness of the model.


Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.
 

Video