1024px-Flatirons_Winter_Sunrise_edit_2

Note: This is the first in a two part series on creating your first plugin. In the series, we’ll create a plugin that will be able to handle displaying and also queuing a series of a messages for the user.

Plugin prerequisites: overcoming myths and challenges

As a enterprise web developer I often found it challenging to shift my mindset from JavaScript coder towards plugin creator. Not that those opportunities weren’t there. Rather, I was stifled by a few factors that many enterprise developers face:

Code ownership and licensing concerns

Writing software that you are planning to release as open source can often conflict with corporate policies. Given that you are already using jQuery, the organization should already have some understanding of licensing policies. Or, at the very least, the organization has some trust in their developers understanding licensing policies.


Publishing plugins under open source licensing is something that most enterprises today should accept. However be sure to do due diligence with your superiors. Some points I would recommend making:

  • Explain to them the power of the open source community. Developers giving back to the community is part of its strength.
  • jQuery is making you a lot more productive. Giving back should be part of paying it forward.
  • Point to plugins you have been able to use in your own development.
  • Point out that you can garner feedback for your plugin which can help identify bugs and create a better solution for the enterprise.

As a worst case, plugins can be used as a pattern and not released as open source.

The “plugins are complex” myth

> Plugin developers are senior front-end web developers. Any typical plugin is without a doubt something I can never write. Additionally the most useful plugins must be quite complex.

My naivete was quickly broken when I did a little investigation.

Plugins are written by people who want to give back to the community. Newer developers are included in that group.
Many useful plugins are not that complex in code. Some are fairly complex. Here are a few examples from the same developer. These are plugins I have used in code:

I’d assert that all three of these plugins are incredibly useful. Yet only one has a high level of complexity.

Lack of ability to recognize code that could be a candidate for a plugin

On your path from a enterprise web coder to developer, this should be one of your goals. Identifying patterns that can be abstracted into plugins are a key to your journey to that ‘senior’ level. We’ll see utility libraries as another possibility for code reuse. But in both cases identifying a pattern is key.

Starter Code

Lets get rolling. Here is code I’ve seen in enterprise code used today. This is an implementation of the incredibly popular “flash message” or “message center” you see on sites like twitter and stack overflow:

[js] $(‘#flashMessageCenter’)
.html(‘message for the user’)
.addClass(‘info’)
.click(function(){
$(this)
.slideUp(1000,function(){
$(this).removeClass(‘info’);
});
})
.slideDown(1000);[/js]

Live jsbin demo

Super. This code seems to work pretty well, and took almost no time to write. The power of the jQuery side of the force…

This is where the light bulb needs to start going on. What are we doing here? We are displaying messages via some sort of message center for the user. Why not make this into something repeatable?

Generalizing the Code

We are going to travel a road to get to the plugin in order to bridge some common knowledge gaps. Lets start with a function that can take in some parameters.

[js] var flashMessage = function(message, levelClass, animationSpeed) {
if(message && levelClass && animationSpeed) {
$(‘#flashMessageCenter’)
.html(message)
.addClass(levelClass)
.click(function(){
$(this)
.slideUp(animationSpeed,function(){
$(this).removeClass(levelClass);
});
})
.slideDown(animationSpeed);
}
}[/js]

It would be better if we had defaults :

[js] var flashMessage = function(message, levelClass, animationSpeed) {
levelClass = typeof(levelClass) === ‘string’
? levelClass
: ‘info’;
animationSpeed = typeof(animationSpeed) === ‘number’
? animationSpeed
: 1000;
if(message) {
$(‘#flashMessageCenter’)
.html(message)
.addClass(levelClass)
.click(function(){
$(this)
.slideUp(animationSpeed,function(){
$(this).removeClass(levelClass);
});
})
.slideDown(animationSpeed);
}
}[/js]

Live jsbin demo

But wait, a bug already! Pay close attention to the .slideUp animation in the demo page. It’s always fast? Why?

We are attaching a new click handler each time this method is called. What we really want to happen is to attached the handler, let it run once, and then remove it. The next time the flashMessage is called a new handler will be attached with the new set of parameters. Fortunately jQuery gives us a shortcut to do exactly that:

[js] var flashMessage = function(message, levelClass, animationSpeed) {
levelClass = typeof(levelClass) === ‘string’
? levelClass
: ‘info’;
var animationSpeed = typeof(animationSpeed) === ‘number’
? animationSpeed
: 1000;
if(message) {
//our message center div id
$(‘#flashMessageCenter’)
//replace html with the message
.html(message)
//add the appropriate class for the message level
.addClass(levelClass)
//click to close the message.
//remove the handler once it has run.
.one(‘click’,function(){
$(this)
.slideUp(animationSpeed,function(){
//this will remove the Class
//once slideUp is complete
$(this).removeClass(levelClass);
});
})
.slideDown(animationSpeed);
}
}[/js]

We have a function that we can use to flash messages. But we can spruce this up even more.

I’m a huge fan of using object literals for parameter inputs. It will allow you to scale out your plugin in the future as thousands of people beg you to expand its functionality.

Again jQuery comes through. This time a utility function is our helper $.extend(). We can use $.extend() to merge an input object literal with a set of default object literals. Awesome!

[js] var flashMessage = function(params) {
//use extend to merge input parameters and defaults.
//use an empty object literal first as it
//is overwritten by the extend method.
var settings = $.extend(
{},
{
levelClass : ‘info’,
animationSpeed : 1000
},
params);
if(settings.message) {
//our message center div id
$(‘#flashMessageCenter’)
//replace html with the message
.html(settings.message)
//add the appropriate class for the message level
.addClass(settings.levelClass)
//click to close the message.
//remove the handler once it has run.
.one(‘click’,function(){
$(this)
.slideUp(settings.animationSpeed, function(){
//this will remove the Class
//once slideUp is complete
$(this).removeClass(settings.levelClass);
});
})
.slideDown(settings.animationSpeed);
}
}[/js]

Live jsbin demo

Notice that we don’t specify a message in our default object literal. We expect the user to pass in the message to the function.

Time for a plugin!

We are so close. We have a function that can be used. It takes in a sweet object literal. It also does two things that aren’t so nice:

  • We are polluting the global namespace
  • We are hard coding our selector for the flash message

Lets eliminate both at the same time. And produce our first plugin:

[js] (function($,undefined){
$.fn.myFlashMessage = function(params) {
//use extend to merge input parameters and defaults.
//use an empty object literal first as it is
//overwritten by the extend method.
var settings = $.extend(
{},
{
levelClass : ‘info’,
animationSpeed : 1000
},
params);
if(typeof(settings.message) === ‘string’) {
//our jQuery object
this
//replace html with the message
.html(settings.message)
//add the appropriate class for the message level
.addClass(settings.levelClass)
//click to close the message.
//remove the handler once it has run.
.one(‘click’,function(){
$(this)
.slideUp(settings.animationSpeed, function(){
//this will remove the Class once
//slideUp is complete
$(this).removeClass(settings.levelClass);
});
})
.slideDown(settings.animationSpeed);
}
}
})(jQuery);[/js]

Live jsbin demo

A few more topics we just introduced:

We are using a self invoking anonymous function to create a plugin. That’s this pattern:

[js] (function($, undefined){

})(jQuery);
[/js]

The code creates a function without a name (not polluting the global space), and then immediately executes it. There are a few reasons to use this pattern. In our case, we use the function so the we can use the ‘$’ to mean ‘jQuery’, even if the ‘$’ variable is assigned to something else outside of this function. We also have a parameter ‘undefined’. Although we aren’t yet using ‘undefined’ in code yet I’ve added it for future revisions. Adding ‘undefined’ (yet passing in nothing as the parameter when executing the function) allows us to make sure someone didn’t do this sort of funny business in javascript previous to our function execution:

[js] undefined = "I’m defined now!!!"; //legal
[/js]

Next we have the actual assignment of the jQuery plugin:

[js] $.fn.myFlashMessage = function(params)
[/js]

This line assures that any future instance of the jQuery object will have access to that method. It’s a plugin. Nice!

Also looking at the code again I realized I could make a better comparison of the message by making sure it is of a type string.

And there we have it! A complete plugin.

In the next in the plugin post series we are going to continue to expand our plugin, including:

  • Utilize queuing to retrieve and show multiple messages
  • Automatically close the message center if not clicked in a certain time period
  • Fix a few quirks we find in the current plugin