A jQuery Development Pattern
After dealing with jQuery for about 7 months, I’ve finally settled into my own style of plugin development. This article will discuss what I feel are the shortcomings of the current jQuery development pattern, and my alternative: the class based plugin development pattern.
Shortcomings of the Current Plugin Pattern
The Plugin Pattern Clutters the Arguments
It’s not uncommon to see a plugin that takes multiple objects and multiple anonymous functions in as arguments. The result is extremely cluttered, borderline unreadable syntactical soup. For instance, take this example, provided in the documentation of the most popular jQuery validation plugin:
$("form").validate({
invalidHandler: function(e, validator) {
var errors = validator.numberOfInvalids();
if (errors) {
var message = errors == 1
? 'You missed 1 field. It has been highlighted below'
: 'You missed ' + errors + ' fields.';
$("div.error span").html(message);
$("div.error").show();
} else {
$("div.error").hide();
}
},
onkeyup: false,
submitHandler: function() {
$("div.error").hide();
alert("submit! use link below to go to the other step");
},
messages: {
password2: {
required: " ",
equalTo: "Please enter the same password as above"
},
email: {
required: " ",
email: "Please enter a valid email address, example: you@yourdomain.com",
remote: jQuery.validator.format("{0} is already taken, please enter a different address.")
}
},
debug:true
});
As the code user’s needs grow, so does the complexity of the plugin instantiation. It’s easy to get lost in the sea of curly braces, especially once conditional statements and objects within objects are thrown into the equation. From lines 19-23, you can see that the plugin actually goes 3 layers deep in objects.
Solution
Keep the plugin instantiation for the most basic settings. Use public methods to take care of the more complex customizations. The easiest way to accomplish this adjustment is to use JavaScripts “new” operator in conjunction with some object-oriented principles. If the plugin had been authored using a class(prototype) model, the equivalent configuration would look like so:
var form = new validate("form",
{
onkeyup: false,
debug: true
});
form.invalidHandler(function(e, validator)
{
var errors = form.numberOfInvalids();
if (errors)
{
var message = errors == 1
? 'You missed 1 field. It has been highlighted below'
: 'You missed ' + errors + ' fields.';
$("div.error span").html(message);
$("div.error").show();
}
else
{
$("div.error").hide();
}
});
form.submitHandler(function()
{
$("div.error").hide();
alert("submit! use link below to go to the other step");
});
form.message("password2",
{
required: " ",
equalTo: "Please enter the same password as above"
});
form.message("email",
{
required: " ",
email: "Please enter a valid email address, example: you@yourdomain.com",
remote: jQuery.validator.format("{0} is already taken, please enter a different address.")
});
The separation of handlers and basic configuration promotes readability and organization. Additionally, the start and end of configuration options are now explicitly clear. Adjusting or removing configurations would be extremely easy. These conveniences also extend to the plugin source itself.
Many Complex Plugins Simply Do Too Much
As a plugin becomes increasingly complex, it becomes increasingly difficult to preserve the reason why plugins are developed in the first place: ease of use in projects. Remember that the plugin should conform to the wishes of the developer, not the other way around. Many plugin developers strive to make their plugin work with an empty argument call, such as $(“selector”).myplugin();. There’s an underlying notion amongst developers that an empty argument call equates to ultimate ease of use, and this is rarely the case. A complex plugin with an empty argument call usually means the code user has to alter large quantities of HTML and/or CSS. At that point, the zero argument call is nothing but meaningless flare. Notice my emphasis on “complex plugins”. A simple plugin, such as a plugin that fades in elements in sequence, could benefit greatly from an empty argument call. My main point is
Do not devoid the plugin user of all responsibility.
If you adequately document your plugin, it is up to the plugin user to implement it correctly. There are going to be some developers that will fail to use your code successfully. That’s okay. What’s not okay is absolving the plugin user of responsibility to the extent that they can no longer customize the plugin implementation to fit their specific needs. No one knows the full capabilities of their code. I’m sure John Resig, creator of jQuery, has been surprised at what’s been created by the development community with his code. You might think the plugin you’re authoring is only good for a certain situation, but another developer with a different mindset might find it useful in another situation. The moment you hard-code your situation into the plugin, you eliminate other, possibly better, ideas.
The ultimate goal of your plugin should be to make a developer’s idea easy to execute. That idea might be brilliant. That idea might be terrible. Either way, your job is to make that idea simple to put in motion.
Class Based Plugin Development Pattern
Now that we’ve discussed the shortcomings of the current plugin development pattern, lets discuss an alternative: the class-based plugin development pattern.
This pattern requires you to know the object oriented basics of JavaScript. Whether you decide to implement this pattern or not, I highly encourage you to learn the object oriented fundamentals found in that article.
Defining the Plugin
Defining the plugin with the class-based pattern is similar to the normal plugin pattern.
Normal plugin pattern:
jQuery.fn.myPlugin = function()
{
//Code stuff goes here!
};
Class-based plugin pattern
function myPlugin()
{
//Code stuff goes here!
}
Function Header and Default Values
Since you’re creating a plugin, chances are you’re wanting to manipulate an element that can be represented by a jQuery selector. Thus, the most natural function header is
function myPlugin(obj, options)
{
//Code stuff goes here!
}
Where obj represents the jQuery selector or jQuery object for the element(s) you wish to manipulate, and options is an object with properties that will be used in the plugin.
This brings up a question: Why not have obj just be a property of options? In many instances, you want default values to be values associated with the CSS properties of the elements in question. However, object members can’t refer to other object members in the definition of the object. This is simply because at the time the object is being populated with values, it does not yet exist to refer to itself.
var test1 = {val1: 10, val2: 5+test1.val1};
alert(test1.val2); //Error, val1 undefined
var test2 = {val1: 10, val2: 5+val1};
alert(test2.val2); //Error, val1 undefined
var test3 = {val1: 10, val2: 5+this.val1};
alert(test3.val2); //Error, val2 Not a number
For default values, jQuery extend works perfectly. Lets say our plugin options takes in 3 properties: x, y, and z. jQuery extend allows us to fill in our options with default values in the event they aren’t specified in the function call.
function myPlugin(obj, options)
{
//------------------------------------------------------------
// Set default property values
//------------------------------------------------------------
var defaults = {
x:0,
y: 0,
z: 0
}, settings = jQuery.extend(defaults,options);
}
The settings object is the options object populated with the values of default in the instance a value from options is missing. For example, if we passed in {x: 5, y:10} as our options object, settings.x would be 5, settings.y would be 10, and settings.z would be 0. Since z was not specified in the options object, the value of z associated with the defaults object was placed in the settings object.
Throughout the plugin, you should refer to the option values via the settings object.
Constructor Methods
If you have any events that you would like to take place once the plugin is initiated, you should have those executed immediately after declaring your default values. For example, if we wanted to make our jQuery selected object have an absolute position at coordinates (x,y),
function myPlugin(obj, options)
{
//------------------------------------------------------------
// Set default property values
//------------------------------------------------------------
var defaults = {
x:0,
y: 0,
z: 0
}, settings = jQuery.extend(defaults,options);
//Do this immediately
$(obj).css({'position': 'absolute',
'left': settings.x,
'top': settings.y});
}
Private Methods and Properties
Private methods are functions that can only be called within the plugin definition. Similarly, private properties are properties that can only be accessed within the plugin definition. Private methods are useful for calculations and callbacks. Private methods promote readability for those viewing/maintaining the code. Since JavaScript exhibits function scope, private methods and properties can be created by simply using the “var” statement.
function myPlugin(obj, options)
{
//------------------------------------------------------------
// Set default property values
//------------------------------------------------------------
var defaults = {
x:0,
y: 0,
z: 0
}, settings = jQuery.extend(defaults,options);
//Do this immediately
$(obj).css({'position': 'absolute',
'left': settings.x,
'top': settings.y});
//Cannot be accessed by calling environment
var callback = function()
{
alert("Callbacked!");
};
}
Public Methods
Public methods are functions that can be accessed by the calling environment. Notice that public properties are not listed, as most of the time public properties are poor programming practice. You don’t want the values inside the plugin to be altered by the outside without validation.
Public methods are extremely useful for initiating actions, setting values, validation of arguments, and my personal favorite, altering callbacks. To make a method public, you attribute it to the plugin itself with the “this” keyword.
Lets say we want our plugin to allow the user to move the elements in the selected jQuery object to a certain coordinate. After the element has moved, we want a custom callback to occur.
function myPlugin(obj, options)
{
//------------------------------------------------------------
// Set default property values
//------------------------------------------------------------
var defaults = {
x:0,
y: 0,
z: 0
}, settings = jQuery.extend(defaults,options);
//Do this immediately
$(obj).css({'position': 'absolute',
'left': settings.x,
'top': settings.y});
//Cannot be accessed by calling environment
var callback = function()
{
alert("Callbacked!");
};
//Replace the callback with a custom callback
this.callback = function(func)
{
callback = func;
};
//Animate the element to a coordinate, then do the callback
this.move = function(x,y)
{
//Make sure the values are positive.
x = Math.abs(x);
y = Math.abs(y);
$(obj).stop(true,true).animate({'left': x, 'top': y}, 500,
function() {
callback();
});
};
}
Calling the Plugin
Now that we have our Plugin defined, it’s time to call it. Plugins under this pattern will be called using the “new” operator, and it must be assigned to a variable. While this might feel awkward at first, you’ll grow comfortable with this instantiation over time.
var item = new myPlugin("#box",
{
x: 20,
y: 30
});
Once this statement is executed, the constructor of the plugin occurs. Thus, the element with a div ID of “box” will be positioned absolutely with left value at 20 and top value at 30.
In order to access public method, use the “.” operator along with the name of the variable used.
$(document).ready(function()
{
var item = new myPlugin("#box",
{
x: 20,
y: 30
});
var x = 0;
var y = 0;
//Alters the default callback function
item.callback(function()
{
$("#box").html("Left: " + x + "<br />Top: " + y);
});
//Moves box when clicked
$("#box").click(function()
{
item.move(x, y);
x += 10;
y += 10;
});
});
Demo of our little plugin
So we’ve spent some time creating this little plugin, and you might be attached after all this work. I understand! Feel free to view this plugin in action and download the source code.
Note how our plugin by itself is not hard-coded to move the element every time it’s clicked and display the coordinates in the element. All that was done outside of the plugin. It’s that type of versatility that makes me really enjoy this development pattern.
A Real Example
To see this development pattern in action, check out my jQuery sticky scroller plugin.
Feedback
If you have any feedback or suggestions, please leave them in the comments below!
Related Posts:


Two words… “utterly brilliant” so stealing your pattern!
Thanks Josh! Please link us to a project when you implement the pattern!
Hey Joe,
First of all, I really appreciate how much you tend to question “the norm” and really hope you do blog more this year. 365 times is going to be a marathon, but good luck – you put out some sweet content, man.
As far as this article is concerned, the part that really stuck with me was “A complex plugin with an empty argument call usually means the code user has to alter large quantities of HTML and/or CSS. At that point, the zero argument call is nothing but meaningless flare.” and I couldn’t agree more. This actually goes against my typical (plugin) development style… but I agree with you nonetheless.
Chances are, you created a site’s content first, then appearance, then interaction. So, typically, the JS is late to the game. Those plugins with empty argument calls require the developers to basically always restructure their code to be suitable for the plugin, which as you mention, is a pain in the ass sometimes (especially after you’ve styled it & gotten other JS scripts/functions working on it). I’m totes going to steal your dev pattern here, but am interested in seeing how that affects my workflow – if/how much it will slow it down & such. Like you said – plugins are meant to work for the developer, not vice versa.
I think we need to find the balance of a “personal plugin”, if you will, and a “public plugin”. Like you said, John Resig probably had no idea that jQuery would grow to be the most widely used JS framework in the world. I feel like we, as developers, also need to keep that in mind, but not let it DRIVE the development. Just pointing it out…
Like Josh said though – this is one of the best posts I think you’ve written. Keep it up man!
Hey Connor. Thanks for taking the time to reply.
My main philosophies concerning coding are reusability and patience. While creating plugins, I take the time to make sure they provide all the tools necessary for a great implementation. If you’ve looked at any of my source, you’ll see that I comment the hell out of everything as well. I just want to be sure that when it’s crunch time and I’m actually doing client work, implementing a plugin will take only as much effort as the complexity of my ideas. That philosophy might not work for everyone.
Thanks again for reading!
I guess I don’t see how this offers any advantage over the following:
var opts = {}; opts.invalidHandler = function() {...}; opts.onkeyup = false; opts.submitHandler = function() {...}; opts.messages = {...}; opts.debug = true; $("form").validate(opts);This then keeps to jQuery’s chainable philosophy, and the code seems equally clean.
What am I missing?
— Scott
Hey Scott, appreciate you stopping by.
I think in more complex situations, chain-ability is not necessarily essential. For simple plugins, chain-ability is great! However, you begin to experience large diminishing returns as the scope of the plugin increases. The line between simple and complex is, of course, arbitrary, and it’s all a matter of judgement and opinion. Personally, I’m not a fan of passing a constructed object into a function. It seems sloppy, and clutters up the calling environment. In the event you’re calling more plugins in that style, you’d have to have opts1, opts2, etc.
And you’re missing the ability to implement public methods to return valuable pieces of data. Unless there is some way to attribute accessors/mutators directly to jQuery objects. Then I’d be happy to see a demo!
Thanks again!
I wasn’t trying to claim a great benefit for chainability; in fact, I think it’s overused. But it is a part of the jQuery culture that I wouldn’t want to disturb without good reason.
I’ve thought a fair bit about how to do a plug-in that preserves chainability but also allows for additional method calls, and in the end, I can’t come up with anything that works better than what jQuery UI does. It’s not something I like very much, but it is workable, and will probably have to do until something else comes along.
That uses code like
$("#birthdate").datepicker(opts); // ... $("#birthdate").datepicker("setDate", "08/04/1961").someFancyHighlightPlugin(); // ... var birthday = $("#birthdate").datepicker("getDate");In this pattern, an initial string parameter to the plugin is the name of a method to call. Any additional parameters are then supplied as parameters to that method. If the method doesn’t have an explicit return value, it returns the jQuery wrapper and the chain can continue.
As I said, I’m not thrilled with this, but I can’t find anything better that still maintains chainability.
If we skip the chainability, then it’s very easy to have
$(selector).myPlugin(opts)return an object with methods; there are plenty of patterns that will work there. And I’ve found techniques that will let me do, for instance,
$(selector).myPlugin(opts); // ... $(selector).myPlugin().myMethod(args);which is relatively close to what I want, but which has its own chaining issue.
I guess what I don’t see in your code is anything that makes it a “jQuery” development pattern. It’s simply one of the many ways to do some OO-style programming in JS. The only thing that relates to jQuery is that you use one parameter to your constructor to create a jQuery wrapper object you then can reuse. That’s not really a pattern for the use of jQuery.
Your last example seems a bit cumbersome. Having to call a variable name to access the public method is one thing. Having to call the selector, the plugin, and then the method seems to be a bit much.
I can appreciate your semantics in regards to the term “jQuery Development Pattern”. Indeed, I’m completely disregarding the .fn interface, so my pattern by definition does not consist of “jQuery plugins”. It’s simply the use of jQuery’s power in an OO pattern. An “anti-pattern” pattern, if you will.
And I have no problem deviating from jQuery “culture”. This is my preferred style, and people are free to accept, reject, or alter it as they please. The pattern, while possibly against your own definition of “jQuery pattern”, solves the problem of clutter, cumbersome method calls, lack of customization, and an overall lack of readability. It’s different, but that’s okay. The developers looking for something different may enjoy using the pattern, regardless of what terminology is used to encapsulate what exactly the pattern is.
Is it a “plugin pattern”? Is it a “jQuery pattern”? Those questions don’t really mean much to me. “Does this style help me solve problems?”: That’s really the only problem I’m concerned with. If this pattern successfully enhances the organization and/or readability of someone’s code, it’s fulfilled the only purpose I’ve intended it to have.
Thanks a ton for the great input Scott!
Of course you shouldn’t feel obliged to slavish participate in the jQuery culture. I was just assuming from your title that you meant this as a suggested way of working with jQuery.
You’re right that the previous example was cumbersome. The advantage is that one can pick up where the system left off, not storing a local reference to the datepicker object if your code make it difficult to do so. You can get it back through calling .datepicker() on the jQuery wrapper again. (For most code, I would recommend that you cache the jQuery reference, but there are times when this in too inconvenient.)
There are lots of interesting OO patterns out there. I posted one recently. [1] My only objection to what you’re suggesting is that if you create a lot of objects with these constructor functions, you’re wasting a lot of memory as each one will get its own instance of each of the public and private functions. They wouldn’t share anything. That might or might not be a concern for you.
Nice work, though. Please keep it up.
[1] http://scott.sauyet.com/thoughts/archives/2011/01/04/no-classes-in-javascript/
That’s a good point concerning the redundant declaration of functions. As an alternative, would you create the functions separate in such a way that you pass the “this” scope as an argument? That seems like the only way you could create functions only once while still being able to refer to public properties.
The nature of web development is pretty sloppy overall, mainly because we’re spoiled when it comes to memory. I’ll be sure to check out your pattern when I get a chance.
That would be one way to do it. And the pattern I mentioned does something similar: the functions are wrapped in a closure to keep them private; I use Function.call passing the objects rather than making the functions accept the object parameter, but that is still it in essence.
An alternative would be to use prototype methods. Private methods would be called as above, but public ones would be defined as
MyConstructorFn.prototype.method = function(…) { … };
But often these OO layers are not really needed in JS, in my opinion. I usually try to use it more like a functional language.
Interesting conversation. Thank you.
Hi. Probably this reply is kind of late for this post (I can’t find when it was authored, but I guess a long time ago), but I wanted to say thanks for this writing.
I’m dealing with a jQuery plugin that I’ve “inherited” from previous developers, and I’ve been having lots of headaches with it. I had to extend it to provide both public and private functions, and the techniques I’ve been using have proven to be wrong.
I tried to avoid the way it’s suggested on the Plugins/Authoring page of the jQuery Docs, because I thought passing a string that represents the method to be invoked quite ugly and hackish (although I might end up using it). I think that I like more your solution, even thought it makes chainability not possible and technically that makes the code not a jQuery plugin, which I think is great many times, but very overrated for some other situations.
Thanks for the ideas and the discussion afterwards.