Verifica se un elemento contiene una classe in JavaScript?


588

Utilizzando JavaScript (non jQuery), c'è un modo per verificare se un elemento contiene una classe?

Attualmente sto facendo questo:

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>

Il problema è che se cambio HTML in questo ...

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

... non c'è più una corrispondenza esatta, quindi ottengo l'output predefinito di nothing ( ""). Ma voglio ancora che l'output sia I have class1perché contiene<div> ancora la classe..class1


5
element.classList.contains (cls)
Ronnie Royston

Risposte:


1039

Utilizzare il metodo:element.classList .contains

element.classList.contains(class);

Funziona su tutti i browser attuali e ci sono polyfill per supportare anche i browser più vecchi.


In alternativa , se lavori con browser più vecchi e non vuoi usare i polyfill per risolverli, usare indexOfè corretto, ma devi modificarlo un po ':

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

Altrimenti otterrai anche truese la classe che stai cercando fa parte di un altro nome di classe.

DEMO

jQuery utilizza un metodo simile (se non uguale).


Applicato all'esempio:

Poiché ciò non funziona insieme all'istruzione switch, è possibile ottenere lo stesso effetto con questo codice:

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

È anche meno ridondante;)


Fantastico, ma come posso usarlo in combinazione con l'istruzione switch in modo da poter cambiare l'output in base a quali classi contiene il div?
daGUY

@daGUY: Cosa vuoi fare comunque con l'istruzione switch? Ad esempio, la seconda divha due classi, ma verrà emessa solo I have class1mentre si sta utilizzando break. Se vuoi produrre ogni classe di un elemento, puoi semplicemente prendere classNamee dividerlo su spazi bianchi. O qual è il tuo obiettivo reale?
Felix Kling

@Felix Kling: ho bisogno che il HTML interno del div cambi tra quattro diverse stringhe a seconda della classe che contiene. Ho appena usato "I class1", ecc. Come esempi - le stringhe reali sono tutte diverse. Mostrerò solo una stringa alla volta, non combinandone nessuna (quindi le interruzioni dopo ogni caso). Voglio solo che continui a funzionare anche se la classe corrispondente è una delle classi multiple sul div.
daGUY

@Felix Kling: l'ha fatto, grazie mille! In realtà non sto producendo i nomi delle classi, ma piuttosto una delle quattro stringhe completamente diverse, quindi l'ho modificata leggermente con alcune istruzioni IF / ELSE IF per gestirle. Funziona perfettamente però.
daGUY

1
C'è un motivo specifico per cui hai aggiunto spazi prima e dopo?
Ced


49

Nei browser moderni, puoi semplicemente usare il containsmetodo di Element.classList:

testElement.classList.contains(className)

dimostrazione

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>


Browser supportati

inserisci qui la descrizione dell'immagine

(da CanIUse.com )


polyfill

Se si desidera utilizzare Element.classListma si desidera supportare anche i browser meno recenti, è consigliabile utilizzare questo polyfill di Eli Gray .


10

Dato che vuole usare switch (), sono sorpreso che nessuno lo abbia ancora presentato:

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
Mi stavo solo chiedendo la stessa cosa, ma sì, questo è il più vicino al problema originale!
Silver Ringvee,

8

Element.matches ()

element.matches (selectorString)

Secondo MDN Web Docs :

Il Element.matches()metodo restituisce truese l'elemento sarebbe selezionato dalla stringa di selezione specificata; altrimenti, ritorna false.

Pertanto, è possibile utilizzare Element.matches()per determinare se un elemento contiene una classe.

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

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

Visualizza la compatibilità del browser


7

Ecco un piccolo frammento Se stai provando a controllare se l'elemento contiene una classe, senza usare jQuery.

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

Ciò spiega il fatto che l'elemento potrebbe contenere più nomi di classi separati da spazio.

O


È inoltre possibile assegnare questa funzione al prototipo dell'elemento.

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

E attivalo in questo modo (molto simile alla .hasClass()funzione di jQuery ):

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

Preferisco di più questa soluzione. Evita il problema del nome della classe che corrisponde parzialmente ad un'altra classe e non richiede che i polyfill funzionino in IE.
scoota269,

5

Un oneliner semplificato: 1

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

1 indexOf per gli array non è supportato da IE (ofcourse). Ci sono molte patch di scimmie che si trovano in rete per questo.


1
Il problema con i confini delle parole è che alcuni caratteri validi per i nomi delle classi come -sono considerati limiti delle parole. Ad esempio, la ricerca fooe la classe sono i foo-barrendimenti true.
Felix Kling

Hai ragione. Rimosso l'originale, aggiunto un altro approccio. Ancora un oneliner.
KooiInc,

5

Questo è un po 'vecchio, ma forse qualcuno troverà la mia soluzione 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,

Perché hai usato t.length >>> 0? Per quanto ne so è un noop se si utilizza '0', giusto?
Vitor Canova,

wow così tanto codice per qualcosa di semplice. Perché non usare un'espressione regolare e non reinventare la ruota? potresti semplicemente usare /^class_name_you_are_searching_for$/.test(myElement.className)
pqsk

1
L'ho scritto troppo in fretta. Solo per non complicare la mia espressione regolare sarebbe /\s*class_name_you_are_searching_for\s*/.test(myElement.className)
pqsk

@pqsk - scrivo le mie librerie per uso futuro. e questo si aggiunge al mio stack. ovviamente altre soluzioni funzionerebbero, questo è solo il mio modo preferito
Dementic

4

classNameè solo una stringa in modo da poter utilizzare la normale funzione indexOf per vedere se l'elenco delle classi contiene un'altra stringa.


1
Che dire del test per la classe classnell'esempio sopra?
Felix Kling

6
Per esperienza, questo metodo può essere piuttosto rischioso: tornerà vero quando cerchi la classe foosu un elemento che ha la foobarclasse.
Zirak,

2
Certo, devi solo essere consapevole di ciò che stai testando. Il codice di Felix funziona bene usando gli spazi come delimitatore.
David,

Non riesce a tenere conto delle istanze nidificate di un nome di classe. Esempio: 'end' può essere trovato nel nome della classe 'frontend'.
Anthony Rutledge,

4

Conosco molte risposte, ma la maggior parte di queste sono per funzioni aggiuntive e classi aggiuntive. Questo è quello che uso personalmente; linee di codice molto più pulite e molto meno!

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

1
questo metodo può restituire falsi positivi quando si cerca un nome di classe che corrisponda parzialmente - ad es. <body class="category-page">e document.body.className.match('page')- corrisponderà ma non vi è alcuna classe pageassociata all'elemento
hooblei

Può essere risolto \b, ad esempio /\bpage\b/g, poiché è regex (nota: è necessario utilizzare / /g).
Andrew

2

Ecco una soluzione banale senza distinzione tra maiuscole e minuscole:

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

Se l'elemento ha un solo nome di classe, puoi verificarlo rapidamente ottenendo l'attributo class. Le altre risposte sono molto più robuste ma questo ha certamente i suoi casi d'uso.

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

}

2

Ho creato un metodo prototipo che utilizza classList, se possibile, altrimenti ricorre a 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>

Pagina di prova


C'è un motivo per cui si desidera utilizzare classlist invece dell'indice di e.className? Sembra che i perf siano meno buoni
Ced

@Ced - beh, perf è irrilevante se non stai testando migliaia di elementi per la loro classe (probabilmente verrà refactorizzato nei browser in futuro). è più elegante da usare perché il codice descrive la sua funzionalità, ma la linea di fondo, non importa, fai quello che vuoi :)
vsync

1
  1. Il trucco di Felix di aggiungere spazi per affiancare className e la stringa che stai cercando è l'approccio giusto per determinare se gli elementi hanno la classe o meno.

  2. Per avere un comportamento diverso in base alla classe, è possibile utilizzare riferimenti di funzione o funzioni all'interno di una mappa:

    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);
        }
    }
    • per (var i in fns) scorre attraverso i tasti all'interno della mappa fns.
    • Non avere alcuna interruzione dopo fnsi consente l'esecuzione del codice ogni volta che esiste una corrispondenza, in modo che se l'elemento ha, fi, class1 e class2, verranno eseguiti sia fn1 che fn2.
    • Il vantaggio di questo approccio è che il codice da eseguire per ogni classe è arbitrario, come quello nell'istruzione switch; nel tuo esempio tutti i casi hanno eseguito un'operazione simile, ma domani potresti dover fare cose diverse per ognuno.
    • È possibile simulare il caso predefinito avendo una variabile di stato che indica se è stata trovata una corrispondenza nel loop o meno.


1

Questo è un po 'spento, ma se hai un evento che attiva il passaggio, puoi fare a meno delle classi:

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

Tu puoi fare

$('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, '')rimuove le cifre da id.

È un po 'confuso, ma funziona per switch lunghi senza funzioni extra o loop


1

Vedi questo collegamento Codepen per un modo più semplice e veloce di controllare un elemento se ha una classe specifica usando JavaScript ~ vaniglia!

hasClass (Vanilla JS)

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

1

Questo è supportato su IE8 +.

Innanzitutto controlliamo se classListesiste se è possibile utilizzare il containsmetodo supportato da IE10 +. Se siamo su IE9 o 8, si ricorre all'utilizzo di un regex, che non è così efficiente ma è un conciso polifill.

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

In alternativa, se stai compilando con babel puoi semplicemente usare: el.classList.contains(className);


0

Prova questo:

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
Stai attento con la parola limite. Corrisponderà anche a true se hai ad esempio una classe foo-bare cerchi foo.
Felix Kling

1
Ciao Jimy, quindi stavo cercando questo \ b metacarattere e considera solo [ a-zA-Z0-9_] come caratteri di parole. Quindi per un nome di classe contenente un carattere meno questo non funzionerà .
Stano,

0

Penso che la soluzione perfetta sarà questa

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

8
1. "Uso di JavaScript semplice (non jQuery)" 2. Usa parentesi
nkmol

3 - use Parenthesis
TheBlackBenzKid

0

in quale elemento è attualmente la classe '.bar'? Ecco un'altra soluzione, ma dipende da te.

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

demo di jsfiddle

Naturalmente questa è solo una ricerca per 1 elemento semplice <img>( /Image/g) ma puoi mettere tutto in un array come <li>is /LI/g, <ul>= /UL/getc.


0

Solo per aggiungere alla risposta le persone che cercano di trovare i nomi delle classi all'interno di elementi SVG in linea.

Cambia la hasCLass()funzione in:

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

Invece di usare la classNameproprietà dovrai usare il getAttribute()metodo per prendere il nome della classe.


0

Ho creato queste funzioni per il mio sito Web, utilizzo solo javascript alla vaniglia, forse aiuterà qualcuno. Innanzitutto ho creato una funzione per ottenere qualsiasi elemento 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;
    }

Quindi la funzione che riceve la classe da rimuovere e il selettore dell'elemento:

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

Ora puoi usarlo in questo modo:

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

Spero che possa essere d'aiuto.


0

Suggerimento: prova a rimuovere il più possibile le dipendenze di jQuery dai tuoi progetti: VanillaJS .

document.firstElementChildrestituisce il <html>tag quindi l' classListattributo restituisce tutte le classi aggiunte ad esso.

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

-1

Per me il modo più elegante e veloce per raggiungerlo è:

function hasClass(el,cl){
   return !!el.className && !!el.className.match(new RegExp('\\b('+cl+')\\b'));
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.