Your Favourite getElementsByClassName
There's a variety of scripts out there for getElementsByClassName. Oddly though, the first 20 or so results from Google are confusing or completely inaccurate. So, what's your favourite getElementsByClassName script?
Here's something I threw together based on an unusable script I just saw on Digital Media Minute.
function getElementsByClassName(node, classname)
{
var a = [];
var re = new RegExp('\\b' + classname + '\\b');
var els = node.getElementsByTagName("*");
for(var i=0,j=els.length; i<j; i++)
if(re.test(els[i].className))a.push(els[i]);
return a;
}
Note: Be sure to wrap your code examples in like so: <pre><code> </code></pre>
. It'll format better that way.
UPDATE:As mentioned by Cameron, the regular expression I use above may not catch every valid class name. More specifically, class names with hyphens in them causing false positives. Using Cameron's technique of '(^| )'+classname+'( |$)'
should prove more reliable.
For those unsure of what it all means, in regular expression speak, \b
is used to indicate word boundaries. The problem being that a search for \bhelp\b
would also find help-me
which isn't what we want. The ^
indicates beginning of the string, |
is an OR statement and the space is, well, a space. Similar thing on the other end except the $
means match at the end of a string. Therefore, in English, find the class name if it's the first or last part of the string or if there is a space on either side of the class name (for those of you who actually use more than one class on an element).
Conversation
You should check out Simon Willison's slick JavaScript function that grabs any CSS selector, including, I believe, class names:
getElementsBySelector
I used the one from here for CSS Reboot:
Both seems great, but both with the same change, because of IE5
first one
second one
The first one seems also great, I am using already the second with together this function
It realy very universal a usefull function
I'm happily using
http://neo.dzygn.com/archive/2003/10/attributecrawler
Are all these methods certified working in all the recent browsers?
Why use regexp?
Mats: the regex helps match against word boundaries. The problem with your function is that a search for "mydiv" would return elements "mydiv" AND "notmydiv".
flevour: mine hasn't been specifically tested in all recent browsers. Some research seemed to indicate that older versions of Safari (iirc) don't support using * with getElementsByTagName and would therefore return an empty array.
Hmm, somebody is using my Attribute Crawler script? Honestly I had forgotten about it.... but looking at the code now, the implementation looks quite nice. Perhaps I should revisit it :)
Check the `parseSelector` method I wrote for sIFR, that one is pretty nice too.
BTW, in IE 5.01 you can't select all tags using `document.getElementsByTagName("*")`. You'll have to use `document.all`. Not sure if it applies to IE 5.5 as well....
That's a big 10-4! :-D
Any version that uses getElementsByTagName will be pretty expensive to use.
See what daniel glazman said on the subject a while ago:
http://daniel.glazman.free.fr/weblog/newarchive/2003_06_01_glazblogarc.html#s95287073
dead in the wake of it all
Hey Jonathan,
That regex for finding a classname is actually unreliable. JavaScript word boundaries match on some things you don't want.
It's safer to parse it yourself:
/(^| )classname( |$)/
I like the site! nice and clean.
It seems to me this would be all i'd want:
Todd, that would miss any elements that contain the class you're searching for if it's accompanied by any additional classes.
For example, if you're looking for elements with the class "foo", your code wouldn't return any elements with, say class="bar foo".
Since I'm working on a page that both a) needs to support MacIE and b) is trying to getElementsByClassName of elements that sometimes have multiple classes (e.g. sometimes just class="item" and other times class="item last"), I have been having a little trouble with the getElementsByClassNames functions I have found up till now (MacIE doesn't support the push() method).
I think a hybrid of the functions I've found here on this page (and another page) seem to have worked, though:
I haven't tested the Opera part, but I can't imagine it doing much damage.
BTW, the positioning and previewing of this comment form are awesome. Kudos!
p.s. Most posters here didn't escape the "less than" (<) in their for loops, so half of them are cut off (which is why I had to go to another site to see if these same functions were copied elsewhere).
Max: thanks for pointing out the escaping issue... I've gone over the previous comments and encoded them.
The version I use (actually hauntingly similar to some of these), working fine in at least Opera, Mozilla and IE:
I got a version working that is both a hybrid of the XPATH version by Glazman and a version i cooked up that works in IE as well.
NOTE: It matches only if it has 1 class name in Gecko, but matches multiple classes in IE. How can we change the XPATH to do better multi-selector matching?
Sorry, the less than symbol messed things up a bit.
This will also do matching, but its more inclusive that I'd like it to be. If we're looking for a className of "vButton" it would also match "uvButton" and vButtonz as well.
Hi there; your site design rocks.
Why getElementsByClassName when you can getElementsBySelector? See Behaviour:
http://bennolan.com/behaviour/
- Ian
@Ron: Wouldn't adding a space either side of the classname give you the desired effect?
Might need some quotes to get it to honour the spaces.
Mats' non-regex proposal can easily be made to work by padding with spaces: