jQuery: The Write Less, Do More JavaScript Library

Plugins/Authoring

From jQuery JavaScript Library

Jump to: navigation, search

jQuery offers a mechanism for adding in methods and functionality, bundled as plugins. Most of the methods and functions included in the default download are written using the jQuery plugin construct.

Plugin writing comes in two steps. The first is writing any of your public methods and functions, for example:

jQuery.fn.debug = function() {
  return this.each(function(){
    alert(this);
  });
};
jQuery.log = function(message) {
  if(window.console) {
     console.debug(message);
  } else {
     alert(message);
  }
};

Coders will now be able to call your new plugin, like so:

$("div p").debug();

Or use your functions:

try {
  // do some error prone stuff
} catch(exception) {
  $.log(exception);
}

There are a couple of very important points to remember:

  • Name your file jquery.[insert name of plugin].js, eg. jquery.debug.js
  • All new methods are attached to the jQuery.fn object, all functions to the jQuery object.
  • inside methods, 'this' is a reference to the current jQuery object.
  • Any methods or functions you attach must have a semicolon (;) at the end - otherwise the code will break when compressed.
  • Your method must return the jQuery object, unless explicity noted otherwise.
  • You should use this.each to iterate over the current set of matched elements - it produces clean and compatible code that way.
  • Always use jQuery instead of $ inside your plugin code - that allows users to change the alias for jQuery in a single place. See below for an explanation and a more elegant solution.

If you're curious as to how a full plugin looks, feel free to browse the plugins or look through the jQuery Source Code.

The above will suffice for small and simple plugins, but in other scenarios, a more sophisticated approach is necessary.

Contents

Collecting static functions in objects

If you need multiple public static methods, you should add them to an object. Eg. if you start with this:

jQuery.logError = function() { ... };
jQuery.logWarning = function() { ... };
jQuery.logDebug = function() { ... };

Change it to:

jQuery.log = {
  error : function() { ... },
  warning : function() { ... },
  debug : function() { ... },
};

This avoids namespace cluttering and can prevent a lot of issues.

Hiding variables

There are different scenarios where you want to define your plugin methods in a loop, without specifying each one. Something like this:

var newMethods = {
  check       : function() { ... },
  uncheck     : function() { ... },
  toggleCheck : function() { ... }
};
jQuery.each(newMethods, function(i) {
  jQuery.fn[i] = this;
});

To hide the variable newMethods from other code, you should wrap the code into a function:

(function() {
  var newMethods = {
    check       : function() { ... },
    uncheck     : function() { ... },
    toggleCheck : function() { ... }
  };
  jQuery.each(newMethods, function(i) {
    jQuery.fn[i] = this;
  });
})();

Options

It is a very good practice to design your plugin that it can be used without having to specify lots of parameters. To make it as flexible as possible, you provide several options with sensible defaults. Consider a plugin that always needs an URL as a parameter, and has 'name' (string), 'size' (number) and 'global' (boolean) as optional parameters. You should code your plugin like this:

jQuery.fn.pluginName = function(url, settings) {
  // define defaults and override with options, if available
  // by extending the default settings, we don't modify the argument
  settings = jQuery.extend({
     name: "defaultName",
     size: 5,
     global: true
  }, settings);
  // do the rest of the plugin, using url and settings
}

You use the plugin without options like this:

$('selection').pluginName('mypage.php');

Or with two of three options like this:

// override defaults for name and size, but not global
var options = {
  name: "foobar",
  size: 10
}
$('selection').pluginName('mypage.php', options);

Using jQuery.extend to extend jQuery itself

In the above section, we checked if any options are given before we applied jQuery.extend(settings, options). The reason for this: If you specify only one parameter, the jQuery object itself is extended with the given object. This allows you to add stuff to nearly every aspect of jQuery, eg. new methods:

jQuery.fn.extend({
  check       : function() { ... },
  uncheck     : function() { ... },
  toggleCheck : function() { ... }
});

But you can use jQuery.extend also to extend other objects defined inside of jQuery, eg. to add new selectors:

jQuery.extend(jQuery.expr[":"], {
  text     : "a.type=='text'",
  radio    : "a.type=='radio'",
  checkbox : "a.type=='checkbox'",
});

Customizing animations

Your plugin uses an animation for certain events, eg. the tabs plugin can use fade or slide animations when the tab is changed. Making the animations customizable is quite easy when using the animate method (see [/api/ API docs] for details). The following example uses a fade as default:

jQuery.fn.foobar = function(settings) {
  settings = jQuery.extend({
    animation: {opacity: "hide"}
  }, settings);
  // use the animation setting as a parameter for animate
  jQuery(...).animate(settings.animation);
}

By passing a hash for the animation option, you could use a slide:

jQuery(...).foobar({
  animation: {height: "hide"}
});

Custom Alias

It was stated above that you should not use the "$" alias inside your plugin code. This allows users of jQuery and your plugins to change the alias from "$" to something else like "jQ". That is necessary when working with other libraries or frameworks which make use of the "$" alias.

Still, $ is a very handy shortcut, and instead of not using it, we should not rely on it's existance. Instead, we can simply define our own alias (and call it "$") for our code.

Custom Alias in plugin code

The trick is to define all plugin code inside a function and execute this function immediately. The construct looks like this:

(function() {
  // put plugin code here
  var xyz; // xyz is NOT a global variable, it is only visible inside this function
})(); // execute the function immediately!

The additional parentheses are necessary! You can't execute an anonymous function without them.

Ok, now to the fun part:

(function($) {
  // plugin code here, use $ as much as you like
})(jQuery);

We pass "jQuery" to the function and can now use whatever alias for jQuery we like. So instead of "$" you could also use any other valid JavaScript variable name.

See the tooltip plugin for a plugin that uses this construct.

Custom Alias in page code

When writing jQuery code for the examples that illustrate the use of your plugin, you may want to consider using an alias technique to make your code more forward-compatible. Many examples of jQuery code (including examples distributed with many plugins) are written using the $ alias. This can be a problem for people using your plugin by starting to copy the example code if their web pages already use the $ alias for another purpose.

To prevent this, you can nest your example code in the DOM ready event handler, which is shown below in its shorthand form. The first argument to your function can be the $ alias, which you can then use as your jQuery alias throughout the code inside the function.

 jQuery(function($) {
   // your code using $ alias here
 });

That way, you type jQuery only once and can use the alias safely inside the ready handler code. For more information, including caveats about this technique, see Using jQuery with Other Libraries.