Some thoughts on HTML5's getElementsByClassName
Now there are 2 things that I would like to point out. One is actually a warning and the other one is something that I feel is an oversight in the specification.
A quick example:
1 2 3
var foo = document.getElementsByClassName('foo'); for (var i = 0; i < foo.length; i++) foo[i].parentNode.removeChild(foo[i]);
That will make you quickly wonder why not all elements having a className of 'foo' are removed in the end
That is also why in my implementation I convert the NodeList to a static array using Array.slice() so it matches the returntype of the alternative branches.
Now there is one thing that made me wonder: getElementsByClassName can be fed multiple classNames (space-seperated) in order to find elements that have all of those classnames, so:
var foobar = document.getElementsByClassName('foo bar');
will find all elements that have both className 'foo' and 'bar' (in any order).
That's also nice, but what if I want to select all elements that have either className 'foo' or 'bar'? From a technical point of view it is easier to filter the outcome of getElementsByClassName('foo') on the existance of className 'bar' for each element than to actually do an intersect on getElementsByClassName('foo') and getElementsByClassName('bar').
In fact, JS1.6 already has an Array.filter() generic that can easily be used to accomodate the usecase of selecting elements that match all of several classnames, but a native intersect method does not exist. If getElementsByClassName was specified to be also applicable to NodeLists it would even be easier to accomodate the usecase of selecting elements that have all of several classnames because than you could just as well do:
var foo_and_bar = document.getElementsByClassName('foo').getElementsByClassName('bar');
So did the WHATWG/HTML5 WG aim here for a 'quick win' choosing the most easy implementable solution and disregarding the other, just as valid, usecase where you want to select elements with either one of a list of classnames? I wonder...
You could try to reverse the handling of the foo-list: for (var i = foo.length -1 ; i >=0 ; i--)var foo = document.getElementsByClassName('foo');
for (var i = 0; i < foo.length; i++)
Whether this actually works is up to the browser implementation of getElementsByClassName...
You are right that it also depends on browser implementation: the order in which the elements are returned in the NodeList is still left undefined in the specification. This issue has already been raised on the HTML WG mailing list. I too think that it would be wise to explicitly define the order. Document order would seem to be a rational choice.
[Comment edited on Tuesday 12 February 2008 10:22]
I can't wait for the first HTML5/CSS3 compliant browsers.
var foo = document.getElementsByClassName('foo');
while (foo.length) foo.parentNode.removeChild(foo);
There is nothing 'wrong' with the NodeList model, you simply need to use it the right way.
Comments are closed