getElementsByClassName pre Prototype 1.6

There’s an important compatibility regression coming up with the releases of Firefox 3 and Safari 3.1 (and any other browser that will natively implement getElementsByClassName) concerning old releases of Prototype (pre 1.6).

In talking with Tobie Langel, of the Prototype team, he recommends the following:

We’ve already deprecated document.getElementsByClassName and Element#getElementsByClassName [in Prototype 1.6].

The easiest workaround, which does not require upgrading, is to replace calls to document.getElementsByClassName(‘foo’) with $$(‘.foo’) and calls to Element#getElementsByClassName(‘foo’) with Element#getElementsBySelector(‘.foo’) or Element#select(‘.foo’) (version >= 1.6.0) depending on which version of Prototype you are running.

A number of users noticed this problem during the Firefox 3 betas and after the release of Safari 3.1:

If you have a site that’s using an old version of Prototype, and getElementsByClassName, then it’s recommended that you either upgrade or perform the above steps (probably sooner, rather than later, so you don’t hit compatibility problems).

How This Issue Came About

It’s important to realize how a problem like this can come about so that you can prepare for it within your development. This core issue arises from the fact that Prototype was implementing a property on the global document variable which was, eventually, codified into the HTML 5 standard and implemented in some browsers.

Looking at their code we can see something like this:

if (!document.getElementsByClassName)
  document.getElementsByClassName = function(instanceMethods){
    // ...
  };

This code in, and of, itself isn’t necessarily the problem. If you implement a JavaScript library that completely, 100%, implements a specification then it’s probably safe to do the above in that manner (base2 is a good example of a library that does this well).

A problem occurred because, in their implementation of the method, they were adding new methods to the returned array (such as .each). This meant that users began to use the method in this manner:

document.getElementsByClassName("monkey").each(Element.hide);

Which subsequently broke when an actual getElementsByClassName implementation came on the scene (since the result returned from the method wasn’t ‘enhanced’ with the each functionality – amongst other methods).

Attempting to implement any sort of future specification can be a real fools game. Since standards are often imperfect (such as not providing an .each mechanism) or frequently change – attempting to match that functionality with a library can be incredibly difficult. More often than not it’s simply a better idea to implement brand new methods that can never conflict with upcoming functionality (as the Prototype team has done in the 1.6 release).

Posted: March 26th, 2008


Subscribe for email updates

22 Comments (Show Comments)



Comments are closed.
Comments are automatically turned off two weeks after the original post. If you have a question concerning the content of this post, please feel free to contact me.


Secrets of the JavaScript Ninja

Secrets of the JS Ninja

Secret techniques of top JavaScript programmers. Published by Manning.

John Resig Twitter Updates

@jeresig / Mastodon

Infrequent, short, updates and links.