javascript document.getElementsByClassName 与 IE 的兼容性

Posted

技术标签:

【中文标题】javascript document.getElementsByClassName 与 IE 的兼容性【英文标题】:javascript document.getElementsByClassName compatibility with IE 【发布时间】:2011-11-16 16:17:28 【问题描述】:

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

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

所以我尝试了Jonathan Snook's solution:

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 mentioned,函数不是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');

【问题讨论】:

您确定您的更新是正确的吗?不应该是 var tabs = getElementsByClassName(document.body,'tab'); **注意我删除了 document.getEle... ** 你最后的例子正确吗?您正在传递“.tab”,但它不应该没有句点,因为您的内部方法添加了句点,如果它是 IE9+,那么它也没有句点?不应该是 var tabs = document.getElementsByClassName('tab'); 吗?当最后两个示例相同时,为什么会有“或”?我一定是错过了什么。 @BoBoCoding 已修复。 另见getElementsByClassName polyfill gist in Polyfill for getElementsByClassName for particular uses。 【参考方案1】:

这不是文档的方法:

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 - 你现在遇到什么错误?它在哪条线上突破?【参考方案2】:

您可以为旧版浏览器创建函数

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;
    

【讨论】:

【参考方案3】:
function getElementsByClassName(className) 
if (document.getElementsByClassName)  
  return document.getElementsByClassName(className); 
else  return document.querySelectorAll('.' + className);  

很确定这与 Leonid 的功能相同,但它尽可能使用document.getElementsByClassName

【讨论】:

【参考方案4】:

你不能真正复制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')

【讨论】:

+1 指出与真正的 getElementsByClassName 不同,兼容性黑客(包括 querySelectorAll)提供静态快照,而不是实时集合。【参考方案5】:

IE8:

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

【讨论】:

在我的 IE9 上不起作用:“对象不支持属性或方法 'querySelectorAll'”【参考方案6】:
function _getClass(whatEverClasNameYouWant)
var a=document.getElementsByTagName('*');
   for(b in a)
      if((' '+a[b].className+' ').indexOf(' '+whatEverClasNameYouWant+' ')>-1)
      return a[b];
      
   

【讨论】:

【参考方案7】:

我只是想改进querySelectorAll IE8 的后备。

像其他人回答的那样,简单的方法是将函数添加到Element.prototype with

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
);

【讨论】:

该函数也可以添加到htmlDocument.prototype,以便与document一起使用。

以上是关于javascript document.getElementsByClassName 与 IE 的兼容性的主要内容,如果未能解决你的问题,请参考以下文章

Anchor 对象和document对象

使用 javascript 将画布添加到页面

如何使用 JavaScript 在 div 中插入多个元素?

用星号javascript/jquery替换数字?

Javascript 在按钮单击时清除表单字段

selenium-JavaScript的处理