Проверить, содержит ли элемент класс?

используя простой JavaScript (не jQuery), есть ли способ проверить, есть ли элемент содержит класс?

в настоящее время я делаю это:

HTML-код:

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

JS:

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

это приводит к этому выходу, который является правильным:

I have class1

проблема в том, что если я изменю HTML на это...

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

...там больше нет точного соответствия, поэтому я получаю вывод по умолчанию ничего (""). Но я все равно хочу, чтобы выход был I have class1, потому что <div> еще содержит на .class1 класса.

22 ответов


использовать element.classList .contains способ:

element.classList.contains(class);

это работает на всех текущих браузерах, и есть polyfills для поддержки старых браузеров тоже.


как вариант, если вы работаете со старыми браузерами и не хотите использовать polyfills для их исправления, используя indexOf правильно, но вы должны настроить его немного:

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

в противном случае вы также получите true если класс, который вы ищете является частью другого названия класса.

демо

jQuery использует аналогичный (если не тот же) метод.


применяется к примеру:

поскольку это не работает вместе с оператором switch, вы можете достичь того же эффекта с этим кодом:

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

это также менее лишними ;)


простое и эффективное решение пытается .содержит метод.

test.classList.contains(testClass);

в современных браузерах, вы можете просто использовать contains метод Element.classList :

testElement.classList.contains(className)

демо

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>

поддерживаемые браузеры

enter image description here

(от CanIUse.com)


Polyfill

если вы хотите использовать Element.classList но вы также хотите поддерживать старые браузеры, рассмотрите возможность использования это polyfill by Эли-Серый.


поскольку он хочет использовать switch (), я удивлен, что никто еще не выдвинул это:

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

упрощенный oneliner:1

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

1indexOf для массивов не поддерживается IE (конечно). Есть много патчи можно найти в сети для этого.


Это немного старо, но, возможно, кто-то найдет мое решение полезным:

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

вот небольшой фрагмент, Если вы пытаетесь проверить, содержит ли элемент wether класс, без использования jQuery.

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

этим объясняется тот факт, что элемент может содержать несколько имен классов, разделенных пробелами.

или


вы также можете назначить эту функцию на прототип элемента.

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

и вызвать его так (очень аналогично в jQuery ):

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

className - Это просто строка, поэтому вы можете использовать обычный indexOf функция, чтобы увидеть, содержит ли список классов другую строку.


вот тривиальное решение без учета регистра:

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

Я знаю там много ответов, но большинство из них предназначены для дополнительных функций и дополнительных занятий. Это тот, который я лично использую; намного чище и намного меньше строк кода!

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

Я создал метод прототипа, который использует classList, Если возможно, еще прибегает к 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>

тестовая страница


  1. трюк Феликса добавления пробелов для фланга className и строки, которую вы ищете, является правильным подходом к определению того, имеют ли элементы класс или нет.

  2. чтобы иметь различное поведение в соответствии с классом, вы можете использовать ссылки на функции или функции в карте:

    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 в fns) перебирает ключи внутри карты fns.
    • не иметь никакой перерыв после фнси позволяет код должен выполняться всякий раз, когда есть совпадение - так что если элемент имеет, f.Я., class1 и class2, оба fn1 и fn2 будут выполнены.
    • преимущество этого подхода заключается в том, что код для выполнения для каждого класса является произвольным, как и в инструкции switch; в вашем примере все случаи выполняли аналогичную операцию, но завтра вам может потребоваться сделать разные вещи для каждого.
    • вы можете имитировать случай по умолчанию, имея переменную состояния, сообщающую, является ли совпадение было найдено в петле или нет.

Я думаю, что идеальным решением будет это

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

Я бы Поли заполнить функциональность classList и использовать новый синтаксис. Таким образом, новый браузер будет использовать новую реализацию (что намного быстрее), и только старые браузеры будут получать хит производительности из кода.

https://github.com/remy/polyfills/blob/master/classList.js


если элемент имеет только одно имя класса, вы можете быстро проверить его, получив атрибут class. Другие ответы гораздо более надежны, но это, безусловно, имеет свои варианты использования.

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

}

попробуй это:

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

в каком элементе в настоящее время находится класс'.бар ? Вот еще одно решение, но это зависит от вас.

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

jsfiddle demo

конечно, это только поиск для 1 простого элемента <img>(/Image/g), но вы можете поместить все в массив, как <li> is /LI/g, <ul> = /UL/g etc.


Это немного выключено, но если у вас есть событие, которое запускает переключатель, вы можете обойтись без классов:

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

можно сделать

$('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, '') удаляет цифры из id.

Это немного hacky, но работает долго переключается без дополнительных функций или циклов


см. эту ссылку Codepen для более быстрого и простого способа проверки элемента, если он имеет определенный класс с помощью vanilla JavaScript~!

hasClass (Vanilla JS)

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

это поддерживается на IE8+.

Сначала мы проверяем, если если это так, мы можем использовать contains метод, который поддерживается IE10+. Если мы на IE9 или 8 он использует регулярное выражение, которое является не как эффективным, но является кратким полифилл.

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

просто добавить к ответу для людей, пытающихся найти имена классов внутри встроенных элементов SVG.

изменить


для меня самый элегантный и быстрый способ достижения это:

function hasClass(el,cl){
   return !!el.className && !!el.className.match(new RegExp('\b('+cl+')\b'));
}