Kompatibilität von Javascript document.getElementsByClassName mit IE


76

Was ist die beste Methode, um ein Array von Elementen mit einer bestimmten Klasse abzurufen?

Ich würde document.getElementsByClassName verwenden, aber der IE unterstützt es nicht.

Also habe ich Jonathan Snooks Lösung ausprobiert :

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

... aber IE sagt immer noch:

Object unterstützt diese Eigenschaft oder Methode nicht

Irgendwelche Ideen, bessere Methoden, Fehlerbehebungen?

Ich würde es vorziehen, keine Lösungen mit jQuery oder anderem "sperrigem Javascript" zu verwenden.

Aktualisieren:

Ich habe es zum Laufen gebracht!

Wie @joe erwähnte, ist die Funktion keine Methode von document.

Der Arbeitscode würde also so aussehen:

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


... Auch wenn Sie nur IE8 + -Unterstützung benötigen, funktioniert dies:

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

Verwenden Sie es wie gewohnt:

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

2
Sind Sie sicher, dass Ihr Update richtig ist? Sollte es nicht var tabs = getElementsByClassName sein (document.body, 'tab'); **
Anthony

Sind Ihre letzten Beispiele richtig? Sie übergeben '.tab', aber sollte es nicht ohne den Punkt sein, da Ihre innere Methode den Punkt hinzufügt und wenn es IE9 + ist, hat es auch keinen Punkt? Sollte es nicht var tabs = document.getElementsByClassName ('tab') sein? Und warum haben Sie ein "oder", wenn die letzten beiden Beispiele gleich sind? Mir muss etwas fehlen.
BoBoCoding

@BoBoCoding behoben.
Web_Designer

Siehe auch getElementsByClassNamePolyfill- Kern in Polyfill für getElementsByClassName für bestimmte Verwendungszwecke .
Vadzim

Antworten:


56

Es ist keine Methode des Dokuments:

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

Testen Sie auf jsFiddle.net oder Ihrem eigenen Server / Computer?
Joe

@inquisitive_web_developer - Welchen Fehler bekommen Sie jetzt? Auf welcher Linie bricht es?
nnnnnn

17

Sie können die Funktion für ältere Browser erstellen

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

Ich bin mir ziemlich sicher, dass dies die gleiche Funktion wie Leonid ist, aber dies wird verwendet, document.getElementsByClassNamewenn es möglich ist.


10

Sie können getElementsByClassName nicht wirklich replizieren, da es eine nodeList zurückgibt und sein Wert daher aktiv ist und mit dem Dokument aktualisiert wird.

Sie können ein statisches Array von Elementen zurückgeben, die dieselben Klassennamen haben, aber nicht wissen, wann sich das Dokument ändert.

(Es werden nicht zu viele dieser Dinge nötig sein, um eine Bibliothek schlank aussehen zu lassen ...)

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

//Beispiel

var A = getArrayByClassNames ('sideBar local')


3
+1 für die Feststellung, dass getElementsByClassNamedie Kompatibilitäts-Hacks (einschließlich querySelectorAll) im Gegensatz zum Real statische Snapshots und keine Live-Sammlungen liefern.
Søren Løvborg

9

IE8:

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

1
Funktioniert nicht auf meinem IE9: "Objekt unterstützt keine Eigenschaft oder Methode '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

Ich möchte nur den querySelectorAllFallback für IE8 verbessern .

Wie andere geantwortet haben, besteht der einfache Weg darin, die Funktion Element.prototypemit hinzuzufügen

this.querySelectorAll('.' + className);

Es gibt jedoch einige Probleme:

  • Es funktioniert nicht mit unbeschnittenen Zeichenfolgen (am Anfang).
  • Es funktioniert nicht mit mehreren Klassen.
  • Es funktioniert nicht mit „fremden“ Klassenzeichen funktioniert ( /, $, *, etc.)
  • Es funktioniert nicht mit Klassen, die mit einer Ziffer beginnen (ungültige Bezeichner).

Das heißt, es sollte einige "Korrekturen" geben, zum Beispiel:

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

Code:

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
Die Funktion kann auch hinzugefügt HTMLDocument.prototypewerden, um sie mit zu verwenden document.
Oriol
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.