Infrequently Noted

Alex Russell on browsers, standards, and the process of progress.

Extending dojo.query()

As you probably know, Dojo is layered, extensible, and our philosophy of "build with, not on" means that we give you all of the same tools and extension points that we use in our code for use by your app.

Dojo's got 2 "sides", namely the bits that make working with the DOM better and the bits that make writing idiomatic JavaScript faster and easier. Where the package and language utilities enable you to extend and modularize your JavaScript work, the widget, behavior, and query systems make working with the DOM similarly extensible. Writing widgets and behaviors is well-understood in the Dojo community, but extending the results of a dojo.query() call haven't seen as much attention. To rectify that, here's the two-minute version of how to write your own dojo.query() extension.

Step 1: grok dojo.NodeList

dojo.NodeList is the Array subclass which all dojo.query() calls return an instance of. Therefore, to extend the results of a dojo.query(), we really want to extend the dojo.NodeList class. Both dojo.query() and dojo.NodeList are available as soon as dojo.js is included in your page.

Step 2: extend NodeList the old-skool way

Instances of dojo.NodeList pick up properties from the prototype object of the dojo.NodeList class. Lets add an inspect() method which logs out the innerHTML of the nodes in the list to the Firebug console:


dojo.NodeList.prototype.inspect = function(){
    this.forEach("console.debug(item.innerHTML);");
    return this;
}

// now we can call it: dojo.query("#container > p").inspect();

// or via a direct instance: var nl = new dojo.NodeList(dojo.byId("container"), document.body); nl.inspect();

A couple of small things to note:

Step 3: modernize and package it up

We want to be able to use dojo.require() to manage this module, so we'll assume that our Acme module lives in the acme/ directly which is a peer of the dojo/ and dijit/ directories from the Dojo distribution.

Lets add a provide() so that we can require() our module and use a bit of Dojo's language tools to extend dojo.NodeList more tersely:


// this file located in:
//    acme/ext-dojo/NodeList.js

dojo.provide("acme.ext-dojo.NodeList"); // require() statements go here

dojo.extend(dojo.NodeList, { inspect: function(){ this.forEach("console.debug(item.innerHTML);"); return this; }, ... });

We can now include this module at runtime via dojo.require("acme.ext-dojo.NodeList") and use it as a part of a build which will significantly improve the performance of the application which needs the file. Dojo's infrastructure makes doing what's easy pay off in the long run for your application.

Note that the file name is acme/ext-dojo/NodeList.js, which might seem a bit odd at first glance, but the intermediate "ext-dojo" directory makes it blindingly obvious to anyone who sees the require() statement what's going on. You can't dot-access a variable named "ext-dojo", so we know that this isn't a "normal" module. Instead, it's an extension, which extends the dojo.NodeList class. Subclassing is often more trouble than it's worth, and discouraging people from extending the Dojo core objects seems lame. Instead, we use this convention to make it easy to understand what's happening when you look at any given Dojo project.

And that's it! Writing powerful extensions for query results is easy, and because your project is using Dojo, you can structure your extension as a module and gain the benefits of optimization for deployment via the Dojo build system and the ease of use that comes from not having to worry about what order you're including your files in. It's good to be using a tool that you can build with, not just on.

Big Questions On IE8's Big Progress

So IE is the first browser out of the gate to do something sane about rendering engine locking to content…and good on them for it.

Now we need to know a couple more details to see if it’s going to have real legs:

These questions need to be answered, and soon. If the IE team has just replaced one scarce resource for another, we’re not much better off over the long haul. It’s great news that the IE team is really implementing the “renderer selection switch” which many of us have dreamed of for so long…but having it continue to be global to the page or in other ways encourage contention on yet another single element in the document wouldn’t be stepping forward enough.

Older Posts

Newer Posts