JavaScript
Article

Introduction to Developing jQuery Plugins

By Simon Codrington

This article was peer reviewed by Mark Brown and Julian Motz. Thanks to all of SitePoint’s peer reviewers for making SitePoint content the best it can be!

You’ve probably worked on interactive components before, like sliders, galleries or interactive forms. While you might be creating these on a site-by-site basis, one great time saver is to build your functionality as a jQuery plugin to speed up your development.

jQuery plugins let you define your functionality once and then drop it into your projects as needed, getting you up and running faster.

We’re going to look at how to build your own jQuery plugin. We’ll look at all the areas you need to know to get you up and running building plugins in no time.

We’ll be using a plugin I’ve created called fancytoggle to showcase the different parts of a plugin. It’s a simple plugin for toggling the visibility of nested elements, such as list items, to create accordion-style widgets for things like FAQs. The overall idea is about the concepts of plugins, but this example should help you see how it all works in practice.

See the Pen FancyToggle by SitePoint (@SitePoint) on CodePen.

A Plugin Approach: The Advantages

The core concept here is to create something extensible that you can add to your projects to give you quick functionality. jQuery’s plugin functionality simplifies the process of building reusable code.

One of the strengths of these plugins is that they let the developer define several options that can be used to customize the functionality. You might create several options that change the way your plugin operates entirely, or you might just define a few to give the user a bit more control for styling or layout. With plugins, this choice will be up to you.

Developing jQuery Plugins

Let’s run through the steps needed to register a new jQuery plugin. We’ll use our example plugin, fancyToggle, so you can see how it’s all put together.

Creating our function with $.fn

jQuery plugins work by registering a function with the name you want to call to trigger your plugin (for example, you call jQuery’s inbuilt .width() or .height() functions when you want the width / height returned)

We attach our function to jQuery’s $.fn object to make it available to the global $ object. This registers our function and lets it be called on objects or selections.

//registering our function
$.fn.fancytoggle = function(){
  // ...
};

That’s all there is to it! You now have a new method you can call from jQuery’s $ object. Right now, it won’t do anything, but you can call this method wherever you like, for example on a selector:

//Call fancytoggle on this element
$('.my-element').fancytoggle(); 

You can register as many functions as you want with $.fn, however its good practice to avoid registering more than one function unless the plugin does distinctly different tasks.

Multiple collections and looping

An important thing to understand is that when your plugin is called it might be applying itself to either a single element or to several. For example with our plugin, if we are applying fancytoggle() to several different items we will have a collection to process within our function.

To process each element we just need to loop through the collection using jQuery’s $.each function:

$.fn.fancytoggle = function(options) {
  // `this` refers to the jQuery elements your plugin is called on
  this.each(function(index, value){
    // the rest of your plugins functionality here
  });

  return this;
};

We iterate through each of the collection’s elements and set them up. We might be performing calculations, adding event listeners or playing with our elements in some way. It’s the $.each here that ensures we’re referring to the right element.

Returning objects / chaining

Most of the time, your plugins will work by being called directly on an object or on a selector. This executes your plugin’s function against this item.

One of jQuery’s features is the concept of chaining, where you can call several methods back to back on a single item and each will execute in order:

// Chaining several jQuery methods on a selector
$('.my-element')
  .addClass('active')
  .slideToggle('fast'); 

This selects an element, adds an active class and then slides it either up or down. Each method returns an object which the next method is then called on.

To make our plugin work this way all that’s needed is to return the item at the end of your plugin’s function. While it’s technically not required, it’s highly recommended.

// defining our plugin function and returning it
$.fn.fancytoggle = function() {
  // ...
  return this;
};

Creating options and configurations

Plugins can be passed a series of options to change the way they work. These options are passed to your function as a series of key/value pairs (a JavaScript object):

// apply fancyToggle to this element (and customize our values)
$('.my-element').fancytoggle({
  openSpeed: 300,
  closeSpeed: 600,
});

To give our plugin the ability to process options we need to define the default settings to be used. We can then use jQuery’s $.extend method to merge our default options with the options passed in when our plugin is called:

$.fn.fancytoggle = function(options) {
  // default arguments 
  options = $.extend({
    openSpeed: 400,
    closeSpeed: 400,
    easing: 'linear',
    // all your options here
  }, options);

  // ...

  return this;
}

You can define as many options you want for your plugin, $.extend will create a single object by merging and collecting values. You might want to include some basic settings or other elements that will help your plugin configure itself.

For our plugin, we’re including several options to define how the plugin will work. For example, we want the user to be able to toggle as many areas open as they want. However, we have it as an option to let them only toggle one section at a time (closing the others). During our toggle function we check to see if we should close other items based on this setting.

options = $.extend({
  singleItemOpen: false,
}, options);

// later on in our toggle function
if (options.singleItemOpen === true) {
  var $activePanel = $item.siblings('.active');
  animate($activePanel, 'data-min-height', 'data-close-speed');
}

Event listeners

Event listeners are functions that will be called at a specific moment in the plugins life-cycle. These callbacks will let others (or you) hook into key parts of your plugin and trigger additional functionality.

Many developer-focused jQuery plugins have callbacks that you can hook into, for example when clicking through a slide-show or closing a modal window.

You define these callbacks as elements in your default options. Start by adding these event names and setting their values to empty functions:

options = $.extend({
  // ...,
  onItemClick: function(){},
  onItemOpen: function(){},
  onItemClose: function(){}
}, options);

Instead of using all those empty functions, jQuery provides the $.noop function. This does the same thing but avoids the overhead of creating multiple anonymous functions.

options = $.extend({
    onItemClick: $.noop,
    onItemOpen: $.noop,
    onItemClose: $.noop
}, options);

Once you have your settings organised you can build your functionality where your callbacks happen.

The callbacks work by calling your options when they are triggering. For example in our plugin we have the onItemClick callback which we would like triggered every time someone clicks on a toggle item. We use the .call method to trigger the event listener (if one has been set) .

Lets’s see how this looks:

// called when we click on any of our toggle items
function toggle($item, event){

    // trigger the event listener
    options.onItemClick.call(null, $item, event); 

}); 

What this does is when we toggle our item we pass three parameters. The first parameter is null: we do this so that later when we extend our callback we don’t need to worry about the value of this.

Our second parameter is $item (the toggled element): this is important as it gives the callback function access to the item itself.

Finally our third parameter is our event (the event itself).

The event listener will have access to both the $item and the event and be able to customize your functionality. For example, if we wanted to remove the element when clicked:

$('.my-element').fancytoggle({
    // on click, remove item and log it
    onItemClick: function($item, event){
        $item.remove(); 
        console.log('Removed this item!'); 
    }
});

This is one of the reasons that events are so versatile. They can give the developer access to your plugin at crucial times so they can extend or modify it to suit their needs.

Progressive enhancement

One thing to think about is what happens when JS is disabled. Without it, our plugins won’t work and we will be left with whatever HTML content we started with.

For our example, we are creating toggleable sections with a title and content body (clicking on the title to toggle the body up and down). If we didn’t have JS enabled our content would still work perfectly.

It’s always important to consider these cases.

Where to Go from Here?

Expanding your knowledge

With the basics we’ve covered, you can apply these concepts to your existing code, turning it into easily configurable and extendable plugins that you can drop into your next project. There’s a great wealth of knowledge out there in regards to plugin development. The jQuery website itself has several sections on plugin development that are worth a read.

Digging deeper into the plugin

The best way to expand your knowledge is to look through the code of actual jQuery plugins or to try and create your own. Only after fiddling around will you see how you can take advantage of these plugins to save yourself time.

Our fancytoggle plugin discussed today can be found on our CodePen account. Feel free to fork it and play around with different configurations. You might want to try the following:

  • Add new options to the default arguments (and overriding them)
  • Add additional events to the plugin, such as when the toggle area resizes or after the plugin has initialized.
  • Use the existing events to extend the functionality of the plugin, for example triggering a fade-in animation when a section is opened and then fading it out when closed.

Wrapping It Up: What You Should Have Learned

You should now have a strong grasp of what jQuery plugins are and how you can leverage them to make your development quicker and easier. Here’s a breakdown of what we covered:

  • Adding a plugin to jQuery’s namespace with $.fn
  • Handling multiple collections by looping through them with .each
  • How to create chainable methods (and correctly return it for consistence)
  • How to create default options and merge them with passed in custom values
  • How event callbacks give developers easy access to important parts of a plugin’s functionality
  • Touched briefly on progressive enhancement (considerations for when JS is not available)

Have you created any of your own plugins yet? Do you have some tips on plugin development that you’d like to share? Let me know in the comments!

  • Yashi

    This is awesome.. thank you.

    • simon codrington

      Thanks @disqus_y6cMsbP1RR:disqus for reading. Glad you enjoyed it!

  • Patrik Jarl

    Great article. This made me inspired.

    • simon codrington

      Thanks @patrikjarl:disqus for having a read and posting your feedback. Happy I could help :)

  • Alexander Stepanets

    Good starting point of plugin development, thank you! :)

  • http://facebook.com/jokewd Eduardo Azevedo

    Great article, help me alot!

Recommended

Learn Coding Online
Learn Web Development

Start learning web development and design for free with SitePoint Premium!

Get the latest in JavaScript, once a week, for free.