#28: Building a More Complex Plugin

(Updated on )

Now that we understand the basics of plugin development, we can dig a little deeper. Because ultimately a plugin is a function, it provides us the scope we need to organize. Remember when we got our house in order when we were learning about templating? We can use some of those same concepts in a plugin.

But first, I think jQuery plugin architecture can benefit from some boilerplate code. Perhaps you’re familiar with the HTML5 Boilerplate which provides a bunch of smart defaults. A jQuery Plugin boilerplate is the same kind of thing. Saves some typing and gets you going down a path of smart development.

I came across a project literally called jQuery Boilerplate which I would kinda guess is good. But I haven’t dug into that one much. Instead, I quite like Starter by Doug Neiner. You provide a name, some defaults, and some choices and it will generate that boilerplate structure for you.

We decide to make a slider named lodgeSlider with a simple speed parameter and end up with this code:

(function($){
    $.lodgeSlider = function(el, options){
        // To avoid scope issues, use 'base' instead of 'this'
        // to reference this class from internal events and functions.
        var base = this;
        
        // Access to jQuery and DOM versions of element
        base.$el = $(el);
        base.el = el;
        
        // Add a reverse reference to the DOM object
        base.$el.data("lodgeSlider", base);
        
        base.init = function(){
            base.options = $.extend({},$.lodgeSlider.defaultOptions, options);
            
            // Put your initialization code here
        };
        
        // Sample Function, Uncomment to use
        // base.functionName = function(paramaters){
        // 
        // };
        
        // Run initializer
        base.init();
    };
    
    $.lodgeSlider.defaultOptions = {
        speed: 300
    };
    
    $.fn.lodgeSlider = function(options){
        return this.each(function(){
            (new $.lodgeSlider(this, options));
        });
    };
    
})(jQuery);

A lot of that should look familiar. There is an IIFE wrapping the plugin for safety. There is a function created off the jQuery object. There is an init function called right away. There is a method created off the jQuery object which returns a jQuery object. There are variables created caching references we’re likely to use again. Mostly stuff we’ve seen before.

Perhaps two new things. One is the options object in there. You can see the hard-coded 300 value. But also see the line with $.extend(). That’s a jQuery function to combine two objects into one with one taking precedence over the other. When we call the plugin, perhaps like this:

$("#slider-1").lodgeslider();

We’re passing in no options, and that empty object gets combined with our hard-coded object, and the default values are available inside the plugin. But we could call it like this too:

$("#slider-1").lodgeslider({
  speed: 500
});

We’re passing an object as a parameter there. That object gets combined with our hard-coded object, takes precedence, and the value we passed becomes the value available in the plugin. Pretty cool.

The other new thing is that weird bit with .data(). We created the base variable to reference the function itself, which is created anew for every element the plugin is called upon. For instance, say we called the plugin on $(".slider") – there could be two elements on the page with a class name of slider. The each loop runs, and two instances of the lodgeSlider function are made. In each one, we attach a reference to it to the element itself. That way we can call internal plugin methods from any reference we have of that element.

Like maybe:

$(".the-first-slider").data("lodgeSlider").changeSlide(2);

Just kinda gives us a nice way to use plugin methods if we need to.

We didn’t get tremendously far in this plugin building adventure:

See the Pen Building a Slider from Scratch by Chris Coyier (@chriscoyier) on CodePen

Honestly the world probably doesn’t need another slider plugin. But, you can see how complex they could get. Here’s just a few ideas:

  • There could be callback functions (or custom events) for before and after the slide changes, after the slider is set up, after it is torn down, etc.
  • The widths could be percentage based and recalculate when the browser window changes.
  • The navigation could be build dynamically instead of being required in the markup.
  • The IDs and #hash hrefs could be created dynamically also.
  • Touch events like swipes could be added to make the slider more touch friendly (little dots aren’t touch friendly).

The more of those things you do, the larger the size of the plugin. That’s why striking that balance between features, practicality, performance, and size is so tricky and where there are so many different plugins that ultimately do the same thing.