Sprawdź, czy element zawiera klasę w JavaScript?

585

Używając zwykłego JavaScript (nie jQuery), czy jest jakiś sposób, aby sprawdzić, czy element zawiera klasę?

Obecnie robię to:

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>

Problem polega na tym, że jeśli zmienię HTML na ten ...

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

... nie ma już dokładnego dopasowania, więc domyślnie wyprowadzam nic ( ""). Ale nadal chcę być wyjście I have class1, ponieważ <div>nadal zawiera w .class1klasie.

DaGUY
źródło
5
element.classList.contains (cls)
Ronnie Royston

Odpowiedzi:

1034

Użyj metody:element.classList .contains

element.classList.contains(class);

Działa to we wszystkich aktualnych przeglądarkach, a istnieją też wielouzupełniacze obsługujące starsze przeglądarki.


Alternatywnie , jeśli pracujesz ze starszymi przeglądarkami i nie chcesz używać wielopełniaczy do ich naprawy, użycie indexOfjest poprawne, ale musisz go nieco poprawić:

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

W przeciwnym razie otrzymasz także, truejeśli klasa, której szukasz, jest częścią innej nazwy klasy.

PRÓBNY

jQuery używa podobnej (jeśli nie tej samej) metody.


Zastosowano do przykładu:

Ponieważ nie działa to razem z instrukcją switch, można osiągnąć ten sam efekt za pomocą tego kodu:

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

Jest również mniej zbędny;)

Felix Kling
źródło
Wspaniale, ale jak korzystać z tego w połączeniu z instrukcją switch, aby zmienić dane wyjściowe na podstawie klas, które zawiera div?
daGUY
@daGUY: Co i tak chcesz zrobić z instrukcją switch? Np. Druga divma dwie klasy, ale generowałaby dane tylko I have class1podczas używania break. Jeśli chcesz wypisać każdą klasę, którą posiada element, możesz po prostu wziąć classNamei podzielić go na białe spacje. A jaki jest twój rzeczywisty cel?
Felix Kling
@ Felix Kling: Potrzebuję innerHTML div, aby zmieniać między czterema różnymi łańcuchami w zależności od tego, która klasa zawiera. Po prostu użyłem „Mam klasę 1” itp. Jako przykładów - prawdziwe ciągi znaków są różne. Będę pokazywał tylko jeden ciąg naraz, nie łącząc żadnego (stąd przerwy po każdym przypadku). Chcę tylko, żeby nadal działał, nawet jeśli pasująca klasa jest jedną z wielu klas w div.
daGUY
@Felix Kling: to zrobiło, wielkie dzięki! Właściwie to nie wypisuję nazw klas, ale jeden z czterech zupełnie różnych ciągów, więc zmodyfikowałem go nieco za pomocą kilku instrukcji IF / ELSE IF, aby obsłużyć każdą z nich. Działa idealnie.
daGUY
1
Czy istnieje konkretny powód dodania spacji przed i po?
Ced
93

Łatwym i skutecznym rozwiązaniem jest wypróbowanie metody .contains .

test.classList.contains(testClass);
deweloper
źródło
3
containssposób na element.classListwłasności
user907860
7
NB! Nieobsługiwany we wszystkich przeglądarkach, więcej informacji tutaj: caniuse.com/#feat=classlist
Silver Ringvee
4
To świetna odpowiedź i uważam, że .contains () ma teraz znacznie szersze wsparcie.
Nicholas Kreidberg
49

W nowoczesnych przeglądarkach możesz po prostu użyć containsmetody Element.classList:

testElement.classList.contains(className)

Próbny

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>


Obsługiwane przeglądarki

wprowadź opis zdjęcia tutaj

(z CanIUse.com )


Polyfill

Jeśli chcesz używać, Element.classListale chcesz także obsługiwać starsze przeglądarki, rozważ użycie tej funkcji wypełniania przez Eli Gray .

John Slegers
źródło
10

Ponieważ chce używać switch (), jestem zaskoczony, że nikt jeszcze tego nie ujawnił:

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/>";
    }
}
Myśl
źródło
1
Zastanawiałem się tylko nad tym samym, ale tak, to jest najbliższy pierwotny problem!
Srebrny Ringvee
8

Element.matches ()

element.matches (selectorString)

Według MDN Web Docs :

Te Element.matches()metody powróci true, gdy element będzie wybrany przez określony ciąg wyboru; w przeciwnym razie zwraca false.

Dlatego możesz użyć Element.matches()do ustalenia, czy element zawiera klasę.

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

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

Zobacz kompatybilność przeglądarki

Grant Miller
źródło
7

Oto mały fragment Jeśli próbujesz sprawdzić, czy element zawiera klasę, bez użycia jQuery.

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

Wynika to z faktu, że element może zawierać wiele nazw klas oddzielonych spacją.

LUB


Możesz także przypisać tę funkcję do prototypu elementu.

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

I uruchom go w następujący sposób (bardzo podobny do .hasClass()funkcji jQuery ):

document.getElementById('MyDiv').hasClass('active');
Keval Bhatt
źródło
Wolę to rozwiązanie bardziej. Pozwala to uniknąć problemu z nazwą klasy częściowo pasującą do innej klasy i nie wymaga wypełniania wielopełniaczem w IE.
scoota269
5

Uproszczony oneliner: 1

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

1 indexOf dla tablic nie jest obsługiwany przez IE (oczywiście). W tym celu można znaleźć wiele łat małp.

KooiInc
źródło
1
Problem z granicami słów polega na tym, że niektóre poprawne znaki dla nazw klas, takie jak, -są uważane za granice słów. Np. Szukanie, fooa klasa to foo-barplony true.
Felix Kling
Masz rację. Usunięto oryginał, dodano inne podejście. Wciąż oneliner.
KooiInc
5

To jest trochę stare, ale może ktoś uzna moje rozwiązanie za pomocne:

// 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;
    }
}
Demencja
źródło
use: 'element.hasClass (' classname ');
Demencja
Dlaczego użyłeś t.length >>> 0? O ile wiem, to noop, jeśli użyjesz „0”, prawda?
Vitor Canova,
wow tyle kodu na coś prostego. Dlaczego nie użyć wyrażenia regularnego i nie wymyślić koła na nowo? możesz po prostu użyć /^class_name_you_are_searching_for$/.test(myElement.className)
pqsk
1
Napisałem to zbyt szybko. Aby nie komplikować mojego wyrażenia regularnego, byłoby to /\s*class_name_you_are_are_searching_for\s*/.test(myElement.className)
pqsk
@pqsk - Piszę własne biblioteki do wykorzystania w przyszłości. a to tylko dodaje do mojego stosu. oczywiście zadziałałyby inne rozwiązania, to po prostu mój preferowany sposób
demencja
4

classNamejest tylko łańcuchem, więc możesz użyć zwykłej funkcji indexOf, aby sprawdzić, czy lista klas zawiera inny ciąg.

David
źródło
1
Co z testowaniem na zajęcia classw powyższym przykładzie?
Felix Kling
6
Z doświadczenia foowynika, że ta metoda może być dość ryzykowna: zwróci prawdę, gdy będziesz szukać klasy na elemencie, który ma foobarklasę.
Zirak
2
Jasne, musisz mieć świadomość tego, co testujesz. Kod Felixa działa dobrze, używając spacji jako separatora.
David
Nie można uwzględnić zagnieżdżonych instancji nazwy klasy. Przykład: „end” można znaleźć w nazwie klasy „frontend”.
Anthony Rutledge
4

Znam wiele odpowiedzi, ale większość z nich dotyczy dodatkowych funkcji i dodatkowych klas. Tego osobiście używam; znacznie czystsze i znacznie mniej linii kodu!

if( document.body.className.match('category-page') ) { 
  console.log('yes');
}
TheBlackBenzKid
źródło
1
ta metoda może zwracać fałszywe alarmy podczas wyszukiwania nazwy klasy, która częściowo pasuje - np. <body class="category-page">i document.body.className.match('page')- będzie pasować, ale pagedo elementu nie jest przypisana żadna klasa
hooblei
Można rozwiązać \bnp. /\bpage\b/g, Ponieważ jest wyrażeniem regularnym (uwaga: trzeba użyć / /g).
Andrew
2

Oto banalne rozwiązanie bez rozróżniania wielkości liter:

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;
}
Anders Fjeldstad
źródło
2

Jeśli element ma tylko jedną nazwę klasy, możesz ją szybko sprawdzić, uzyskując atrybut class. Pozostałe odpowiedzi są znacznie bardziej niezawodne, ale z pewnością ma to zastosowanie.

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

}
Brandon Brule
źródło
2

Stworzyłem prototypową metodę, która w classListmiarę możliwości wykorzystuje inne metody 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>

Strona testowa

vsync
źródło
Czy istnieje powód, dla którego chcesz używać listy klas zamiast indeksu nazwy e.className? Wygląda na to, że perf są mniej dobre
Ced
@Ced - cóż, perf nie ma znaczenia, jeśli nie testujesz tysięcy elementów dla ich klasy (prawdopodobnie zostanie to zrefaktoryzowane w przeglądarkach w przyszłości). jest bardziej elegancki w użyciu, ponieważ kod opisuje jego funkcjonalność, ale w
gruncie
1
  1. Sztuczka Felixa polegająca na dodawaniu spacji do flankowania nazwy klasy i szukanego ciągu jest właściwym podejściem do ustalenia, czy elementy mają klasę, czy nie.

  2. Aby zachować różne zachowanie w zależności od klasy, możesz użyć odwołań do funkcji lub funkcji w obrębie mapy:

    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) iteruje przez klucze w mapie fns.
    • Brak przerwy po fnsi pozwala na wykonanie kodu za każdym razem, gdy występuje dopasowanie - tak, że jeśli element ma, fi, klasa 1 i klasa 2, zarówno fn1, jak i fn2 zostaną wykonane.
    • Zaletą tego podejścia jest to, że kod do wykonania dla każdej klasy jest dowolny, podobnie jak w instrukcji switch; w twoim przykładzie wszystkie przypadki wykonały podobną operację, ale jutro może być konieczne zrobienie różnych rzeczy dla każdej z nich.
    • Możesz symulować domyślny przypadek, mając zmienną statusu informującą, czy znaleziono dopasowanie w pętli, czy nie.
entonio
źródło
1

Jest to trochę wyłączone, ale jeśli masz zdarzenie, które wyzwala zmianę, możesz obejść się bez klas:

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

Możesz to zrobić

$('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, '')usuwa cyfry z id.

Jest to nieco zhackowane, ale działa w przypadku długich przełączników bez dodatkowych funkcji lub pętli

Artur Tarasow
źródło
1

Zobacz ten link Codepen, aby szybko i łatwo sprawdzić element, jeśli ma on określoną klasę za pomocą waniliowego JavaScript ~!

hasClass (Vanilla JS)

function hasClass(element, cls) {
    return (' ' + element.className + ' ').indexOf(' ' + cls + ' ') > -1;
}
Jefsama
źródło
1

Jest to obsługiwane w IE8 +.

Najpierw sprawdzamy, czy classLististnieje, jeśli tak, możemy użyć containsmetody obsługiwanej przez IE10 +. Jeśli korzystamy z IE9 lub 8, wraca do używania wyrażenia regularnego, które nie jest tak wydajne, ale jest zwięzłym wypełnieniem.

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

Alternatywnie, jeśli kompilujesz z Babel, możesz po prostu użyć: el.classList.contains(className);

Ale
źródło
0

Spróbuj tego:

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;
};
jimy
źródło
1
Uważaj na granicę słowa. Będzie pasować również do prawdy, jeśli masz np. Klasę foo-bari szukasz foo.
Felix Kling
1
Cześć Jimy, więc szukałem tego \ b metaznaka i traktuje on tylko [ a-zA-Z0-9_] jako znaki słowne. Więc dla nazw klas zawierających znak minus to nie zadziała .
Stano,
0

Myślę, że będzie to idealne rozwiązanie

if ($(this).hasClass("your_Class")) 
    alert("positive");            
else              
    alert("Negative");
Abhishek
źródło
8
1. „Korzystanie ze zwykłego JavaScript (nie jQuery)” 2. Użyj nawiasów
nkmol
3 - użyj nawiasu
TheBlackBenzKid
0

w którym elemencie jest obecnie klasa „.bar”? Oto inne rozwiązanie, ale to zależy od Ciebie.

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 jsfiddle

Oczywiście jest to tylko odnośnika do prostego elementu 1 <img>( /Image/g), ale można umieścić wszystko w tablicy jak <li>jest /LI/g, <ul>= /UL/gitd.

Thielicious
źródło
0

Aby dodać do odpowiedzi dla osób próbujących znaleźć nazwy klas w ramach wbudowanych elementów SVG.

Zmień hasCLass()funkcję na:

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

Zamiast korzystać z classNamewłaściwości, musisz użyć getAttribute()metody, aby pobrać nazwę klasy.

Ben Rudolph
źródło
0

Stworzyłem te funkcje na mojej stronie, używam tylko javascript waniliowy, może to komuś pomoże. Najpierw stworzyłem funkcję, aby uzyskać dowolny element 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;
    }

Następnie funkcja odbierająca klasę do usunięcia i selektor elementu:

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

Teraz możesz użyć tego w następujący sposób:

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

Mam nadzieję, że to pomoże.

Josh
źródło
0

Wskazówka: Postaraj się jak najbardziej usunąć zależności jQuery w swoich projektach - VanillaJS .

document.firstElementChildzwraca <html>tag, a następnie classListatrybut zwraca wszystkie dodane do niego klasy.

if(document.firstElementChild.classList.contains("your-class")){
    // <html> has 'your-class'
} else {
    // <html> doesn't have 'your-class'
}
Alireza
źródło
-1

Dla mnie najbardziej eleganckim i szybszym sposobem na osiągnięcie tego jest:

function hasClass(el,cl){
   return !!el.className && !!el.className.match(new RegExp('\\b('+cl+')\\b'));
}
Pinonirwana
źródło