ドキュメント

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 few 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 attach the plugin to jQuery directly instead of $, so users can use a custom alias via noConflict(). Read the custom alias section below for an explanation, with an elegant solution that lets you use $ internally, but attaches to the primary jQuery object.

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 that executes immediately (creating a closure for your variables):

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

Options

It is good practice to design your plugin so that it can be used without having to specify lots of parameters. To make it as flexible as possible, you should provide several options with sensible defaults. Consider a plugin that always needs a 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, options) {
  // 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
  }, options);

  // 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);


Suggested reading: Mike Alsup has written a great plugin development pattern. Make sure you read all the comments; there's a few bugs in the example code.

Using jQuery.extend to extend jQuery itself

In the above section, we applied jQuery.extend(settings, options) to extend the plugin settings object. Now, by passing only one object argument instead of two or more, we change the intent of the jQuery.extend function to extend the jQuery object itself with the given object argument. 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 may use an animation for certain events, e.g. 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 the API documentation 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 its existence. 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.

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.

Putting It All Together

Here's a short code sample that may be used as a starting point for developing your plugin.

 (function($) {
 
   $.fn.myPlugin = function(settings) {
     var config = {'foo': 'bar'};
 
     if (settings) $.extend(config, settings);
 
     this.each(function() {
       // element-specific code here
     });
 
     return this;
 
   };
 
 })(jQuery);


Note that in this sample the "config" variable is an object used to define default settings for your plugin (eg., "{'speed': 1000}") that is extended using the "settings" object optionally passed in when the function is called.

The each() method in the middle will loop over each matched item passed to your plugin by the preceding jQuery selector when your plugin is called. For example, if your plugin were called in this manner:

 $('p').myPlugin();

Then the each() method would loop over every paragraph tag on the page.

One of the more important lines in this sample is the one that reads "return this;" after the each() method; this will ensure that the expected jQuery chaining remains intact when your plugin is called, meaning people may add methods after calling your plugin:

 $('p').myPlugin({'foo': 'bar'}).fadeOut();