Periksa apakah suatu elemen mengandung kelas dalam JavaScript?

588

Menggunakan JavaScript biasa (bukan jQuery), Apakah ada cara untuk memeriksa apakah suatu elemen mengandung kelas?

Saat ini, saya melakukan ini:

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>

Masalahnya adalah bahwa jika saya mengubah HTML ke ...

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

... tidak ada lagi yang sama persis, jadi saya mendapatkan output default nothing ( ""). Tapi aku masih ingin output menjadi I have class1karena <div>masih mengandung satu .class1kelas.

daGUY
sumber
5
element.classList.contains (cls)
Ronnie Royston

Jawaban:

1039

Gunakan metode:element.classList .contains

element.classList.contains(class);

Ini berfungsi pada semua browser saat ini dan ada juga polyfill untuk mendukung browser lama.


Atau , jika Anda bekerja dengan browser yang lebih lama dan tidak ingin menggunakan polyfill untuk memperbaikinya, menggunakan indexOfitu benar, tetapi Anda harus sedikit mengubahnya:

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

Kalau tidak, Anda juga akan mendapatkan truejika kelas yang Anda cari adalah bagian dari nama kelas lain.

DEMO

jQuery menggunakan metode yang serupa (jika tidak sama).


Diterapkan pada contoh:

Karena ini tidak bekerja bersama dengan pernyataan switch, Anda dapat mencapai efek yang sama dengan kode ini:

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

Ini juga kurang berlebihan;)

Felix Kling
sumber
Luar biasa, tetapi bagaimana saya menggunakannya dalam kombinasi dengan pernyataan switch sehingga saya bisa mengubah output berdasarkan kelas mana yang berisi div?
DaGUY
@daGUY: Apa yang ingin Anda lakukan dengan pernyataan switch? Mis. Yang kedua divmemiliki dua kelas tetapi hanya akan menghasilkan I have class1seperti yang Anda gunakan break. Jika Anda ingin menampilkan setiap kelas yang dimiliki elemen, maka Anda bisa mengambil classNamedan membaginya di ruang putih. Atau apa tujuan Anda yang sebenarnya?
Felix Kling
@ Felix Kling: Saya perlu innerHTML div untuk mengubah antara empat string yang berbeda tergantung pada kelas yang dikandungnya. Saya hanya menggunakan "I have class1", dll sebagai contoh - string yang sebenarnya semuanya berbeda. Saya hanya akan menunjukkan satu string pada satu waktu, tidak menggabungkan apa pun (karena itu istirahat setelah setiap kasus). Saya hanya ingin itu tetap berfungsi bahkan jika kelas yang cocok adalah salah satu dari beberapa kelas di div.
DaGUY
@Felix Kling: itu berhasil, terima kasih banyak! Saya sebenarnya tidak mengeluarkan nama-nama kelas, tetapi salah satu dari empat string yang sama sekali berbeda, jadi saya memodifikasinya sedikit dengan beberapa pernyataan IF / ELSE IF untuk menangani masing-masing. Bekerja dengan sempurna.
DaGUY
1
Apakah ada alasan khusus mengapa Anda menambahkan spasi sebelum dan sesudah?
Ced
93

Solusi mudah dan efektif adalah mencoba metode .contains .

test.classList.contains(testClass);
pengembang
sumber
3
yang containsmetode dari element.classListproperti
user907860
7
NB! Tidak didukung di semua browser, informasi lebih lanjut di sini: caniuse.com/#feat=classlist
Silver Ringvee
4
Ini adalah jawaban yang bagus dan saya yakin .cains () memiliki dukungan yang lebih luas sekarang.
Nicholas Kreidberg
49

Di browser modern, Anda bisa menggunakan containsmetode Element.classList:

testElement.classList.contains(className)

Demo

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 yang didukung

masukkan deskripsi gambar di sini

(dari CanIUse.com )


Polyfill

Jika Anda ingin menggunakan Element.classListtetapi Anda juga ingin mendukung browser yang lebih lama, pertimbangkan untuk menggunakan polyfill ini oleh Eli Gray .

John Slegers
sumber
10

Karena dia ingin menggunakan sakelar (), saya terkejut belum ada yang mengajukan ini:

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/>";
    }
}
Pikir
sumber
1
Saya hanya ingin tahu hal yang sama, tapi ya, itu yang paling dekat dengan masalah aslinya!
Silver Ringvee
8

Element.matches ()

element.matches (selectorString)

Menurut MDN Web Documents :

The Element.matches()kembali metode truejika elemen akan dipilih oleh pemilih string yang ditentukan; jika tidak, kembali false.

Oleh karena itu, Anda bisa menggunakan Element.matches()untuk menentukan apakah suatu elemen mengandung kelas.

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

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

Lihat Kompatibilitas Browser

Grant Miller
sumber
7

Ini sedikit cuplikan Jika Anda mencoba memeriksa apakah elemen berisi kelas, tanpa menggunakan jQuery.

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

Ini menjelaskan fakta bahwa elemen mungkin berisi beberapa nama kelas yang dipisahkan oleh ruang.

ATAU


Anda juga dapat menetapkan fungsi ini ke prototipe elemen.

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

Dan picu seperti ini (sangat mirip dengan .hasClass()fungsi jQuery ):

document.getElementById('MyDiv').hasClass('active');
Keval Bhatt
sumber
Saya lebih suka solusi ini. Ini menghindari masalah nama kelas yang sebagian cocok dengan kelas lain dan tidak memerlukan polyfill untuk bekerja di IE.
scoota269
5

Penumpang onlin yang disederhanakan: 1

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

1 indexOf untuk array tidak didukung oleh IE (ofcourse). Ada banyak tambalan monyet yang dapat ditemukan di internet untuk itu.

KooiInc
sumber
1
Masalah dengan batas kata adalah bahwa beberapa karakter yang valid untuk nama kelas seperti -dianggap sebagai batas kata. Misalnya mencari foodan kelas adalah foo-barhasil true.
Felix Kling
Kamu benar. Dihapus yang asli, menambahkan pendekatan lain. Masih oneliner.
KooiInc
5

Ini agak lama, tetapi mungkin seseorang akan menemukan solusi saya bermanfaat:

// 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;
    }
}
Demensik
sumber
gunakan: 'element.hasClass (' classname ');
Demensik
Mengapa Anda menggunakan t.length >>> 0? Sejauh yang saya tahu itu adalah noop jika Anda menggunakan '0', kan?
Vitor Canova
wow begitu banyak kode untuk sesuatu yang sederhana. Mengapa tidak menggunakan ekspresi reguler dan tidak menemukan kembali roda? Anda bisa menggunakan /^class_name_you_are_searching_for$/.test(myElement.className)
pqsk
1
Saya menulis itu terlalu cepat. Hanya saja untuk tidak membuat ekspresi berlebihan saya yang terlalu rumit itu adalah / \s*class_name_you_are_searching_for\s*
test(
@ pqsk - saya menulis perpustakaan saya sendiri untuk digunakan di masa depan. dan ini hanya menambah tumpukan saya. tentu saja solusi lain akan berhasil, ini hanya cara yang saya sukai
Dementic
4

classNamehanyalah sebuah string sehingga Anda dapat menggunakan fungsi indexOf biasa untuk melihat apakah daftar kelas berisi string lain.

David
sumber
1
Bagaimana dengan pengujian untuk kelas classpada contoh di atas?
Felix Kling
6
Dari pengalaman, metode ini bisa sangat berisiko: Ini akan kembali benar ketika Anda mencari kelas foopada elemen yang memiliki foobarkelas.
Zirak
2
Tentu, Anda hanya perlu mengetahui apa yang Anda uji. Kode Felix berfungsi dengan baik dengan menggunakan spasi sebagai pembatas.
David
Gagal memperhitungkan instance nama kelas yang disarangkan. Contoh: 'akhir' dapat ditemukan di nama kelas 'frontend'.
Anthony Rutledge
4

Saya tahu ada banyak jawaban tetapi sebagian besar untuk fungsi tambahan dan kelas tambahan. Ini yang saya gunakan secara pribadi; lebih bersih dan lebih sedikit baris kode!

if( document.body.className.match('category-page') ) { 
  console.log('yes');
}
TheBlackBenzKid
sumber
1
metode ini dapat mengembalikan positif palsu ketika mencari nama kelas yang sebagian cocok - mis <body class="category-page">dan document.body.className.match('page')- akan cocok tetapi tidak ada kelas yang pagemelekat pada elemen
hooblei
Dapat diatasi dengan \b, misalnya /\bpage\b/g, karena regex (catatan: harus digunakan / /g).
Andrew
2

Inilah solusi sepele yang case-insensitive:

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
sumber
2

Jika elemen hanya memiliki satu nama kelas, Anda dapat dengan cepat memeriksanya dengan mendapatkan atribut kelas. Jawaban lainnya jauh lebih kuat tetapi ini jelas memiliki kasus penggunaannya.

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

}
Brandon Brule
sumber
2

Saya telah membuat metode prototipe yang menggunakan classList, jika mungkin, resor lain untuk 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>

Halaman uji

vsync
sumber
Apakah ada alasan mengapa Anda ingin menggunakan classlist alih-alih indeks e.className? Sepertinya perf kurang bagus
Ced
@Ced - yah, perf tidak relevan jika Anda tidak menguji ribuan elemen untuk kelas mereka, (itu mungkin akan di-refactored di browser di masa depan). itu lebih elegan untuk digunakan karena kode tersebut menjelaskan fungsionalitasnya, tetapi intinya, itu tidak masalah, lakukan apa pun yang Anda inginkan :)
vsync
1
  1. Trik Felix untuk menambahkan spasi untuk mengapit className dan string yang Anda cari adalah pendekatan yang tepat untuk menentukan apakah elemen memiliki kelas atau tidak.

  2. Untuk memiliki perilaku yang berbeda sesuai dengan kelas, Anda dapat menggunakan referensi fungsi, atau fungsi, dalam peta:

    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);
        }
    }
    • untuk (var i di fns) beralih melalui kunci dalam peta fns.
    • Tanpa break setelah fnsi memungkinkan kode untuk dieksekusi setiap kali ada kecocokan - sehingga jika elemen memiliki, fi, class1 dan class2, baik fn1 dan fn2 akan dieksekusi.
    • Keuntungan dari pendekatan ini adalah bahwa kode untuk mengeksekusi untuk setiap kelas adalah arbitrer, seperti yang ada di pernyataan switch; dalam contoh Anda semua kasus melakukan operasi yang sama, tetapi besok Anda mungkin perlu melakukan hal yang berbeda untuk masing-masing.
    • Anda dapat mensimulasikan kasus default dengan memiliki variabel status yang memberitahukan apakah kecocokan ditemukan dalam loop atau tidak.
entonio
sumber
1

Saya akan Poly mengisi fungsionalitas classList dan menggunakan sintaks baru. Dengan cara ini, browser yang lebih baru akan menggunakan implementasi baru (yang jauh lebih cepat) dan hanya browser lama yang akan membuat kinerja terpukul dari kode.

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

Eric Young
sumber
1

Ini agak salah, tetapi jika Anda memiliki acara yang memicu sakelar, Anda dapat melakukannya tanpa kelas:

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

Anda dapat melakukan

$('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, '')menghapus digit dari id.

Agak rumit, tetapi bekerja untuk sakelar panjang tanpa fungsi atau loop tambahan

Arthur Tarasov
sumber
1

Lihat tautan Codepen ini untuk cara memeriksa elemen yang lebih cepat dan mudah jika memiliki kelas tertentu menggunakan JavaScript vanilla ~!

hasClass (Vanilla JS)

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

Ini didukung pada IE8 +.

Pertama kita periksa apakah classListada jika kita dapat menggunakan containsmetode yang didukung oleh IE10 +. Jika kita menggunakan IE9 atau 8, ia kembali menggunakan regex, yang tidak seefisien tetapi merupakan polyfill ringkas.

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

Atau jika Anda sedang mengompilasi dengan babel Anda cukup menggunakan: el.classList.contains(className);

Tapi s
sumber
0

Coba yang ini:

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
sumber
1
Hati-hati dengan kata batas. Ini juga akan cocok dengan benar jika Anda memiliki misalnya kelas foo-bardan mencari foo.
Felix Kling
1
Hai Jimy, jadi saya mencari metacharacter ini dan hanya menganggap [ a-zA-Z0-9_] sebagai karakter kata. Jadi untuk classnames mengandung char dikurangi ini tidak akan bekerja .
Stano
0

Saya pikir solusi sempurna adalah ini

if ($(this).hasClass("your_Class")) 
    alert("positive");            
else              
    alert("Negative");
Abhishek
sumber
8
1. "Menggunakan JavaScript biasa (bukan jQuery)" 2. Gunakan tanda kurung
nkmol
3 - gunakan Parenthesis
TheBlackBenzKid
0

di elemen mana saat ini kelas '.bar'? Berikut ini solusi lain tetapi terserah Anda.

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

Tentu saja ini hanya pencarian untuk 1 elemen sederhana <img>( /Image/g) tetapi Anda dapat meletakkan semua dalam array seperti <li>ini /LI/g, <ul>= /UL/gdll.

Sangat berbahaya
sumber
0

Hanya untuk menambah jawaban bagi orang yang mencoba menemukan nama kelas dalam elemen SVG sebaris.

Ubah hasCLass()fungsi menjadi:

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

Alih-alih menggunakan classNameproperti Anda harus menggunakan getAttribute()metode untuk mengambil nama kelas.

Ben Rudolph
sumber
0

Saya membuat fungsi-fungsi ini untuk situs web saya, saya hanya menggunakan javascript vanilla, mungkin itu akan membantu seseorang. Pertama saya membuat fungsi untuk mendapatkan elemen HTML apa pun:

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

Kemudian fungsi yang menerima kelas untuk dihapus dan pemilih elemen:

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

Sekarang Anda dapat menggunakannya seperti ini:

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

Semoga ini bisa membantu.

Josh
sumber
0

Tip: Cobalah untuk menghapus dependensi jQuery di proyek Anda sebanyak yang Anda bisa - VanillaJS .

document.firstElementChildmengembalikan <html>tag lalu classListatribut mengembalikan semua kelas yang ditambahkan padanya.

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

Bagi saya cara yang paling elegan dan lebih cepat untuk mencapainya adalah:

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