javascript document.getElementsByClassName与IE的兼容性


76

检索具有特定类的元素数组的最佳方法是什么?

我会使用document.getElementsByClassName,但是IE不支持它。

所以我尝试了乔纳森·斯努克的解决方案

function getElementsByClassName(node, classname) {
    var a = [];
    var re = new RegExp('(^| )'+classname+'( |$)');
    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;
}
var tabs = document.getElementsByClassName(document.body,'tab');

...但是IE仍然说:

对象不支持此属性或方法

任何想法,更好的方法,错误修复?

我不希望使用任何涉及jQuery或其他“笨拙的javascript”的解决方案。

更新:

我知道了!

正如@joe提到的,该函数不是的方法document

因此,工作代码如下所示:

function getElementsByClassName(node, classname) {
    var a = [];
    var re = new RegExp('(^| )'+classname+'( |$)');
    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;
}
var tabs = getElementsByClassName(document.body,'tab');


...此外,如果您只需要IE8 +支持,那么它将起作用:

if(!document.getElementsByClassName) {
    document.getElementsByClassName = function(className) {
        return this.querySelectorAll("." + className);
    };
    Element.prototype.getElementsByClassName = document.getElementsByClassName;
}

像平常一样使用它:

var tabs = document.getElementsByClassName('tab');

2
您确定更新正确吗?不应该是var tabs = getElementsByClassName(document.body,'tab'); **注意我删除了document.getEle ... **
Anthony

您最近的例子正确吗?您正在传递“ .tab”,但由于内部方法添加了句点,所以它也不应该没有句点吗?如果它是IE9 +,那么它也没有句点?它不应该是var tabs = document.getElementsByClassName('tab');吗?最后两个示例相同时,为什么会有一个“或”呢?我肯定错过了什么。
BoBoCoding '16

@BoBoCoding已修复。
Web_Designer '16

另请参见Polyfill中的getElementsByClassNamepolyfill要点以了解特定用途的getElementsByClassName
Vadzim

Answers:


56

这不是记录方法:

function getElementsByClassName(node, classname) {
    var a = [];
    var re = new RegExp('(^| )'+classname+'( |$)');
    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;
}

tabs = getElementsByClassName(document.body,'tab');  // no document

您是在jsFiddle.net还是您自己的服务器/机器上进行测试?

@inquisitive_web_developer-您现在遇到什么错误?它在哪条线上中断?
nnnnnn

17

您可以为较旧的浏览器创建该功能

if (typeof document.getElementsByClassName!='function') {
    document.getElementsByClassName = function() {
        var elms = document.getElementsByTagName('*');
        var ei = new Array();
        for (i=0;i<elms.length;i++) {
            if (elms[i].getAttribute('class')) {
                ecl = elms[i].getAttribute('class').split(' ');
                for (j=0;j<ecl.length;j++) {
                    if (ecl[j].toLowerCase() == arguments[0].toLowerCase()) {
                        ei.push(elms[i]);
                    }
                }
            } else if (elms[i].className) {
                ecl = elms[i].className.split(' ');
                for (j=0;j<ecl.length;j++) {
                    if (ecl[j].toLowerCase() == arguments[0].toLowerCase()) {
                        ei.push(elms[i]);
                    }
                }
            }
        }
        return ei;
    }
}

14
function getElementsByClassName(className) {
if (document.getElementsByClassName) { 
  return document.getElementsByClassName(className); }
else { return document.querySelectorAll('.' + className); } }

可以肯定的是,这与列昂尼德的函数相同,但是会document.getElementsByClassName在可能的情况下使用。


10

您实际上不能复制getElementsByClassName,因为它返回一个nodeList,因此它的值是活动的,并随文档更新。

您可以返回共享相同类名的静态元素数组-但在文档更改时它不会“知道”。

(不需要太多这类事情就可以使图书馆看起来更苗条……)

function getArrayByClassNames(classes, pa){
    if(!pa) pa= document;
    var C= [], G;
    if(pa.getElementsByClassName){
        G= pa.getElementsByClassName(classes);
        for(var i= 0, L= G.length; i<L; i++){
            C[i]= G[i];
        }
    }
    else{
        classes= classes.split(/\s+/);
        var who, cL= classes.length,
        cn, G= pa.getElementsByTagName('*'), L= G.length;
        for(var i= 0; i<cL; i++){
            classes[i]= RegExp('\\b'+classes[i]+'\\b');
        }
        classnameLoop:
        while(L){
            who= G[--L];
            cn= who.className;
            if(cn){
                for(var i= 0; i<cL; i++){
                    if(classes[i].test(cn)== false) {
                        continue classnameLoop;
                    }
                }
                C.push(who);
            }
        }
    }
    return C;
}

//例

var A = getArrayByClassNames('sideBar local')


3
+1是因为注意到与real不同getElementsByClassName,兼容性技巧(包括querySelectorAll)提供了静态快照,而不是实时集合。
索伦·勒夫堡

9

IE8:

document.getElementsByClassName = function (className) {
    return document.querySelectorAll('.' + className)
}

1
在我的IE9上不起作用:“对象不支持属性或方法'querySelectorAll'”
Phil

0
function _getClass(whatEverClasNameYouWant){
var a=document.getElementsByTagName('*');
   for(b in a){
      if((' '+a[b].className+' ').indexOf(' '+whatEverClasNameYouWant+' ')>-1){
      return a[b];
      }
   }
}

0

我只想改善querySelectorAllIE8的备用广告。

与其他人一样回答,简单的方法是添加的功能Element.prototype

this.querySelectorAll('.' + className);

但是有一些问题:

  • 它不适用于未修饰的字符串(开头)。
  • 它不适用于多个类。
  • 它不“怪”级的人物合作(/$*等)
  • 它不适用于以数字开头(无效的标识符)的类

这意味着应该有一些“修复”,例如:

"abcd"     ->  ".abcd"
"a   b cd" ->  ".a.b.cd"
"   a b  " ->  ".a.b  "
"a/b$c d"  ->  ".a\/b\$c.d"
"1234"     ->  ".\000031234"

码:

this.querySelectorAll(className
    .replace(/(?=[^ \w])/g, '\\')   // Escape non-word characters
    .replace(/\b\d/g, '\\00003$&')  // Escape digits at the beginning
    .replace(/(^| +)(?!$| )/g, '.') // Add "." before classes, removing spaces
);

1
该功能也可以添加到HTMLDocument.prototype以便与一起使用document
Oriol 2014年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.