The JavaScript Library World Cup

Love them or loathe them, JavaScript libraries are making a huge impact in the area of DOM Scripting. As AJAX matures, and the complexity of the scripts required to support its expanding use increases, it becomes much less feasible to produce custom code from scratch for every project.

In addition, the growth of AJAX and the burgeoning interest in Web 2.0 applications is bringing many new people to the field. Not surprisingly, they don’t want to spend the long, hard years absorbing the arcane knowledge required to wrestle with browser bugs and API differences.

Whether you’re an old-school DHTML guru or a Web 2.0 wannabe, it’s time you got to know some libraries. So, what’s out there? I’m glad you asked!

Over the past year or so, as DOM Scripting has exploded in the mainstream coding arena on the back of AJAX, a seemingly endless number of JavaScript libraries have joined the list of contenders. Fortunately for our poor brains, there are four libraries that have emerged as the clear forerunners in terms of their levels of adoption, documentation and community support:

  • Dojo, a powerful library developed primarily off the back of JotSpot
  • Prototype, the backbone of Ruby on Rails excellent AJAX support
  • Mochikit, the Python library that makes JavaScript suck less
  • Yahoo UI Library (often shortened to just YUI), the new kid on the block

Of these four, there is no clear front-runner yet. Each library differs enormously from the others not only in features, but in less tangible aspects like ease-of-use, community support and philosophy. One of the most important factors in choosing a development platform is how well its philosophy fits with the way that your brain works.

In this article, I’ll examine each library to help you decide which one best suits your development style and project needs. While it would be impossible to cover every aspect of each library, I’ve done my best to cover the highlights of each of them, as well as give some insight into how they handle the bread-and-butter tasks of DOM manipulation, event handling and AJAX.

1537_dojo

Dojo

Dojo is maintained by lead developer Alex Russell — who recently announced that he would be working on Dojo full time — and a group of around 30 core contributors. The library is primarily funded by Jot, creators of JotSpot, a souped-up Wiki engine.

Dojo can be downloaded from the Dojo site in several editions. Each edition bundles certain parts of the Dojo library into one JavaScript file, and allows you to load other parts of the library dynamically using Dojo’s import mechanism. The most popular edition of Dojo is the AJAX edition, which weighs in at around 132K in its compressed form, and includes support for asynchronous I/O operations (for AJAX calls), visual effects, event handling and the Dojo base libraries.

Loading additional functions on top of an edition of Dojo is easy. If you wanted to add the crypto library, for example, you would write the following:

dojo.require("dojo.crypto.*");

However, for performance reasons it’s best to choose your edition well, based on the needs of your project, and to avoid requiring extra libraries in this fashion.

Dojo definitely has the widest scope of the four libraries in terms of features, and pays more attention to tackling performance issues and browser compatibility issues. It has also been written with technologies such as SVG in mind, and moves are being made to bring the functionality of Dojo to SVG in a cross-compatible manner.

From dealing with strings as quickly as possible, to efficient iterations, to built-in support for the back button in AJAX, Dojo really has it all covered. However, this means it has quite a huge API, and the learning curve associated with Dojo is therefore substantial, given the sparse documentation at the moment.

Recently, the Django framework began to bundle Dojo with its distribution, using it in its administration system, so this may be a catalyst for increased Dojo documentation.

The Basics

At the heart of Dojo is a flexible, powerful and easy-to-use method, dojo.io.bind. This single method can be used in many ways to make both synchronous and asynchronous calls. To give you an idea of how flexible it is, let’s take a look at some examples:

// Load a text document from the server, then alert the user of the contents. 
dojo.io.bind(
 {
   url: "http://example.com/document.txt",
   load: function(type, data, evt) { alert(data) },
   mimetype: "text/plain"
 }
);

// Serialize a form and send it to the server, then evaluate the response as JavaScript!
dojo.io.bind(
 {
   url: "http://example.com/comment.cgi",
   load: function(type, json) { alert(json.myProp) },
   formNode: document.getElementById("formToSubmit"),
   mimetype: "text/javascript"
 }
);
dojo.io.bind can also handle the back button with ease:

dojo.io.bind( 
 {
   url: " http://example.com/comment.cgi",
   load: function(type, data) { alert(data) },
   backButton: function() { /* do something when back is pressed */}
 }
);

Read more about the full capabilities of dojo.io.bind in this introductory article.

The dojo.event method takes the approach of implementing its own event handling system, rather than providing a wrapper around the browser's event system. This results in quite a solid system and, like dojo.io.bind, it's both simple to use and exposes large amounts of power and flexibility.

You can read more about Dojo events here. In the meantime, let's take a sneak peek at the dojo.event method in action. As expected, the following code is triggered by the onClick event and uses an intuitive and familiar syntax.

dojo.event.connect(node, "onclick", "handleOnClick");

Highs and Lows

The great thing about Dojo is that it's so rich in features. The Widget system provides a raft of useful controls such as a DatePicker, a RichText widget, as well as a considerable number of controls that you would expect to find in something like Microsoft's MFC. In addition to this, you can build your own widgets on the framework using HTML, CSS and JavaScript (see this article for details).

But JavaScript need not be limited just to the browser, and Dojo is designed with this in mind. Dojo's platform independence could make it an interesting platform for desktop widget development, as well as many other potential applications. As an example, Open Laszlo recently announced that it was licensing Dojo for its JavaScript implementation of the platform.

Dojo's design has quite a Java-like aesthetic without trying to be Java. In fact, I'd say Dojo utilises JavaScript as a language exceptionally well. One downside of the library's design, though, is the sometimes long package strings that you need to type out to call the methods or instantiate the library's objects -- it would be nice if Dojo could provide a way to "mix" a package into the global or local scope. This would provide ready access to a certain package if you planned on using a lot of methods from it, although I'm not sure how easily it could be incorporated.

Additionally, for all its features, Dojo is completely missing any functions that could aid the selection of DOM elements -- something that's quite fundamental to DOM Scripting. It seems to be quite a gaping hole in the library -- it would be great to be able to select elements using CSS and/or XPath. Similarly, while some of the objects in the library seem to support a kind of iteration framework, Dojo is lacking in methods for iterating though arrays and collections, a task which seems to make up the bulk of DOM scripting tasks.
And at this point in time, documentation for Dojo is not at a premium. The official Dojo site contains some API documentation that's far from complete, but it does have some well-written articles highlighting areas of the library. The JavaScript community has yet to embrace the daunting task of documenting Dojo, though, so independent on the topic articles are few and far between.

1537_protoscript

Prototype and Scriptaculous

The development of the Prototype library is lead by Sam Stephenson of 37 Signals and, along with scriptaculous, has risen to fame as the JavaScript backbone of Ruby on Rails AJAX helpers.

Prototype itself contains the base-level functionality such as AJAX, DOM manipulation, event handling and some extensions to JavaScript itself, while the separate but very much related library, scriptaculous, developed by Thomas Fuchs, is based on Prototype and implements a whole raft of visual effects, as well as drag and drop and some user interface components.

Prototype can be downloaded from the Prototype site, or you can pull it straight from the Ruby on Rails subversion repository if you want to live on the bleeding edge. It currently weighs in at a reasonably compact 54KB. scriptaculous is available from the scriptaculous site and is split into three files: controls.js, dragdrop.js and effects.js, which weigh in at 28KB, 23KB and 32KB respectively. Ruby on Rails bundles all of these files by default.

For an overview of Prototype, take a look at my earlier SitePoint article, Painless JavaScript with Prototype.

The Basics

As far as DOM manipulation goes, Prototype sits very much on the innerHTML side of the innerHTML/DOM methods argument,which may be a plus or a minus depending on which side of the fence you sit in that particular holy war.

Regardless, for most of the DOM lifting you'll need to do, Prototype is extremely useful. A new but very nice feature is that many methods are added directly into the nodes themselves. Here are a few examples:

$('form').visualEffect('fade', { duration : 3 }); 
$('loader').show();

This code fades out the form to which it is applied over a period of three seconds. You can even extend the node objects with your own methods. There have been some performance issues flagged with this approach, but I believe they have mostly been addressed.

Unfortunately, although Prototype has a set of methods for event handling, at this time they're pretty under-developed. Event.observe is more or less a wrapper around the well-used but now superceded addEvent by Scott Andrew-LePara. However, it's easy to use and capable of handling most circumstances. One nice aspect is that it automatically removes all the event handlers you set using Event.observe when the page is unloaded, which should help prevent IE from leaking memory.

The AJAX support is reasonably straightforward and very well developed, as it has been developed right alongside Ruby on Rails. It offers a host of excellent features that I find extremely useful.

It handles JSON transparently, and even evaluates JavaScript sent back from the server automatically. This is the basis of the much-lauded RJS technology in Rails, and is extremely powerful. You don't need Rails to take advantage of this, though -- you can make an AJAX request:

new Ajax.Request('new_comment.php',  
 {  
   data: 'comment=My comment.',  
   evalScripts: true  
 }
);

Then, you can return updates to the page from your server as JavaScript:

  $('comments').replace('<div class="comment">My   comment.</div>'); 

As you can see, this is an incredibly powerful way of designing AJAX applications.

Another nice little feature of the Ajax.Request object is that it appends the X-Requested-With HTTP header automatically, which enables you to tell if your requests come from AJAX on the server side.

Highs and Lows

Convenience is king with Prototype. Most notably, the $ function (which selects elements by id) and the $$ function (which selects elements using CSS selectors) provide extremely quick access to elements on the page. The $$ function even supports CSS3 selectors -- most browsers don't. When you use it in conjunction with the enumerable methods and Prototype's other convenience methods, you can come up with some pretty concise statements. For instance, to hide all div elements with a class of /#c#"obscene":

$$("div.obscene").map(Element.hide); 
$$("a[href='http://']").each(function(element)  
 {
   Event.observe(element, 'click', openNewWindow);
 }
);

As we all spend most of our scripting time working through lists of DOM nodes, this buys us a lot of power indeed. The compact and intuitive API really is the killer feature of Prototype for me.

Scriptaculous is a great, extensive effects library with solid drag-and-drop support that, again, is ridiculously easy to use. Consider this:

new Draggable('my_element');

This produces an element that the user can drag. You can then add further configuration using object notation, like this:

new Draggable('my_element',  
 {  
   revert : true  
 }
);

Documentation was very limited for a long time, but recently many people have filled the gap, making Prototype one of the most widely documented of the big JavaScript libraries, albeit that that documentation is a bit splintered. There are no central API docs, but there's a whole raft of libraries that cover parts of the library, as well as Jonathan Snook's excellent cheat sheet detailing the entire library. The prototypedoc.com site also maintains a pretty thorough list of articles about Prototype to help you get started with the library.

1537_mochikit

Mochikit

Mochikit is the brain child of Bob Ippolito (the primary contributor) and is available from the Mochikit site. The basic package weighs in at around 90KB (compressed), but you can load each of the modules separately. Mochikit is also currently bundled with the Python web framework, TurboGears.

In the words of Bob,

We took all the good ideas we could find from our Python, Objective-C, etc. experience and adapted it to the crazy world of JavaScript.


So, to a large extent, Mochikit draws on the idioms of Python for its API. If you're familiar with Python, you'll have an instant head start with Mochikit, although it has a simple API which is reasonably easy to pick up. Of all the libraries covered in this article, Mochikit's API feels the most "designed". Rather than relying on package-style naming conventions, it exports a select number of functions to the global namespace, which helps make your scripts a lot more compact.

When getting started with Mochikit, you should:

  1. Watch Bob's screencast.
  2. Start bashing away using Mochikit's excellent interactive interpreter, much like you would with Python. This is a great way to get a feel for the library and a basic understanding of how Mochikit works.

The Basics

When working with the DOM, Mochikit has some real tricks up its sleeve:

var warning = P(  
 { 'class' : 'warning' },  
 "Please provide a ", STRONG(null, "valid email address")  
);  
swapDOM(document.getElementById("notifications"), warning);

This code will use the relevant W3C DOM methods to create the equivalent node tree for the following HTML:

<p class="warning">Please provide a <strong>valid email address</strong></p>

The Mochikit code is almost cleaner than the HTML syntax!

The Mochikit.DOM module also contains a number of other methods for easy DOM manipulation, such as the swapDOM method mentioned above (which does what it says on the tin), and toHTML (which converts a DOM node to the HTML it represents). And just for good measure, Mochikit has thrown in the $ function for those who are used to it.

As far as event handling goes, Mochikit has a well designed (if slightly unfamiliar system) that's implemented in the Mochikit.Signal module. It's based around the concept of connecting a listener to a signal that's sent from an object. All the regular DOM events are signals, but you can create your own, too. The connect method does all the work here:

// connects the onclick signal of the element with id="thing"   
// to the function showDialog, which points to the element.  
connect($('thing'), 'onclick', showDialog);  
 
// connects the onsubmit signal of element id="form" to  
// formController.checkSubmit, which points to the  
// formController object.  
connect($('form'), 'onsubmit', formController, 'checkSubmit');

You can make your own objects send signals simply with the signal method:

signal(anObject, 'a_signal');

While Mochikit's event system is a departure from the way you might normally expect event handling to work, it's actually brutally simple and great to use once you get used to it.

AJAX stuff is handled by the Mochit.Async module, and the Deferred objects which lie at the core of the implementation. To perform a basic AJAX call, use either loadJSONDoc or doSimpleXMLHttpRequest:

var request = doSimpleXMLHttpRequest('get_options.php',   
   { q : 'web developer'}  
);

This function returns a Deferred object, on which you can set callbacks:

request.addCallbacks(mySuccessFunction, myErrorFunction);

When the XMLHttpRequest is complete, the relevant callback is called and passed the XMLHttpRequest object as the argument:

function mySuccessFunction(req) {  
 alert(req.responseText);  
}

Deferred objects are useful for any asynchronous programming and are a great idea. Read more here, or watch the screencast for more details.

Highs and Lows

First off, Mochikit's logging framework is excellent. Simply add logging statements:

log("This is so much better than alert");  
log("ERROR This thing is broke");

You can then use Mochikit's bookmarklet to open a log window and view your log messages. You don't need to add anything into your pages or include any extra script -- it's truly effortless and beats alert any day.

Mochikit also makes full use of JavaScript's functional programming features to really enhance and simplify the library's API. For instance, if you want to sort a group of objects by their name properties, you can use keyComparator to create the sort function for you:

var sortedByName = people.sort(keyComparator("name"));

There's also the useful counter function. This creates a function which returns a value that's incremented by one every time it's called:

var nextId = counter();  
nextId(); //=> 1  
nextId(); //=> 2  
nextId(); //=> 3

There's also a full set of Python-style iteration functions, such as forEach, map and filter, which are sure to see heavy use.

As far as documentation goes, Mochikit has some very good API documentation, but details on some very basic parts of the library are a little lacking. In particular, after reading all the docs, watching the screencast and writing a few Mochikit-based scripts, I'm still unsure which version of the library is best suited for any purpose. Do I use the packed version or the main Mochikit.js? How can I load individual parts of the library?
However, Mochikit does have a mailing list, so answers to these kinds of questions are, no doubt, not far away. All in all, Mochikit may not be what you're used to in terms of a JavaScript library, but it's beautifully designed and I'm looking forward to seeing where Bob takes it.

1537_yui

Yahoo! UI Library

The Yahoo! UI Library or (YUI as it's commonly been referred to) was developed by Yahoo! for internal use, but has recently been open sourced along with a whole raft of excellent developer resources at developer.yahoo.com.

YUI is more a distinct set of "utilities" than a coherent library, with five core scripts that cover:

  • animation
  • AJAX
  • DOM manipulation
  • drag-and-drop
  • event handling

And there are six controls, namely:

  • Calendar
  • Slider
  • Menu
  • AutoComplete
  • Tree View
  • Container classes (with which you can implement all manner of window-style widgets)

You can download each of these scripts individually from the developer.yahoo.com site.

There is a definite advantage to this loosely coupled approach to designing libraries -- it often seems a bit of an overkill to have users download 100 or so kilobytes of library when, for instance, they only want to use the event system.

Each of the Yahoo! libraries depends only on the small yahoo.js file. On the other hand, this approach offers a slightly less coherent experience for the developer and could possibly introduce a certain amount of repetition within the libraries.

One thing that feels awkward about YUI is the fact that it's very heavily namespaced. Every call you make to the library needs to be prefixed with a hefty package string:

var myAnim = new YAHOO.util.Anim(  
 'test',  
 { height: {to: 10} },  
 1,  
 YAHOO.util.Easing.easeOut  
);  
myAnim.animate();

This all seems rather verbose, and I'm unsure whether JavaScript really requires that degree of namespacing -- usually we'd never have that much code loaded into any one page. Nevertheless, YUI is a straightforward and utilitarian library with a primary focus that seems to be smoothing over browser differences as simply as possible.

The Basics

YUI's event handling library should have a very familiar API for those who are used to the native browser event handling methods. However, it packs a few nice surprises that Yahoo! developer, Dustin Diaz, has explained in some detail on his site. You can set a simple listener like this:

YAHOO.util.event.addListener('object_id', 'click', callBackFunction);

A very powerful feature of the event library is its deferred attachment of event listeners. Essentially, if you attempt to attach a listener to an element that does not yet exist because the page hasn't loaded yet, it will transparently wait for that page to become available before attaching to the event. This is a neat solution to an issue that has confused and frustrated many DHTML newbies.
The DOM library abstracts over browser inconsistencies, allowing the seamless setting of styles and reporting of element properties. However, while it takes care of the common tasks reasonably well, there are a few surprises in here:

  • get is YUI's version of the infamous $ function.
  • One interesting method is generateId, which can be used to generate IDs for elements programmatically so you can quickly access them at other points in the script. It's not immediately obvious why this approach would be used over simply storing references to the objects, though, so I'd be interested to see it used in a real script.

The Connection Manager contains all of YUI's AJAX magic, and in line with the other libraries, chooses not to take a high-level approach. It does nothing more than provide a cross browser interface to XMLHttpRequest:

YAHOO.util.Connect.asyncRequest(  
 'GET',  
 'http://www.yahoo.com',  
 callback  
);

One highlight is the rich callback interface, which allows you to define an object that wraps your callback functions as well as some extra configuration. Here's an example callback object:

var callback = {  
 success: function(resp) { alert('WOO!!'); }, // called on success  
 failure: function(resp) { alert('BOO!'); }, // called on error  
 argument: arguments, // user defined arguments  
 scope: formController // scope the callbacks are called within  
}

Highs and Lows

The documentation provided by Yahoo! for the library is excellent. The site has formal API documentation, plenty of examples, a mailing list and some brief but clear explanations of the main features of each part of the library. However, as with Dojo and Mochikit, the library has not quite managed to capture the imagination of the developer community as much as Prototype, so independent articles are still thin on the ground at the moment. The best place to check for articles about YUI is Yahoo! developer, Dustin Diaz's site.

As I implied above, the event handling implementation is one of YUI's main strengths, and the fact that it is decoupled from the other parts of the library means that it could well see a lot of use independently from the rest of the library. However, the rest of the library, while being very functional, doesn't contain as many innovative features as the likes of Mochikit, Dojo and Prototype, and because of the long package strings, coding with YUI sometimes feel rather long-winded.

Yet the growing list of components is very rich. For instance, the Calendar component supports several languages and multiple date selections, and the Container classes give you the power to implement all kinds of windowed interfaces. One downside of using these components is that they tend to be very heavily dependent on the other libraries; in discussing this, Dean Edwards highlights as an example the treeview control, which uses around 260K of JavaScript.

Which one Wins?

Well, the short answer to this question is that there is no real stand-out solution that excels in all situations.

Prototype is the most comprehensively documented -- albeit in a splintered way. It is also seemingly the most widespread library at the moment, possibly because it really excels at the kind of tasks developers complete most often, like selecting nodes and working with lists. Of course, it's going to be the natural choice for Ruby developers because it sticks to many Ruby idioms. One other great thing about Prototype is that it has the mighty weight of Rails behind it and, as a result, there are many developers providing bug fixes and patches to Prototype. Finally, it offers a wealth of add-on libraries such as scriptaculous, Rico, and Behaviour that make it a good, solid choice for many developers.

On the other hand, Prototype has a very under-developed event handling framework, which is a major problem for an otherwise powerful library. Also -- and this is purely a matter of taste -- Prototype's super-pragmatic approach to things (like the heavy use of the innerHTML property) can seem a little "dirty" sometimes.

For smaller projects, the decoupled design and fully-featured components of YUI may well be a big plus. It's very easy to drop in the Connection Manager or the Event library and get going on some basic tasks without having to traverse too much of a learning curve. On the whole, though, it doesn't have much to offer in terms of cool or powerful features.

Dojo is definitely the daddy of the bunch -- you can almost always rely on it for the most powerful implementation of any feature. And Dojo's focus on performance is an absolute godsend if you're planning a very JavaScript-intensive application. The widget implementation also has enormous potential for building complex UIs. However it really is quite big -- both in terms of its file size and the size of the API -- so I wouldn't recommend it for smaller projects.

In my opinion, Mochikit is by far the most well designed and well thought out of the four, and Python/Twisted/Nevow developers will definitely find its API very familiar. However, its documentation is a bit thin in some places (for instance, I'm still a little unsure as to which version of the Mochikit distribution to put in the script tag). Also, some of the idioms and functional techniques that it uses may be confusing for beginners or those who aren't well versed in functional programming techniques. However, it really is worth a look. Mochikits's capabilities will probably surprise you -- the createDOM function, iteration tools and the asynchronous architecture are a work of art.

Free book: Jump Start HTML5 Basics

Grab a free copy of one our latest ebooks! Packed with hints and tips on HTML5's most powerful new features.

  • Steven

    If you need a JavaScript library with a short learning curve and rich set of UI controls, check DHTMLX ( http://dhtmlx.com ). Although it’s only partly open source, it’s a great choice for complex web apps.