The Road to HTML 5: getElementsByClassName()
Welcome back to my semi-regular column, "The Road to HTML 5," where I'll try to explain some of the new elements, attributes, and other features in the upcoming HTML 5 specification.
The feature of the day is
getElementsByClassName() exists as a method of the
document object (for searching the entire DOM), as well as on each
HTMLElement object (for searching the children of an element).
The HTML 5 specification defines
getElementsByClassName(classNames)method takes a string that contains an unordered set of unique space-separated tokens representing classes. When called, the method must return a live
NodeListobject containing all the elements in the document, in tree order, that have all the classes specified in that argument, having obtained the classes by splitting a string on spaces. If there are no tokens specified in the argument, then the method must return an empty
NodeList. If the document is in quirks mode, then the comparisons for the classes must be done in an ASCII case-insensitive manner, otherwise, the comparisons must be done in a case-sensitive manner.
A Brief History of getElementsByClassName()
- September 2005: getElementsByClassName() Implementation Questions and followups discuss whether
getElementsByClassName()should take a string with multiple classnames, and if so, what that would mean. Despite early protests, it was eventually decided that
getElementsByClassName()should take multiple classnames in a single string, separated by spaces, and that the function should return elements that define all of given classnames.
- February 2006: "I see this is still an open issue."
- October 2006: "This omnibus edition of your WHATWG mail includes replies to 50 or so separate e-mails about getElementsByClassName()."
- February 2007: "I landed support for this on the Mozilla trunk, and it will appear in upcoming Firefox alphas and betas. The array argument turned out to be quite a pain to implement, so we cut it." Ian Hickson responds: "I've changed the spec to use a space-separated list. ... I've dropped the array form altogether."
- March 2007: John Resig puts Firefox 3's implementation to the test in getElementsByClassName Speed Comparison.
- July 2007: "I suggest that participants in this thread reacquaint themselves with the discussion in the previous one before having it again." Good luck with that.
- September 2007: "A popular and useful feature [in Opera 9.5] will be the addition of native support for getElementByClassName from HTML5."
- December 2007: "Last week WebKit joined upcoming versions of Firefox and Opera in supporting [getElementsByClassName]."
- December 2007: "Currently getElementsByClassName is specified as always being case sensitive. This would be fine, except that the primary other use of html class names (CSS selector matching) is only case sensitive in standards mode. This leads to situations ... in which CSS and getElementsByClassName match different results."
- July 2008: Ian Hickson responds: "I've made it consistent with how classes work in CSS (case-insensitive for quirks and case-sensitive otherwise)."
Can We Use It?
Yes We Can! As you can tell from the timeline,
getElementsByClassName() is supported natively in Firefox 3, Opera 9.5, Safari 3.1, and all versions of Google Chrome. It is not available in any version of Microsoft Internet Explorer. (IE 8 beta 2 is the latest version as of this writing.) To use it in browsers that do not support it natively, you will need a wrapper script. There are many such scripts; I myself am partial to Robert Nyman's Ultimate GetElementsByClassName. It uses the native
getElementsByClassName() method in modern browsers that support it, then falls back to the little-known
document.evaluate() method, which is supported by older versions of Firefox (since at least 1.5) and Opera (since at least 9.27). If all else fails, Robert's script falls back to recursively traversing the DOM and collecting elements that match the given classnames.
And in conclusion
getElementsByClassName() is well-supported across all modern browsers except IE, and a performance-optimized open source wrapper script can cover IE and older browsers.
As more and more browsers start supporting querySelector and querySelectorAll (including IE8b2), does getElementsByClassName still serve much purpose?
There’s a really nasty bug in the implementation of getElementsByClassName in WebKit. See https://bugs.webkit.org/show_bug.cgi?id=19974 for more details. There’s a workaround but it makes it more difficult to use it right now.
“I suggest that participants in this thread reacquaint themselves with the discussion in the previous one before having it again.” We need an acronym for that…
when and why did you decide to go this route (specifying DOM APIs and scripting language behavior) in the first place? does the “ML” part of “HTML” confuse you? 😉 having a DOM “interface” as a property collection with accessor tags (private, readonly, etc), i can understand. but methods, i think, are out of your “jurisdiction”. also, the link to the specification just starts throwing around “document.getElementByClassName(‘foo’)” as if you can call it from anywhere. “document.getElementByClassName()” then?? not likely.
and “quirks mode” is in your specification? seriously? you’re making displaying things inconsistently a language feature??
Dustin: The WHATWG isn’t just “the HTML group” — we’re defining a number of things, including the HTML language, its APIs, and its syntaxes.
Originally “HTML5” was actually called “Web Applications 1.0”, and indeed “web-apps” is still in the document’s URL. We renamed it as part of the cooperation effort with the W3C.
Regarding quirks mode, our goal is to write a (group of) specification(s) that defines everything you need to implement a Web browser, and quirks mode is part of that, whether we like it or not, so it is defined.
Regarding ECMAScript vs other languages: The HTML5 spec is mostly language-agnostic, it just uses WebIDL to define the interfaces.
It may be obvious, but non-native
getElementsByClassName()does not return a live NodeList, but an array. In some cases this may lead to different results in different browsers.
[…] The Road to HTML 5: getElementsByClassName() […]