Introduction

When developing rich web applications, Javascript will probably end up being a big part of your code base. As more and more of an application’s code moves to client-side Javascript, keeping all of this code organized can be challenging. A constant effort must be made to keep things from becoming a tangled mess of code.

Benefits of a jQuery plugin

One of the ways that we can enforce some design constraints in code is to modularize areas of similar functionality. This is a great design pattern, and jQuery can help us with this by leveraging its plugin architecture. Migrating Javascript code into a jQuery plugin can provide several benefits, including:

  • Consistent structure (in much the same was Rails can give a structure to a Ruby web application)
  • Options support with default values
  • Improved code reuse on multiple and disparate DOM elements
  • Better readability by method changing your code on the jQuery selector function

What makes a good candidate for a plugin?

These benefits may sound compelling, but not all code makes a good candidate for a migration to a jQuery plugin. Look for the following characteristics to identify code that could benefit:

  • Code that needs to instantiate and keep internal variables
  • Code that is repeated on multiple DOM elements
  • Code that needs to be scoped to a certain parent in your DOM tree
  • Code that begins to duplicate functionality provided by the jQuery plugin framework

Creating the jQuery plugin

Lets say we have code that meets several of these criteria. This code is written using Javascript object literal notation, and is then invoked on page load:

    MyLib = {
      setListeners: function() {
        $('.container a').bind('click', function() {
          console.log(MyLib.message());
        });
      },

      message: function() {
        return "hello world";
      }
    }

    $(MyLib.setListeners);

Issues

In this example, there are several problems with our code from a design standpoint. The first is that all functions are public, meaning that internal functions cannot be hidden. In our example above, the message function should be made private.

Second, the selector is hard coded, in the object literal and prevents easy reuse on different DOM elements. This is where jQuery can help by providing a mechanism (selectors) to determine which DOM elements on which to to apply our code.

Finally, the message is hard coded to return “hello world”. Perhaps we want to make this more extensible by making the value returned a variable that we can pass to message?

Note: All of these things can be done without migrating to a jQuery plugin, however the benefits of solving these solutions in a consistent way using commonly accepted conventions should not be underestimated.

jQuery Plugin Skeleton

    // You need an anonymous function to wrap around your function to avoid conflict
    (function($){
      // Attach this new method to jQuery
      // This is where you write your plugin's name
      $.fn.pluginname = function() {
        // Iterate over the current set of matched elements
        return this.each(function() {
          // code to be inserted here
        });
      };

    // pass jQuery to the function, 
    // So that we will able to use any valid Javascript variable name 
    // to replace "$" SIGN. But, we'll stick to $ (I like dollar sign: ) )
    })(jQuery);

Taken from http://www.queness.com/post/112/a-really-simple-jquery-plugin-tutorial

Adding Code to the Skeleton

    (function($){
      $.fn.myLib = function(options) {
        var defaults = {message: 'hello world'};

        function setListeners(container, options) {
          $('a', container).bind('click', function() {
            console.log(message());
          });
        }

        function message() {
          return options.message;
        }

        var options = $.extend(defaults, options);
        return this.each(function() {
          setListeners(this, options);
        });
      };
    })(jQuery);

This function is not executed directly; rather, we need to initialize our code by method chaining from a jQuery object. We can invoke by calling:

$('.container').myLib();

Exploring the New jQuery Plugin

We now have a jQuery plugin that addresses the issues that I stated earlier. First, we have truly private methods. There is no way for a user to invoke the message() method inside our plugin, because our function returns the jQuery object.

Second, the elements that this code executes on has been abstracted. The jQuery selector returns a collection of DOM elements, and our code is applied to each.

Finally, options are easily implemented. When we invoke the method, we can pass a different message by doing the following:

$('.container').myLib({message: 'foobar'});

Conclusion

While these solutions are not exclusive to jQuery, the conventions of building a plugin provide these structures in a consistent manner. This makes it easier for developers behind you to understand your code structure. The changes made to our code are minimal, with the contents remaining largely unchanged—just reorganized. Given the benefits, and the low bar for entry, you should keep your eyes open for the chance to make your commonly-used javascript functions into a jQuery plugin!

Thoughts and Additional Resources

If you are confused by the jQuery plugin syntax, try working with Javascript in a different context, like Node.js. I found that this helped my comprehension of Javascript as a language, and was a great resource when developing jQuery plugins.

Below is a list of resources that should help you in your jQuery plugifying:

—Ben Simpson