web-dev-qa-db-fra.com

javascript document.getElementsByClassName compatible avec IE

Quelle est la meilleure méthode pour récupérer un tableau d'éléments ayant une certaine classe?

J'utiliserais document.getElementsByClassName mais IE ne le prend pas en charge.

J'ai donc essayé solution de Jonathan Snook :

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

... mais IE dit toujours:

L'objet ne prend pas en charge cette propriété ou cette méthode

Des idées, de meilleures méthodes, des corrections de bugs?

Je préférerais ne pas utiliser de solutions impliquant jQuery ou un autre "javascript volumineux".

Mise à jour:

Je l'ai au travail!

Comme @ joe mentionné la fonction n'est pas une méthode de document.

Donc, le code de travail ressemblerait à ceci:

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


... Aussi si vous avez seulement besoin du support de IE8 + , alors cela fonctionnera:

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

Utilisez-le comme d'habitude:

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

Ce n'est pas une méthode de 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;
}

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

vous pouvez créer la fonction pour les anciens navigateurs

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;
    }
}
17
gdarcan
function getElementsByClassName(className) {
if (document.getElementsByClassName) { 
  return document.getElementsByClassName(className); }
else { return document.querySelectorAll('.' + className); } }

Je suis presque sûr que c'est la même chose que la fonction de Leonid, mais cela utilise document.getElementsByClassName quand il le peut.

13
Mike_OBrien

Vous ne pouvez pas vraiment répliquer getElementsByClassName, car il renvoie une liste de noeuds; sa valeur est donc en direct et se met à jour avec le document.

Vous pouvez retourner un tableau statique d'éléments qui partagent les mêmes noms de classe, mais il ne "saura pas" quand le document sera modifié.

(Il ne faudra pas beaucoup de ce genre de choses pour rendre une bibliothèque svelte ...)

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

//Exemple

var A = getArrayByClassNames ('sideBar local'))

10
kennebec

IE8:

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

Je veux juste améliorer querySelectorAll le repli pour IE8.

Comme d’autres, le moyen le plus simple est d’ajouter la fonction à Element.prototype avec

this.querySelectorAll('.' + className);

Mais il y a quelques problèmes:

  • Cela ne fonctionne pas avec les chaînes non limitées (au début).
  • Cela ne fonctionne pas avec plusieurs classes.
  • Cela ne fonctionne pas avec des caractères de classe "étranges" (/, $, *, etc.)
  • Cela ne fonctionne pas avec les classes qui commencent par un chiffre (identificateurs non valides)

Cela signifie qu'il devrait y avoir une "réparation", par exemple:

"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
);
0
Oriol