Providing Options in jQuery Plugins

By Ryan Florence, published 2010-10-05

Part of the issue Thoughtful jQuery Plugin Development.

Nothing new or extraordinary here, but I run across enough jQuery plugins that don’t provide options to warrant writing an article about it. You can meet a lot more use cases for your plugin if you provide the developer with some options.

Here’s a plugin called disables that I recently wrote for a project. It disables form elements based on the value of another, a checkbox by default.

(function($){
  
  // add it to the jQuery prototype
  $.fn.disables = function(selector, options){
    // set options, YES!
    options = $.extend({}, defaults, options);
    // cache els
    var els = $(selector);

    // check if the attribute of my element matches what I'm looking for
    // and then disable or enable the subject elements accordingly
    var test = function(){
      var isEqual = $(this).attr(options.attr) == options.expected;
      els.attr('disabled', isEqual);
      // fire an optional function for kicks
      options.onChange.apply(this, [isEqual, els]);
    };

    // keep the chain alive and bind the events
    return this.each(function(){
      $(this).bind({
        change: test,
        keyup: test
      });
    });

  };

  // create some sane defaults, please and thank you
  var defaults = {
    attr: 'checked',
    expected: true,
    onChange: function(){}
  };  

})(jQuery);

Take a look at line 6. The extend method merges the defaults with the user supplied options, giving precedence to the options. Now look at var defaults on line 30. It’s important to choose sane defaults. By providing these defaults, and merging them with the developer’s options, the developer has the ability to use this plugin in a number of different scenarios.

    // ex. 1
    $('#my-checkbox').disables('.some-group-of-elements'); // uses defaults
    // ex. 2
    $('#my-input').disables('.group', {
      attr: 'value',
      expected: 'dog' // disables when a text input value is 'dog'
    })
    // ex. 3
    $('#my-checkbox').disables('.group', {
      onChange: function(isEqual, els){
        els[((isEqual) ? 'add' : 'remove') + 'Class']('disabled'); // adds or removes disabled className
      }
    });

There’s something not right here …

Because the defaults are tucked behind a self-invoking anonymous function, this plugin is not as flexible and reusable as it could be. Imagine you wanted every instance of disables to behave like ex 3. You’d have to copy and paste that onChange code block every time (lines 10-12). Or, you hack the source, and I really hate doing that

Instead, plugin developers could use the $.fn namespace, let me show you what I mean here.

Hi, I'm Ryan!

Location:
South Jordan, UT
Github:
rpflorence
Twitter:
ryanflorence
Freenode:
rpflo

About Me

I'm a front-end web developer from Salt Lake City, Utah and have been creating websites since the early 90's. I like making awesome user experiences and leaving behind maintainable code. I'm active in the JavaScript community writing plugins, contributing to popular JavaScript libraries, speaking at conferences & meet-ups, and writing about it on the web. I work as the JavaScript guy at Instructure.