Vérifiez si un élément contient une classe en JavaScript?


588

En utilisant du JavaScript simple (pas jQuery), existe-t-il un moyen de vérifier si un élément contient une classe?

Actuellement, je fais ceci:

var test = document.getElementById("test");
var testClass = test.className;

switch (testClass) {
  case "class1":
    test.innerHTML = "I have class1";
    break;
  case "class2":
    test.innerHTML = "I have class2";
    break;
  case "class3":
    test.innerHTML = "I have class3";
    break;
  case "class4":
    test.innerHTML = "I have class4";
    break;
  default:
    test.innerHTML = "";
}
<div id="test" class="class1"></div>

Le problème est que si je change le HTML en ceci ...

<div id="test" class="class1 class5"></div>

... il n'y a plus de correspondance exacte, donc j'obtiens la sortie par défaut de Nothing ( ""). Mais je veux toujours que la sortie soit I have class1parce que la contient<div> toujours la classe..class1


5
element.classList.contains (cls)
Ronnie Royston

Réponses:


1039

Utilisez la méthode:element.classList .contains

element.classList.contains(class);

Cela fonctionne sur tous les navigateurs actuels et il existe également des polyfills pour prendre en charge les anciens navigateurs.


Alternativement , si vous travaillez avec des navigateurs plus anciens et que vous ne souhaitez pas utiliser de polyfills pour les corriger, l'utilisation indexOfest correcte, mais vous devez l'ajuster un peu:

function hasClass(element, className) {
    return (' ' + element.className + ' ').indexOf(' ' + className+ ' ') > -1;
}

Sinon, vous obtiendrez également truesi la classe que vous recherchez fait partie d'un autre nom de classe.

DEMO

jQuery utilise une méthode similaire (sinon la même).


Appliqué à l'exemple:

Comme cela ne fonctionne pas avec l'instruction switch, vous pouvez obtenir le même effet avec ce code:

var test = document.getElementById("test"),
    classes = ['class1', 'class2', 'class3', 'class4'];

test.innerHTML = "";

for(var i = 0, j = classes.length; i < j; i++) {
    if(hasClass(test, classes[i])) {
        test.innerHTML = "I have " + classes[i];
        break;
    }
}

C'est aussi moins redondant;)


Génial, mais comment puis-je utiliser cela en combinaison avec l'instruction switch afin de pouvoir modifier la sortie en fonction des classes contenues dans le div?
daGUY

@daGUY: Que voulez-vous faire de toute façon avec l'instruction switch? Par exemple, la seconde diva deux classes mais elle ne sortira que I have class1lorsque vous utilisez break. Si vous souhaitez afficher chaque classe d'un élément, vous pouvez simplement prendre le classNameet le diviser sur des espaces blancs. Ou quel est votre objectif réel?
Felix Kling

@Felix Kling: J'ai besoin que le innerHTML du div change entre quatre chaînes différentes selon la classe qu'il contient. J'ai juste utilisé "J'ai la classe 1", etc. comme exemples - les vraies chaînes sont toutes différentes. Je ne montrerai qu'une chaîne à la fois, sans en combiner (d'où les ruptures après chaque cas). Je veux juste qu'il fonctionne toujours même si la classe correspondante est l'une des multiples classes sur le div.
daGUY

@Felix Kling: ça y est, merci beaucoup! En fait, je ne génère pas les noms des classes, mais plutôt l'une des quatre chaînes entièrement différentes, donc je l'ai légèrement modifiée avec quelques instructions IF / ELSE IF pour gérer chacune. Fonctionne parfaitement bien.
daGUY

1
Y a-t-il une raison spécifique pour laquelle vous avez ajouté des espaces avant et après?
Ced


49

Dans les navigateurs modernes, vous pouvez simplement utiliser la containsméthode de Element.classList:

testElement.classList.contains(className)

Démo

var testElement = document.getElementById('test');

console.log({
    'main' : testElement.classList.contains('main'),
    'cont' : testElement.classList.contains('cont'),
    'content' : testElement.classList.contains('content'),
    'main-cont' : testElement.classList.contains('main-cont'),
    'main-content' : testElement.classList.contains('main-content')
});
<div id="test" class="main main-content content"></div>


Navigateurs pris en charge

entrez la description de l'image ici

(de CanIUse.com )


Polyfill

Si vous souhaitez utiliser Element.classListmais que vous souhaitez également prendre en charge les navigateurs plus anciens, pensez à utiliser ce polyfill d' Eli Gray .


10

Puisqu'il veut utiliser switch (), je suis surpris que personne ne l'ait encore proposé:

var test = document.getElementById("test");
var testClasses = test.className.split(" ");
test.innerHTML = "";
for(var i=0; i<testClasses.length; i++) {
    switch(testClasses[i]) {
        case "class1": test.innerHTML += "I have class1<br/>"; break;
        case "class2": test.innerHTML += "I have class2<br/>"; break;
        case "class3": test.innerHTML += "I have class3<br/>"; break;
        case "class4": test.innerHTML += "I have class4<br/>"; break;
        default: test.innerHTML += "(unknown class:" + testClasses[i] + ")<br/>";
    }
}

1
Je me demandais juste la même chose, mais oui, c'est le plus proche du problème d'origine!
Silver Ringvee

8

Element.matches ()

element.matches (selectorString)

Selon MDN Web Docs :

La Element.matches()méthode retourne truesi l'élément serait sélectionné par la chaîne de sélection spécifiée; sinon, revient false.

Par conséquent, vous pouvez utiliser Element.matches()pour déterminer si un élément contient une classe.

const element = document.querySelector('#example');

console.log(element.matches('.foo')); // true
<div id="example" class="foo bar"></div>

Afficher la compatibilité du navigateur


7

Voici un petit extrait Si vous essayez de vérifier si l'élément contient une classe, sans utiliser jQuery.

function hasClass(element, className) {
    return element.className && new RegExp("(^|\\s)" + className + "(\\s|$)").test(element.className);
}

Cela explique le fait que l'élément peut contenir plusieurs noms de classe séparés par un espace.

OU


Vous pouvez également affecter cette fonction au prototype d'élément.

Element.prototype.hasClass = function(className) {
    return this.className && new RegExp("(^|\\s)" + className + "(\\s|$)").test(this.className);
};

Et déclenchez-le comme ceci (très similaire à la .hasClass()fonction de jQuery ):

document.getElementById('MyDiv').hasClass('active');

Je préfère davantage cette solution. Il évite le problème du nom de classe correspondant partiellement à une autre classe et ne nécessite pas de polyfills pour fonctionner dans IE.
scoota269

5

Un oneliner simplifié: 1

function hasClassName(classname,id) {
 return  String ( ( document.getElementById(id)||{} ) .className )
         .split(/\s/)
         .indexOf(classname) >= 0;
}

1 indexOf pour les tableaux n'est pas pris en charge par IE (bien sûr). Il y a beaucoup de patchs de singe sur le net pour cela.


1
Le problème avec les limites de mot est que certains caractères valides pour les noms de classe tels que -sont considérés comme des limites de mot. Par exemple, la recherche fooet la classe est les foo-barrendements true.
Felix Kling

Tu as raison. Suppression de l'original, ajout d'une autre approche. Toujours un oneliner.
KooiInc

5

C'est un peu vieux, mais peut-être que quelqu'un trouvera ma solution utile:

// Fix IE's indexOf Array
if (!Array.prototype.indexOf) {
    Array.prototype.indexOf = function (searchElement) {
        if (this == null) throw new TypeError();
        var t = Object(this);
        var len = t.length >>> 0;
        if (len === 0) return -1;
        var n = 0;
        if (arguments.length > 0) {
            n = Number(arguments[1]);
            if (n != n) n = 0;
            else if (n != 0 && n != Infinity && n != -Infinity) n = (n > 0 || -1) * Math.floor(Math.abs(n));
        }
        if (n >= len) return -1;
        var k = n >= 0 ? n : Math.max(len - Math.abs(n), 0);
        for (; k < len; k++) if (k in t && t[k] === searchElement) return k;
        return -1;
    }
}
// add hasClass support
if (!Element.prototype.hasClass) {
    Element.prototype.hasClass = function (classname) {
        if (this == null) throw new TypeError();
        return this.className.split(' ').indexOf(classname) === -1 ? false : true;
    }
}

use: 'element.hasClass (' classname ');
Dementic

Pourquoi avez-vous utilisé t.length >>> 0? Pour autant que je sache, c'est un noop si vous utilisez «0», non?
Vitor Canova

wow tellement de code pour quelque chose de simple. Pourquoi ne pas utiliser une expression régulière et ne pas réinventer la roue? vous pouvez simplement utiliser /^class_name_you_are_searching_for$/.test(myElement.className)
pqsk

1
J'ai écrit ça trop vite. Juste pour ne pas trop compliquer mon expression régulière, ce serait /\s*class_name_you_are_searching_for\s*/.test(myElement.className)
pqsk

@pqsk - j'écris mes propres bibliothèques pour une utilisation future. et cela ne fait qu'ajouter à ma pile. bien sûr, d'autres solutions fonctionneraient, c'est juste ma façon préférée
Dementic

4

classNamen'est qu'une chaîne, vous pouvez donc utiliser la fonction indexOf standard pour voir si la liste des classes contient une autre chaîne.


1
Qu'en est-il des tests de classe classdans l'exemple ci-dessus?
Felix Kling

6
Par expérience, cette méthode peut être assez risquée: elle retournera vraie lorsque vous recherchez la classe foosur un élément qui a la foobarclasse.
Zirak

2
Bien sûr, vous n'avez qu'à être conscient de ce que vous testez. Le code de Felix fonctionne bien en utilisant des espaces comme délimiteur.
David

Ne tient pas compte des instances imbriquées d'un nom de classe. Exemple: «end» se trouve dans le nom de classe «frontend».
Anthony Rutledge

4

Je sais qu'il y a beaucoup de réponses mais la plupart d'entre elles concernent des fonctions supplémentaires et des classes supplémentaires. C'est celui que j'utilise personnellement; beaucoup plus propre et beaucoup moins de lignes de code!

if( document.body.className.match('category-page') ) { 
  console.log('yes');
}

1
cette méthode peut retourner des faux positifs lors de la recherche d'un nom de classe qui correspond partiellement - par exemple <body class="category-page">et document.body.className.match('page')- correspondra mais il n'y a pas de classe pageattachée à l'élément
hooblei

Peut être résolu avec \b, par exemple /\bpage\b/g, car il est regex (note: devez utiliser / /g).
Andrew

2

Voici une solution triviale insensible à la casse:

function hasClass(element, classNameToTestFor) {
    var classNames = element.className.split(' ');
    for (var i = 0; i < classNames.length; i++) {
        if (classNames[i].toLowerCase() == classNameToTestFor.toLowerCase()) {
            return true;
        }
    }
    return false;
}

2

Si l'élément n'a qu'un seul nom de classe, vous pouvez le vérifier rapidement en obtenant l'attribut de classe. Les autres réponses sont beaucoup plus robustes mais cela a certainement ses cas d'utilisation.

if ( element.getAttribute('class') === 'classname' ) {

}

2

J'ai créé une méthode prototype qui utilise classList, si possible, sinon recourt à indexOf:

Element.prototype.hasClass = Element.prototype.hasClass || 
  function(classArr){
    var hasClass = 0,
        className = this.getAttribute('class');
  
    if( this == null || !classArr || !className ) return false;
  
    if( !(classArr instanceof Array) )
      classArr = classArr.split(' ');

    for( var i in classArr )
      // this.classList.contains(classArr[i]) // for modern browsers
      if( className.split(classArr[i]).length > 1 )  
          hasClass++;

    return hasClass == classArr.length;
};


///////////////////////////////
// TESTS (see browser's console when inspecting the output)

var elm1 = document.querySelector('p');
var elm2 = document.querySelector('b');
var elm3 = elm1.firstChild; // textNode
var elm4 = document.querySelector('text'); // SVG text

console.log( elm1, ' has class "a": ', elm1.hasClass('a') );
console.log( elm1, ' has class "b": ', elm1.hasClass('b') );
console.log( elm1, ' has class "c": ', elm1.hasClass('c') );
console.log( elm1, ' has class "d": ', elm1.hasClass('d') );
console.log( elm1, ' has class "a c": ', elm1.hasClass('a c') );
console.log( elm1, ' has class "a d": ', elm1.hasClass('a d') );
console.log( elm1, ' has class "": ', elm1.hasClass('') );

console.log( elm2, ' has class "a": ', elm2.hasClass('a') );

// console.log( elm3, ' has class "a": ', elm3.hasClass('a') );

console.log( elm4, ' has class "a": ', elm4.hasClass('a') );
<p class='a b c'>This is a <b>test</b> string</p>
<svg xmlns="http://www.w3.org/2000/svg" width="100px" height="50px">
    <text x="10" y="20" class='a'>SVG Text Example</text>
</svg>

Page de test


Y a-t-il une raison pour laquelle vous souhaitez utiliser classlist au lieu d'index de e.className? On dirait que la perf est moins bonne
Ced

@Ced - eh bien, la perf n'est pas pertinente si vous ne testez pas des milliers d'éléments pour leur classe (elle sera probablement refactorisée dans les navigateurs à l'avenir). il est plus élégant à utiliser car le code décrit ses fonctionnalités, mais en fin de compte, peu importe, faites ce que vous voulez :)
vsync

1
  1. L'astuce de Felix d'ajouter des espaces pour encadrer le nom de classe et la chaîne que vous recherchez est la bonne approche pour déterminer si les éléments ont la classe ou non.

  2. Pour avoir un comportement différent selon la classe, vous pouvez utiliser des références de fonction ou des fonctions dans une carte:

    function fn1(element){ /* code for element with class1 */ }
    
    function fn2(element){ /* code for element with class2 */ }
    
    function fn2(element){ /* code for element with class3 */ }
    
    var fns={'class1': fn1, 'class2': fn2, 'class3': fn3};
    
    for(var i in fns) {
        if(hasClass(test, i)) {
            fns[i](test);
        }
    }
    • for (var i in fns) itère à travers les clés dans la carte fns.
    • Ne pas avoir de pause après fnsi permet au code d'être exécuté chaque fois qu'il y a une correspondance - de sorte que si l'élément a, fi, class1 et class2, fn1 et fn2 seront exécutés.
    • L'avantage de cette approche est que le code à exécuter pour chaque classe est arbitraire, comme celui de l'instruction switch; dans votre exemple, tous les cas ont effectué une opération similaire, mais demain, vous devrez peut-être faire des choses différentes pour chacun.
    • Vous pouvez simuler le cas par défaut en ayant une variable d'état indiquant si une correspondance a été trouvée dans la boucle ou non.


1

C'est un peu éteint, mais si vous avez un événement qui déclenche le changement, vous pouvez vous passer de classes:

<div id="classOne1"></div>
<div id="classOne2"></div>
<div id="classTwo3"></div>

Tu peux faire

$('body').click( function() {

    switch ( this.id.replace(/[0-9]/g, '') ) {
        case 'classOne': this.innerHTML = "I have classOne"; break;
        case 'classTwo': this.innerHTML = "I have classTwo"; break;
        default: this.innerHTML = "";
    }

});

.replace(/[0-9]/g, '')supprime les chiffres de id.

C'est un peu hacky, mais fonctionne pour les longs commutateurs sans fonctions supplémentaires ni boucles


1

Voir ce lien Codepen pour un moyen plus rapide et facile de vérifier un élément s'il a une classe spécifique en utilisant JavaScript vanilla ~!

hasClass (Vanilla JS)

function hasClass(element, cls) {
    return (' ' + element.className + ' ').indexOf(' ' + cls + ' ') > -1;
}

1

Ceci est pris en charge sur IE8 +.

Tout d'abord, nous vérifions s'il classListexiste, nous pouvons utiliser la containsméthode prise en charge par IE10 +. Si nous sommes sur IE9 ou 8, cela revient à utiliser une expression régulière, qui n'est pas aussi efficace mais qui est un polyfill concis.

if (el.classList) {
  el.classList.contains(className);
} else {
  new RegExp('(^| )' + className + '( |$)', 'gi').test(el.className);
}

Alternativement, si vous compilez avec babel, vous pouvez simplement utiliser: el.classList.contains(className);


0

Essaye celui-là:

document.getElementsByClassName = function(cl) {
   var retnode = [];
   var myclass = new RegExp('\\b'+cl+'\\b');
   var elem = this.getElementsByTagName('*');
   for (var i = 0; i < elem.length; i++) {
       var classes = elem[i].className;
       if (myclass.test(classes)) retnode.push(elem[i]);
   }
    return retnode;
};

1
Soyez prudent avec le mot limite. Il sera également vrai si vous avez par exemple une classe foo-baret recherchez foo.
Felix Kling

1
Salut Jimy, donc je cherchais ce métacaractère \ b et il ne considère que [ a-zA-Z0-9_] comme des caractères de mot. Donc, pour un nom de classe contenant un caractère moins, cela ne fonctionnera pas .
Stano

0

Je pense que la solution parfaite sera la suivante

if ($(this).hasClass("your_Class")) 
    alert("positive");            
else              
    alert("Negative");

8
1. "Utilisation de JavaScript simple (pas jQuery)" 2. Utilisez des crochets
nkmol

3 - utilisez la parenthèse
TheBlackBenzKid

0

dans quel élément se trouve actuellement la classe '.bar'? Voici une autre solution mais c'est à vous de décider.

var reg = /Image/g, // regexp for an image element
query = document.querySelector('.bar'); // returns [object HTMLImageElement]
query += this.toString(); // turns object into a string

if (query.match(reg)) { // checks if it matches
  alert('the class .bar is attached to the following Element:\n' + query);
}

démo jsfiddle

Bien sûr, ce n'est qu'une recherche pour 1 élément simple <img>( /Image/g) mais vous pouvez tout mettre dans un tableau comme <li>is /LI/g, <ul>= /UL/getc.


0

Juste pour ajouter à la réponse pour les personnes qui essaient de trouver des noms de classe dans des éléments SVG en ligne.

Changez la hasCLass()fonction en:

function hasClass(element, cls) {
    return (' ' + element.getAttribute('class') + ' ').indexOf(' ' + cls + ' ') > -1;
  }

Au lieu d'utiliser la classNamepropriété, vous devrez utiliser la getAttribute()méthode pour récupérer le nom de la classe.


0

J'ai créé ces fonctions pour mon site Web, j'utilise uniquement du javascript vanille, cela aidera peut-être quelqu'un. J'ai d'abord créé une fonction pour obtenir n'importe quel élément HTML:

//return an HTML element by ID, class or tag name
    var getElement = function(selector) {
        var elements = [];
        if(selector[0] == '#') {
            elements.push(document.getElementById(selector.substring(1, selector.length)));
        } else if(selector[0] == '.') {
            elements = document.getElementsByClassName(selector.substring(1, selector.length));
        } else {
            elements = document.getElementsByTagName(selector);
        }
        return elements;
    }

Ensuite, la fonction qui reçoit la classe à supprimer et le sélecteur de l'élément:

var hasClass = function(selector, _class) {
        var elements = getElement(selector);
        var contains = false;
        for (let index = 0; index < elements.length; index++) {
            const curElement = elements[index];
            if(curElement.classList.contains(_class)) {
                contains = true;
                break;
            }
        }
        return contains;
    }

Vous pouvez maintenant l'utiliser comme ceci:

hasClass('body', 'gray')
hasClass('#like', 'green')
hasClass('.button', 'active')

J'espère que cela vous aidera.


0

Astuce: Essayez de supprimer autant que possible les dépendances de jQuery dans vos projets - VanillaJS .

document.firstElementChildrenvoie la <html>balise puis l' classListattribut renvoie toutes les classes qui y sont ajoutées.

if(document.firstElementChild.classList.contains("your-class")){
    // <html> has 'your-class'
} else {
    // <html> doesn't have 'your-class'
}

-1

Pour moi, le moyen le plus élégant et le plus rapide d'y parvenir est:

function hasClass(el,cl){
   return !!el.className && !!el.className.match(new RegExp('\\b('+cl+')\\b'));
}
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.