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 ... **
Ентоні

Чи правильні ваші останні приклади? Ви передаєте '.tab', але чи не повинно бути без періоду, оскільки ваш внутрішній метод додає крапку, і якщо це IE9 +, то у нього теж немає періоду? Це не має бути var tabs = document.getElementsByClassName ('tab') ;? І чому у вас є "або", коли два останні приклади однакові? Напевно, мені чогось не вистачає.
BoBoCoding

@BoBoCoding виправлено.
Web_Designer

Відповіді:


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 за зауваження, що на відміну від реального getElementsByClassName, хакі сумісності (у тому числі querySelectorAll) надають статичні знімки, а не реальні колекції.
Søren Løvborg

9

IE8:

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

1
Не працює на моєму IE9: "Об'єкт не підтримує властивість або метод 'querySelectorAll'"
Філ

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

0

Я просто хочу покращити 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
);

1
Функцію також можна додати HTMLDocument.prototype, щоб використовувати її з document.
Oriol
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.