getElementsByClassName in ie8
Solution 1
Here is a quick solution by extending the Element.prototype
and the document
:
(function() {
if (!document.getElementsByClassName) {
var indexOf = [].indexOf || function(prop) {
for (var i = 0; i < this.length; i++) {
if (this[i] === prop) return i;
}
return -1;
};
getElementsByClassName = function(className, context) {
var elems = document.querySelectorAll ? context.querySelectorAll("." + className) : (function() {
var all = context.getElementsByTagName("*"),
elements = [],
i = 0;
for (; i < all.length; i++) {
if (all[i].className && (" " + all[i].className + " ").indexOf(" " + className + " ") > -1 && indexOf.call(elements, all[i]) === -1) elements.push(all[i]);
}
return elements;
})();
return elems;
};
document.getElementsByClassName = function(className) {
return getElementsByClassName(className, document);
};
if(Element) {
Element.prototype.getElementsByClassName = function(className) {
return getElementsByClassName(className, this);
};
}
}
})();
It's not always, however, the best idea to extend the prototype object, especially with a function named exactly like a non-existent native function. If you want to escape the problems caused by extension of the prototype, use this code:
(function() {
var indexOf = [].indexOf || function(prop) {
for (var i = 0; i < this.length; i++) {
if (this[i] === prop) return i;
}
return -1;
};
window.getElementsByClassName = function(className,context) {
if (context.getElementsByClassName) return context.getElementsByClassName(className);
var elems = document.querySelectorAll ? context.querySelectorAll("." + className) : (function() {
var all = context.getElementsByTagName("*"),
elements = [],
i = 0;
for (; i < all.length; i++) {
if (all[i].className && (" " + all[i].className + " ").indexOf(" " + className + " ") > -1 && indexOf.call(elements,all[i]) === -1) elements.push(all[i]);
}
return elements;
})();
return elems;
};
})();
That way, you can safely use a getElementsByClassName()
function that accepts two arguments:
className
: the CSS classcontext
: the node
Solution 2
IE8 doesn't support getElementsByClassName
, but it does support querySelectorAll
.
To use querySelectorAll
, you need a valid class selector, which means it needs to use the Selectors API syntax for a class, which uses a .
to signify a class.
function test2(className, link) {
var e = document.querySelectorAll("." + className);
for (var i = 0, len = e.length; i < len; i++) {
e[i].style.display = "none";
}
link.innerHTML = "Expand";
}
Solution 3
You can implement it yourself if it's not there:
// shim for older browsers:
if (!document.getElementsByClassName) {
document.getElementsByClassName = (function(){
// Utility function to traverse the DOM:
function traverse (node, callback) {
callback(node);
for (var i=0;i < node.childNodes.length; i++) {
traverse(node.childNodes[i],callback);
}
}
// Actual definition of getElementsByClassName
return function (name) {
var result = [];
traverse(document.body,function(node){
if (node.className == name) {
result.push(node);
}
});
return result;
}
})()
}
Now you can use document.getElementsByClassName
in older browsers. One difference between the shim and the native implementation is that the shim returns a real array rather than nodelist (or htmlelementcollection).
stefan
Updated on June 13, 2022Comments
-
stefan almost 2 years
I'm trying to create a collapsable list in Internet Explorer 8 for the HTML I have:
<li> <a href="#" onclick="test('node1')">hello</a> <ul id="node1" class="node" style="display:none"> <li>Sub-item 1</li> <li>Sub-item 2</li> </ul> </li> <li> <a href="#" onclick="test('node2')">test</a> <ul id="node2" class="node" style="display:none"> <li>Sub-item 1</li> <li>Sub-item 2</li> </ul> </li>
in javascript i have
function test2(className, link) { var e = document.getElementsByClassName(className); for (var i = 0, len = e.length; i < len; i++) { e[i].style.display = "none"; } link.innerHTML = "Expand"; }
I'm using this to call it:
<a href="#" onclick="test2('node', this)">Collapse</a>
Unfortunately, this method is not working in IE8, and neither is
querySelectAll
. Can someone provide an example how to fix this please? -
stefan over 11 yearsim getting an error in ie saying does not support this property or method?
-
I Hate Lazy over 11 yearsNot sure why that would be. IE8 and higher supports it.
-
stefan over 11 yearsis there another way to do this? it works on chrome and firefox but not ie8 for me
-
inhan over 11 yearsLooks like it really does. Check it here: caniuse.com/queryselector
-
stefan over 11 yearsyeah i dont understand this! so frustrating, how would you do it say if i were using ie7?
-
I Hate Lazy over 11 years@stefan: You would do a
document.getElementsByTagName("*");
, and the iterate the results and manually test for the class name. You'll be able to find other questions on StackOverflow that show how. -
RobG over 11 years@stefan—make sure IE is in standards mode by including a DOCTYPE. If there's no DOCTYPE, IE goes into quirks mode and some versions hide various W3C DOM methods.
-
Bruce over 10 yearsThis is a great answer!
-
oxygen over 10 yearsOh, why did you have to make me choose between the two? The decision is killing me!