JavaScript closures and jQuery plugins
Making a jQuery plugin is actually not so difficult that I once thought it was. One thing you need to learn when doing this is closure. If you plan on doing any real JavaScript development, it's time well spent to wrap your hear around this.
Closures
Closures is a technique that's very powerful. The thing about JavaScript, is that there is no name-spaces, all of the code and variables are run in the browser's document. This can give some nasty problems, because you when writing a plugin, you don't know the context where it'll be used. To make it of any use, you have to be certain that you don't overwrite global variables like the $. The way to overcome this is closure. You wrap a function inside parentheses making it a function and consequently invoke it. Doing that, you actually wrap your function inside what's called a lambda function. The tricky part is that you can invoke your lambda function with some params, and they will be used inside your anonymous function. Doing this, you are able to create a memory bubble that wont effect the global name-space. This sounds a bit more harry than it actual is so let's look at the code.
arg1 = 'test';
(function(arg1, arg2) {
// arg1 will have the value of param 1
// arg 2 will be param2
})(param1, param2)
// arg1 is still 'test'
So using this syntax, we declare 2 functions, one inside the other and execute both. what's really handy is that arg1 will not conflict with the global name-space. Changes to arg1 inside the function will manifest as changes to param1. In jQuery plugins you usually want to do it like this:
(function($) {
// ...
})(jQuery);
This will enable us to make code that uses the $ for jQuery, even if the $ is used for something else like prototype outside the scope of the function. The nice thing with this setup, is that we can now extend jQuery inside our function, and it will be manifested to the global jQuery variable. But because JavaScript has a functional scope, all the functions and variables we define inside the anonymous function will be available to the plugin we make, but hidden to the outside. This is one of the very fun things about JavaScript as a language.
After this long rant on closures, we're almost done. jQuery provides us with function we can use to expand the jQuery name-space, creating our own function that can be invoked with .functionName(). Adding this to our code block we get:
(function($) {
$.fn.extend({
plugin: function() {
// ...
}
});
})(jQuery);
This will register the function name plugin that would be called doing something like this $("h2").plugin();
All that is left now, is to actually do the plugin. Another thing worth noting, is that inside the function, this will refer to result of the jQuery selection. This means that what we get already have jQuery attached to it. An example of a small plugin we could make ourselves, it the live binding of the click event. jQuery already has a short hand for the normal binding of a click event .bind("click" fn). But we could make our own for the live version, this is pretty easy and would look like this:
(function($) {
$.fn.extend({
lclick: function(fn) {
// Make sure to only make the binding if the arg is a function.
if (typeof fn == "function") {
this.live("click", fn);
}
return this;
}
});
})(jQuery);
With the code above added, we are now able to do .click(fn) for the normal bind and .lclick(fn) for the live binding of the click event. If we wanted to we could also add the execution of the event when no params are presented. That could be done as an if statement when fn is undefined. Another thing to note, is that I am returning this in the lclick function. This is to allow us to chain the events, so we can do $(selector).lclick().show()... which is one of the very nice things about jQuery.
This "plugin" is not as powerful as many of the very nice jQuery plugins that have been made. But I hope I have illustrated that making your own plugin, isn't that difficult, and can actually be done quite easily. Sometimes you might want to convert some of your usual javascript function into plugin, if you tend to use that block of code a lot. It'll also make it easier to manage your code afterward.
Good luck with those plugins!
Add new comment