getElementsByClassName

This is worth a formal note: getElementsByClassName() is now natively supported by the most recent versions of Firefox, Safari, and Opera. I added it to the compatibility tables. Obviously, as long as Certain Other Browsers do not support it we can't yet really use it everywhere, but it's a ray of hope.

And you wrote your custom getElementsByClassName() function to keep an eye on native implementations, didn't you?

function getElementsByClassName(node,classname) {
	if (node.getElementsByClassName)
		return node.getElementsByClassName(classname);
	else {
		// your custom function
	}
}

This is the blog of Peter-Paul Koch, mobile platform strategist, consultant, and trainer. You can also follow him on Twitter.
Atom RSS

I’m speaking at the following conferences:

(Data from Lanyrd)

Categories:

Monthlies:

Comments

Comments are closed.

1 Posted by Dusan Smolnikar on 20 May 2008 | Permalink

Did you by any chance get to test the speed of the implementation? My biggest wory with custom getElementsByClassName functions was the slow processing with large pages (and slow machines).

2 Posted by Eric Meyer on 20 May 2008 | Permalink

I've been using Robert Nyman's 'ultimate' version (http://www.robertnyman.com/2005/11/07/the-ultimate-getelementsbyclassname/). Does the native version allow for the same kind of multi-class getting? I sort of think not, but it's not clear to me. I looked at the documentation of the native version on the MDC but it didn't really help me. I'm interested in your thoughts.

3 Posted by Michael Girouard on 20 May 2008 | Permalink

I've switched to using a getElementsByAttribute in my library as I seem to be capturing attribute values quite often as of late:

http://pastie.caboo.se/200166

Having a native implementation of searching for classed elements will be nice, but I question it's reliability (like Eric Meyer said above). After all, I'm still a little disapointed by the implementations of the native Selectors API.

But if this is like any other wave in the standards movement, it will become great with time.

Cheers,
Mike G.

4 Posted by Anne van Kesteren on 20 May 2008 | Permalink

Eric, it takes a space separated list of class names. See also http://www.whatwg.org/specs/web-apps/current-work/multipage/section-dom-tree.html#getelementsbyclassname

5 Posted by ppk on 20 May 2008 | Permalink

Thanks Anne, that's a useful thing to know. Added a test for multiple class names (works in all browsers).

6 Posted by Rik on 20 May 2008 | Permalink

There's a big différence between a native getElementsByClassName and a JS implementation : the native version returns a live NodeList, like getElementsByTagName. Dean Edwards explains that on John Resig's blog : http://ejohn.org/blog/getelementsbyclassname-pre-prototype-16/#comment-300315

7 Posted by Robert Nyman on 20 May 2008 | Permalink

Thanks Eric, that makes me happy to hear!

However, I think it has become outdated over the years (and it should really use XPath to be more efficient), and going the native route is most likely the best approach for the future.

For anyone wondering, the link in Eric's post ended with a parentheses, which weirdly redirects user to a completely different page on my site.

The correct link should be:

http://www.robertnyman.com/2005/11/07/the-ultimate-getelementsbyclassname/

8 Posted by Scott Johnson on 20 May 2008 | Permalink

I am, perhaps naïvely, just using the function provided by my favorite library, hoping it is doing the right thing and checking for a native version before using its own code. Works for me.

9 Posted by Robert Nyman on 20 May 2008 | Permalink

Scott,

Being the guy behind one JavaScript library, http://www.domassistant.com/ , I can say that we definitely respect native implementations, since they're bound to be the fastest and (hopefully) most correct.

This of course goes way beyond getElementsByClassName, into utilizing XPath and querySelectorAll, and I think it's every JavaScript library's responsibility to offer you, the end user, the best performing and most correct implementations.

I mean, that's what JavaScript libraries are for, right?

10 Posted by Gopal Venkatesan on 22 May 2008 | Permalink

Dusan, you could potentially speed things up by checking for XPath support and use if its available. So, the pattern would be:

if (document.getElementsByClassName) {
// use the native implementation
} else if (document.evaluate) {
// use the XPath support
} else {
// fall back to traditional method
}

11 Posted by Robert Nyman on 27 May 2008 | Permalink

Total self-pimping here, so feel free to remove it, PPK. I've updated my getElementsByClassName script to a new version utilizing native versions if available, XPath if available or otherwise fall backs to regular looping.

As opposed to the native method, it returns an actual array instead of a nodelist, and supports multiple class names specified in any order.

If interested, please read more at http://www.robertnyman.com/2008/05/27/the-ultimate-getelementsbyclassname-anno-2008/

12 Posted by Mark on 7 June 2008 | Permalink

Here is Douglas Crockford's version of getElementsByClassName:
-----------------------

function walkTheDOM (node, func) {
func(node);
node = node.firstChild;
while (node) {
walkTheDOM(node, func);
node = node.nextSibling;
}
}

function getElementsByClassName (className) {
var results = [];
walkTheDOM(document.body, function (node) {
var a, c = node.className, i;
if (c) {
a = c.split(' ');
for (i=0; i<a.length; i++) {
if (a[i] === className) {
results.push(node);
break;
}
}
}
});
return results;
}