jQuery Plugin Design Patterns: Part I

jQuery plugins come in all shapes and sizes. They perform very simple or very complex tasks depending on their intended use. When it comes time for you to design your own plugin, its really important to understand what patterns other developers use and what will best suits your needs.

As a side note, I have built a number of plugins for my own projects and client work that will never be released. The jQuery community needs to stop thinking of plugins only as releasable, open-source projects, and start thinking of them instead as a reusable pieces of code that can help optimize and DRY up a complex website. Take this little plugin as an example:

$.fn.notice = function(){
    return this.slideDown(500).delay(4000).slideUp(500);
}

It simply abstracts the animation for displaying a notice (using jQuery 1.4). Would I ever release this on an open source site? Of course not! But it is still a fully functioning jQuery plugin that can be used over and over throughout a website.

Design Pattern Series Overview

  • Basics & Structure (this article)
  • Options & Updating
  • Callbacks & Custom Events
  • Misc. General Practices

Basics

Filename

Every jQuery plugin sits in its own JS file, and is normally named using the following pattern:

jquery.pluginname.js
jquery.pluginname.min.js

Released plugins often also have a version number:

jquery.pluginname-1.3.js
jquery.pluginname-1.3.min.js

If you end up building a lot of plugins for your website, consider also including a namespace to keep all your files together (And of course you would combine and minify them for production, right?):

jquery.mysite.pluginname.js
jquery.mysite.pluginname.js

Basic File Layout

After any comments you choose to put at the top of your file, the very next thing you should have is a self executing anonymous function that will actually wrap your entire plugin. Say what!? Don’t worry, you have seen it before, and it looks like this:

(function($){

   ... code here ...

})(jQuery);

This gives your plugin a private scope to work in, and also allows your plugin to be used with $.noConflict mode without creating a problem. By passing jQuery into the function, the $ will equal jQuery inside the function even if $ means something different outside your plugin.

Structure

There are three basic structures you will see when you look at released plugins:

Contained Function

In this structure, (almost) all the code to run your plugin is contained within the function used to call your plugin. This is the most common format:

(function($){

   $.fn.myPlugin = function(){
      return this.each(function(){
         // do something
      });
   }

})(jQuery);

You should use this this structure when you are writing a simple plugin that acts once upon the jQuery result set on each execution. For complex plugins that need to maintain an adjustable state, you should consider the “Class and Function” structure.

Class and Function

In this structure, a class is used and an instance is created for each DOM element in the result set. You may see these objects attached in some way to the DOM elements they modify:

(function($){
   var MyClass = function(el){
       var $el = $(el);

       // Attach the instance of this object
       // to the jQuery wrapped DOM node
       $el.data('MyClass', this);
   }

   $.fn.myPlugin = function(){
      return this.each(function(){
         (new MyClass(this));
      });
   }

})(jQuery);

You should use this structure if you need to be able to access the object later that is associated with a DOM element. It is far easier to attach a single object vs several key/value pairs using the data() method. In this approach, you can access the object by calling $('selector').data('MyClass'). This functions more like a widget and is a plugin that maintains state and can adjust its state on the fly (Learn how in the next article.).

Note: Widget Factory: The next release of jQuery UI is going to see the addition of a Widget Factory that will be designed to specially assist in developing widget-like plugins.

Extend

In my opinion, this is the least idiomatic way to create a jQuery plugin. It uses the jQuery.fn.extend method instead of jQuery.fn.pluginName:

(function($){

   $.fn.extend({
     myPlugin: function(){
      return this.each(function(){
         // do something
     },
     myOtherPlugin: function(){
      return this.each(function(){
         // do something
     }
   });

})(jQuery);

You will find this structure helpful if you need to add a large number of plugin methods to jQuery. I would contend, however, that if your plugin needs to add that many methods, there may be a better way to structure its implementation.

I feel the extend method is used more by programmers transitioning from other JS libraries. I personally find the simple $.fn.pluginName = structure to be easier to read, and more in line with what you will normally see in jQuery plugins.

Up Next

In the next part of this series, we will look at passing options and providing methods for updating settings and functionality after a plugin has been called.

Doug Neiner is an Editor at Fuel Your Coding and an official member of the jQuery Team. He is addicted to new technology, and specifically loves spending time with WordPress, Ruby on Rails and jQuery. Learn more via twitter or his Google Profile.

 

If you liked this article, please help spread the news on the following sites:

  • Bump It
  • Blend It
  • Bookmark on Delicious
  • Stumble It
  • Float This
  • Reddit This
  • Share on FriendFeed
  • Clip to Evernote