Two and a half years ago, I released the first version of getElementsByClassName. With how web browsers has evolved since, I thought I’d release a real ultimate version, dated 2008.
Native Web Browser Support
Safari 3.1 has native getElmentsByClassName
support, and upcoming Firefox 3 and Opera 9.5 will have it too. It only leaves out, you’ve guessed it, Internet Explorer.
The Necessity Of This Script
Living in a world where Microsoft is halting every possible way the web could evolve, this means that you will need a custom script for this for years to come. Also, the native version returns just a nodelist, as opposed to an array
, which may somewhat limit your options to work with it.
New Features
When I rewrote the script (download new version), there were a number of factors I wanted to include to make it the best script available for this task:
- Utilize native
getElementsByClassName
support if it’s available. - Utilize native
XPath
support if it’s available. - Support multiple class names in the same call, in any order specified.
- Return an actual
array
to work with, instead of just the native nodelists.
The way it works is that it detects the available native support, and then re-uses that for consecutive calls. This will lead top optimal performance for the end user experience. Please take a look at the demo page, which consists of a hefty 130 kb raw HTML, to compare execution times between call types, web browsers and platforms.
The Script
The script should support basically any web browser being used today, and also has support back till IE 5.5. This is how the script now looks like:
01.
/*
02.
Developed by Robert Nyman, http://www.robertnyman.com
03.
Code/licensing: http://code.google.com/p/getelementsbyclassname/
04.
*/
05.
var
getElementsByClassName =
function
(className, tag, elm){
06.
if
(document.getElementsByClassName) {
07.
getElementsByClassName =
function
(className, tag, elm) {
08.
elm = elm || document;
09.
var
elements = elm.getElementsByClassName(className),
10.
nodeName = (tag)?
new
RegExp(
"\\b"
+ tag +
"\\b"
,
"i"
) :
null
,
11.
returnElements = [],
12.
current;
13.
for
(
var
i=0, il=elements.length; i<il; i+=1){
14.
current = elements[i];
15.
if
(!nodeName || nodeName.test(current.nodeName)) {
16.
returnElements.push(current);
17.
}
18.
}
19.
return
returnElements;
20.
};
21.
}
22.
else
if
(document.evaluate) {
23.
getElementsByClassName =
function
(className, tag, elm) {
24.
tag = tag ||
"*"
;
25.
elm = elm || document;
26.
var
classes = className.split(
" "
),
27.
classesToCheck =
""
,
28.
xhtmlNamespace =
"http://www.w3.org/1999/xhtml"
,
29.
namespaceResolver = (document.documentElement.namespaceURI === xhtmlNamespace)? xhtmlNamespace :
null
,
30.
returnElements = [],
31.
elements,
32.
node;
33.
for
(
var
j=0, jl=classes.length; j<jl; j+=1){
34.
classesToCheck +=
"[contains(concat(' ', @class, ' '), ' "
+ classes[j] +
" ')]"
;
35.
}
36.
try
{
37.
elements = document.evaluate(
".//"
+ tag + classesToCheck, elm, namespaceResolver, 0,
null
);
38.
}
39.
catch
(e) {
40.
elements = document.evaluate(
".//"
+ tag + classesToCheck, elm,
null
, 0,
null
);
41.
}
42.
while
((node = elements.iterateNext())) {
43.
returnElements.push(node);
44.
}
45.
return
returnElements;
46.
};
47.
}
48.
else
{
49.
getElementsByClassName =
function
(className, tag, elm) {
50.
tag = tag ||
"*"
;
51.
elm = elm || document;
52.
var
classes = className.split(
" "
),
53.
classesToCheck = [],
54.
elements = (tag ===
"*"
&& elm.all)? elm.all : elm.getElementsByTagName(tag),
55.
current,
56.
returnElements = [],
57.
match;
58.
for
(
var
k=0, kl=classes.length; k<kl; k+=1){
59.
classesToCheck.push(
new
RegExp(
"(^|\\s)"
+ classes[k] +
"(\\s|$)"
));
60.
}
61.
for
(
var
l=0, ll=elements.length; l<ll; l+=1){
62.
current = elements[l];
63.
match =
false
;
64.
for
(
var
m=0, ml=classesToCheck.length; m<ml; m+=1){
65.
match = classesToCheck[m].test(current.className);
66.
if
(!match) {
67.
break
;
68.
}
69.
}
70.
if
(match) {
71.
returnElements.push(current);
72.
}
73.
}
74.
return
returnElements;
75.
};
76.
}
77.
return
getElementsByClassName(className, tag, elm);
78.
};
How To Call It And Parameters
Parameters
className
- One or several class names, separated by space. Multiple class names demands that each match have all of the classes specified. Mandatory.
tag
- Specifies the tag name of the elements to match. Optional.
elm
- Reference to a DOM element to look amongst its children for matches. Recommended for better performance in larger documents. Optional.
Call Examples
- To get all elements in the document with a “info-links†class.
getElementsByClassName("info-links");
- To get all div elements within the element named “containerâ€, with a “col†class.
getElementsByClassName("col", "div", document.getElementById("container"));
- To get all elements within in the document with a “click-me†and a “sure-thang†class.
getElementsByClassName("click-me sure-thang");
Download The New GetElementsByClassName
The new version is available for download right as we speak, so by all means, download it, take it for a spin, and experience selecting elements through their class names cross-browser, cross-platform without having to worry about any differences.
Source:http://robertnyman.com/2008/05/27/the-ultimate-getelementsbyclassname-anno-2008/