Advanced Javascript By Example: A First Look Inside JQuery UI
Note: This is not a tutorial for the jQuery UI. This is a look at the code of the UI itself in hopes of better understanding javascript and some techniques jQuery developers use to craft better code.
Efficient learning takes place when there is a master involved in the process. It’s simply much faster to learn and assimilate knowledge and technique when we “see it in action”. One observes the master at his craft and tries to imitate his or her action. In doing so, much is gained. Following this learning paradigm, let’s see what we can learn from the javascript masters over at jQuery.
Now we’re not going to be so presumptuousness as tackle the core jQuery library. We’ll start with something a little more manageable and fresh, the new jQuery UI. In particular we will look at the file ui.core.js which provides some of the basic functionality of the UI. Before proceeding, I suggest you get the code and take a look at it first.
Very well, now let’s see what we can make of the code. First, let’s look at what the code is wrapped in.
;(function($) { /* bunch o' code */ })(jQuery);
Now looking at this piece of code… Whoa, what’s that semicolon doing there! We’re usually accustomed to seeing semicolons at the end of a line. Out of place and pointless as it might seem, it actually can be quite helpful. Some web applications in production try to package your code together with other scripts to speed up downloads (the more curious can read on at semicolon at the start of jQuery). Putting a semicolon at the beginning assures that the script proceeding yours will be tied off nicely regardless of how the scripts are concatenated together.
Next we notice that the code is wrapped in some sort of anonymous function. Before we address why this is the case, first let’s ascertain what’s going on. Consider a simpler example…
( function(message) { alert(message); })('Peek-a-boo');
If you were to run this, you see a pop-up with ‘Peek-a-boo’. This bit of code creates a function and then calls it. Going back to the UI code, we see that everything was wrapped in an anonymous function and then it’s called right away, being passed the jQuery object.
Now, why would we want to do this? The rationale is to prevent conflicts with other libraries. The “$” is a shortcut that some other libraries also employ. By encapsulating the code in an anonymous function we create a local scope. The “$” which exists in this local scope (since its the function’s argument) will take precedence over any global “$” floating around. Becasue we pass the jQuery object to the anonymous function, we can be assured that any reference to “$” in this code refers to the jQuery object and not something else.
Moving on, next we see the $.ui object.
$.ui = { plugin: { add: function(module, option, set) { var proto = $.ui[module].prototype; for(var i in set) { proto.plugins[i] = proto.plugins[i] || []; proto.plugins[i].push([option, set[i]]); } }, call: function(instance, name, args) { var set = instance.plugins[name]; if(!set) { return; } for (var i = 0; i < set.length; i++) { if (instance.options[set[i][0]]) { set[i][1].apply(instance.element, args); } } } }, cssCache: {}, css: function(name) { if ($.ui.cssCache[name]) { return $.ui.cssCache[name]; } /* ... */ }, hasScroll: function(e, a) { /* .... */ if (e[scroll] > 0) return true; e[scroll] = 1; has = e[scroll] > 0 ? true : false; e[scroll] = 0; return has; } };
The $.ui object is defined using something akin to JSON. At it’s heart, this notation is nothing more that a list of name/value pairs. The names are, well, the names and the values can be literals, functions or objects. From the code, we can see that $.ui.plugin is an object that has two methods, add and call. $.ui.cssCache is initialized to be an empty object and $ui.css is a method.
That’s it for this first edition. Next time, we’ll look at the widget factory and try to understand factories and prototyping.


