Infrequently Noted

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

Fast DOM Queries in Today's Browsers

What follows is a janky hack. If you do not have the stomach for things that are useful in the real world, please stop reading here. "But it's not standards compliant!" comments will receive no sympathy. Validatorians, you've been warned.

If you're still reading, you're probably aware of the crappy primitives that the W3C has bestowed us with for scripting arbitrary collections of nodes. Things like Microsoft's HTC and Mozilla's XBL allow for browser-specific markup-upgrade paths but these aren't really feasible in the "real world" since they require lots of code branching and different semantics for attaching a behavior. Tools only succeed where they lower our costs. This is why Dojo and Behavior (and even netWindows, back in The Day) work so hard to provide a portable basis for applying behaviors.

Given that the W3C has f'd us in the ear and that the browser manufacturers can't get it together enough to come up with one non-standard way to apply scripts to collections of nodes, we're back to iteration. Updating the collection to which a behavior should be applied when a DOM is updated presents a particular challenge. IE doesn't throw mutation events for DOM changes nor does it provide client-side XSLT. Both hands our tied behind our back.

So we need something else. document.getElementsByName() would work quite well if the browsers paid attention to name attributes for any element. Alas, they don't. Which brings us back to the one fast query browsers will support on any element: document.getElementById(). With it we can build a fast, efficient query function for every browser but Safari:

function elementsById(id){
var nodes = [];
var tmpNode = document.getElementById(id);
while(tmpNode){
nodes.push(tmpNode);
tmpNode.id = "";
tmpNode = document.getElementById(id);
}
for(var x=0; x<nodes .length; x++){
nodes[x].id = id;
}
return nodes;
}

A permutation of this that caches the results and does not set the IDs back to the original value allows re-runs of the function to determine if new elements have been added to the group and/or if a node should be removed:

var groupCache = {};
function elementsById(id){
if(!groupCache[id]){
groupCache[id] = [];
}
var nodes = groupCache[id];
for(var x=0; x<nodes .length; x++){
if(nodes[x].id != ""){
nodes.splice(x, 1);
x--;
}
}
var tmpNode = document.getElementById(id);
while(tmpNode){
nodes.push(tmpNode);
tmpNode.id = "";
tmpNode = document.getElementById(id);
}
return nodes;
}

Obviously, getting a list of added/removed nodes from this function might be preferable to receiving the full list, but I'll leave a better API for this as an exercise. Safari is the only browser which appears to not support this method of constructing queries, but we can fall back to iteration. It's certainly not going to be any slower than current methods. The hack is also made somewhat less useful by the W3C's bone-headed decision to limit elements to a single ID.

The jury is still out as to whether or not this is going to prove useful, but I can already imagine it being an optional optimization for Dojo users looking to make their apps go like hell on pages with complex DOMs.

If only it weren't necessary.

Update: After reading much WebCore source code, I'm not aware of a way to make elementsById() work on the current Safari. There is good news, however. On the latest Konqueror release and nightly Safari builds this hack works flawlessly. In short, this will very soon the the most widely available, fastest DOM query method. More news regarding elementsById() to follow shortly.

Those loveable finks

My last attempt to rebuild my mail client of choice on the old Powerbook was something short of thrilling. It was with some trepidation that I moved my data to the new MacBook and attempted to fire up kmail. Thanks to the magic of rosetta, it worked. I was, in a word, stunned.

But I just can't leave well enough alone. Having read encouraging notes about fink on 10.4+Intel, I backed up my data and /sw directory plunged in, foolishness first.

Unlike my previous attempt at building KMail, the process was absolutely painless. Not only is the "ssl vs. non-ssl" war apparently over, dependencies satisfied themselves in the right order and the only input needed from me was the occasional mirror selection. An hour into the process things were well enough under way that I went to bed and just left the build running. When I came back to the terminal this morning, lo-and-behold, it had built cleanly. On firing it up, i can attest to the difference that native compilation makes. My mail has never been so speedy. As someone who lives-and-dies by the mailing traffic that flows into my laptop, all of this makes me one extra-happy camper.

The fink folks (particularly Benjamin Reed, the KDE maintainer) have clearly spent some quality time polishing the dependency code since last I had to preform this operation. My sincerest thanks go to them for the painless install this go 'round. Not only do I have the latest-and-greatest KDE available, I now feel comfortable recommending fink again to folks who want a better alternative to Mail.app.

Conference Wrap Up

I tend not to take a lot of pictures at conferences. Or blog much when I'm at them. In fact, it's usually not discernible that I'm at a conference except that I'm not doing all the other stuff I normally do. I'm not sure why. I always bring a camera (sometimes more than one), I just don't use it.

That's a long way of saying that FOSDEM and ETech were wonderful, but I don't have a lot of photographic evidence to support that assertion or even to prove that I was really there. It might be to the best though. My ETech demo crashed-and-burned thanks to my foolish assumption that we'd have a working network. Lesson learned.

As this was my first ETech, I was (and still am) in awe of the people I met and how they would even actually talk to me if approached! Whether or not they'll talk to me after having met me is another question entirely. At ETech I got to meet some users of Dojo and folks who are implementing Comet apps small and large. It drove home my suspicion that we do need a new name; one that will let us discuss old concepts with people who may not yet be familiar with them. The sheer number of "and our product has been doing that since X" replies to one of my previous posts also makes the point better than I ever could. Comet is useful, the solutions to the technical problems are becoming more widely distributed, and a set of patterns for how and when to use Comet will soon emerge.

On that front, Douglas Crockford's new JSONRequest proposal was announced. Maddeningly, there's still no link to the various ongoing conversations about it from the document itself, but it does seem worthy of discussion. The provision for duplex communication is particularly interest as it would provide the first known way to do cross-domain Comet without resorting to Flash. James Burke, Dojo's newest commiter, has great comments on the proposal.

Something I hope to come back to soon is something Bruce Sterling mentioned during his keynote at ETech: that augmenting human intelligence is as better goal than replacing it and that language has been our stumbling block to describing what we should be working toward. My recent introduction by Brad to Doug Engelbart's seminal work and the realization that Jot is little more than a conceptual descendant of Augment delivered via the web has made these words ring in my head that much more acutely.

Comet Talk at ETech

Slides are up! You can get them as PDF or flash.

ETech Ajax Tutorial Slides

Here are the slides for today's Ajax Tutorial at ETech. The demos are available in a separate tarball.

I'll publish my slides for the Comet talk sometime on Wed.

Older Posts

Newer Posts