Friday, July 22, 2011

jQuery UI Widget Selectors

Widgets in jQuery UI have their own selectors.  These selectors allow the developer to select widgets by type.  For example, if you want to select all progressbar widgets, you can do this.  The selector for a specific widget type is similar to other element selectors you'd use with jQuery.  For example, you can say :button to retrieve button elements.  This same approach is used with jQuery widgets.

Each widget selector is constructed and added to the core jQuery set of expressions.  It does so by taking the name space, in this case, ui, and combining it with the widget name.  So we can make queries such as :ui-tabs or :ui-progressbar.  This is a great approach - we know that we're only retrieving elements that are real jQuery UI widgets.  There is a problem though.  It's slow and can't be used universally throughout all jQuery UI has to offer.

For example, I used the following to benchmark the widget type selector:

var iterations = 100;
var start = new Date().getTime();
for (i = 0; i < iterations; i++) {
    $(':ui-tabs');
}
var end = new Date().getTime();
console.log(end - start);

Notice we're using the : character in the selector - this invokes the selector built by the base widget.  However, to get a feel for how relatively slow this operation is, try replacing the : with . so you end up with $('.ui-tabs').  Notice the performance difference?  So why would anyone in their right mind use this widget selector?

The rationale behind such a selector is that you should be able to select all widget types base on, well, their type.  Think of a class method in Python or Java that will return all instances of that class.  It's an intuitive leap to transform "get me all accordion widgets" into :ui-accordion.  This way, it becomes a standard query format for widgets - namespace (ui) and widget name.

So what is wrong with using the class selector variant to retrieve all widgets belonging to a specific class?  Nothing aside from the fact that we can't be absolutely certain of widget class names.  For instance, if another UI developer on your team were to build a widget, and you now write some code that wants to grab them all.  You'd have to know ahead of time, or do some investigation work, to figure out which class is applied to every widget of that type.  Well, not necessarily.

You'll notice that you can use the class-based variant of the above query to retrieve all widgets of a specific type for every jQuery UI widget.  For example, .ui-tabs, .ui-progressbar, .ui-button, all these queries work fine and they're much faster than the widget selector that automatically extends the UI core for every widget - .ui-tabs is much faster than :ui-tabs.

You'll also notice that the naming in CSS classes applied to the widgets are all consistent.  This CSS class naming schema doesn't only have a role with themes - we can use this consistent convention to actually speed-up our code.