javascript document.getElementsByClassName совместимость с IE - PullRequest
75 голосов
/ 14 сентября 2011

Каков наилучший метод для получения массива элементов, имеющих определенный класс?

Я бы использовал 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');

Ответы [ 7 ]

55 голосов
/ 14 сентября 2011

Это не метод документа:

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
17 голосов
/ 12 декабря 2011

вы можете создать функцию для старых браузеров

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;
    }
}
13 голосов
/ 31 октября 2011
function getElementsByClassName(className) {
if (document.getElementsByClassName) { 
  return document.getElementsByClassName(className); }
else { return document.querySelectorAll('.' + className); } }

Уверен, это то же самое, что и функция Леонида, но при этом используется document.getElementsByClassName, когда это возможно.

10 голосов
/ 14 сентября 2011

Вы не можете действительно реплицировать 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')

9 голосов
/ 14 сентября 2011

IE8:

document.getElementsByClassName = function (className) {
    return document.querySelectorAll('.' + className)
}
0 голосов
/ 09 февраля 2014

Я просто хочу улучшить querySelectorAll откат для IE8.

Как и другие ответили, простой способ - добавить функцию к 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
    );
    
0 голосов
/ 02 февраля 2012
function _getClass(whatEverClasNameYouWant){
var a=document.getElementsByTagName('*');
   for(b in a){
      if((' '+a[b].className+' ').indexOf(' '+whatEverClasNameYouWant+' ')>-1){
      return a[b];
      }
   }
}
...