Apakah ada cara untuk menambah / menghapus beberapa kelas dalam satu instruksi tunggal dengan classList?

164

Sejauh ini saya harus melakukan ini:

elem.classList.add("first");
elem.classList.add("second");
elem.classList.add("third");

Meskipun ini bisa dilakukan di jQuery, seperti ini

$(elem).addClass("first second third");

Saya ingin tahu apakah ada cara asli untuk menambah atau menghapus.

Tenda Enrique Moreno
sumber

Jawaban:

315
elem.classList.add("first");
elem.classList.add("second");
elem.classList.add("third");

sama

elem.classList.add("first","second","third");
iwege
sumber
15
Dan jika Anda ingin menerapkan Array dari beberapa nama kelas, Anda harus memanggil: DOMTokenList.prototype.add.apply (elem.classList, ['pertama', 'kedua', 'ketiga']);
Emanuel Kluge
8
Firefox juga tidak mendukungnya, pada saat penulisan. Jawaban saya menyediakan polyfill.
Andy E
Saya beralih ke yang ini sebagai jawaban yang benar, karena ini adalah API asli, meskipun dukungannya tidak bagus.
Tenda Enrique Moreno
1
Sudahkah Anda mempertimbangkan el.className + = "kelas saya di sini"
Michael Tontchev
1
apakah ada cara untuk menghapus beberapa kelas
MeVimalkumar
72

Operator spread baru membuatnya lebih mudah untuk menerapkan beberapa kelas CSS sebagai array:

const list = ['first', 'second', 'third'];
element.classList.add(...list);
morkro
sumber
1
Jawaban yang diterima bekerja dengan daftar nilai langsung, tetapi yang ini bekerja dengan array ... keduanya tampak jawaban yang sangat baik!
Tenda Enrique Moreno
Bisakah saya menggunakan DOMTokenListbukan array? Saya tahu bahwa DOMTokenList adalah objek mirip array. Jadi dimungkinkan untuk menggunakannya dengan classList.add()metode atau haruskah DOMTokenList dikonversi dalam array nyata?
xela84
19

The classListproperti memastikan bahwa duplikat kelas tidak perlu ditambahkan ke elemen. Untuk menjaga fungsi ini, jika Anda tidak menyukai versi lama atau versi jQuery, saya sarankan menambahkan addManyfungsi dan removeManyke DOMTokenList(tipe classList):

DOMTokenList.prototype.addMany = function(classes) {
    var array = classes.split(' ');
    for (var i = 0, length = array.length; i < length; i++) {
      this.add(array[i]);
    }
}

DOMTokenList.prototype.removeMany = function(classes) {
    var array = classes.split(' ');
    for (var i = 0, length = array.length; i < length; i++) {
      this.remove(array[i]);
    }
}

Ini kemudian akan bisa digunakan seperti:

elem.classList.addMany("first second third");
elem.classList.removeMany("first third");

Memperbarui

Sesuai komentar Anda, jika Anda hanya ingin menulis metode khusus untuk ini jika tidak ditentukan, coba yang berikut ini:

DOMTokenList.prototype.addMany = DOMTokenList.prototype.addMany || function(classes) {...}
DOMTokenList.prototype.removeMany = DOMTokenList.prototype.removeMany || function(classes) {...}
Rich O'Kelly
sumber
Masih jawaban yang bagus. Dan saya tidak dapat mengeditnya untuk Anda karena hanya 2 karakter.
Pete
18

Karena add()metode dari classListjust memungkinkan untuk melewati argumen terpisah dan bukan array tunggal, Anda perlu membuat faktur add()menggunakan apply. Untuk argumen pertama, Anda harus meneruskan classListreferensi dari simpul DOM yang sama dan sebagai argumen kedua array kelas yang ingin Anda tambahkan:

element.classList.add.apply(
  element.classList,
  ['class-0', 'class-1', 'class-2']
);
Andrés Carreño
sumber
Ini versi ES5 dari solusi dengan Penyebar Operator (lihat jawaban @mroro ). Periksa dengan mudah di Babel Repl .
Nickensoul
7

Untuk menambahkan kelas ke elemen

document.querySelector(elem).className+=' first second third';

MEMPERBARUI:

Hapus kelas

document.querySelector(elem).className=document.querySelector(elem).className.split(class_to_be_removed).join(" ");

sumber
Ini menarik untuk diketahui, tetapi yang perlu dilakukan hanyalah mengedit string kelas. Tidak akan berhasil jika saya ingin menghapus beberapa kelas. Maaf, saya lupa menambahkannya di OP.
Tenda Enrique Moreno
4
Apakah TIDAK menggunakan className. Sangat buruk untuk kinerja (bahkan mengambil nilainya menyebabkan reflow).
jacob
7

Versi yang lebih baru dari spesifikasi DOMTokenList memungkinkan untuk beberapa argumen untuk add()dan remove(), serta argumen kedua toggle()untuk memaksa negara.

Pada saat penulisan, Chrome mendukung banyak argumen untuk add()dan remove(), tetapi tidak ada browser lain yang mendukung. IE 10 dan lebih rendah, Firefox 23 dan lebih rendah, Chrome 23 dan lebih rendah dan browser lain tidak mendukung argumen kedua toggle().

Saya menulis polyfill kecil berikut untuk menyuruh saya sampai dukungan mengembang:

(function () {
    /*global DOMTokenList */
    var dummy  = document.createElement('div'),
        dtp    = DOMTokenList.prototype,
        toggle = dtp.toggle,
        add    = dtp.add,
        rem    = dtp.remove;

    dummy.classList.add('class1', 'class2');

    // Older versions of the HTMLElement.classList spec didn't allow multiple
    // arguments, easy to test for
    if (!dummy.classList.contains('class2')) {
        dtp.add    = function () {
            Array.prototype.forEach.call(arguments, add.bind(this));
        };
        dtp.remove = function () {
            Array.prototype.forEach.call(arguments, rem.bind(this));
        };
    }

    // Older versions of the spec didn't have a forcedState argument for
    // `toggle` either, test by checking the return value after forcing
    if (!dummy.classList.toggle('class1', true)) {
        dtp.toggle = function (cls, forcedState) {
            if (forcedState === undefined)
                return toggle.call(this, cls);

            (forcedState ? add : rem).call(this, cls);
            return !!forcedState;
        };
    }
})();

Peramban modern dengan kepatuhan ES5 dan DOMTokenListdiharapkan, tetapi saya menggunakan polyfill ini di beberapa lingkungan yang ditargetkan secara spesifik, jadi ini berfungsi dengan baik bagi saya, tetapi mungkin perlu mengutak-atik skrip yang akan berjalan di lingkungan browser lama seperti IE 8 dan lebih rendah .

Andy E
sumber
1
Sepertinya tidak ada yang menyebutkan bahwa IE10 tidak memungkinkan untuk beberapa kelas ditambahkan. Ini bekerja dengan baik untuk saya, terima kasih! Saya akan memperingatkan bahwa di IE9 saya mendapatkan kesalahan bahwa DomTokenList tidak didefinisikan. Anda mungkin ingin memperhitungkannya juga. Atau hanya jalankan ini jika (typeof DomTokenList! == 'undefined')
Ryan Ore
@Ryan: terima kasih, saya pikir DOMTokenList didukung di IE 9 tapi saya kira itu terlewatkan. Saya akan mencoba dan menyelidiki solusi di beberapa titik.
Andy E
Sepertinya pada DOMTokenList yang gagal Anda harus menggunakan className dengan pemeriksaan batas kata regEx
Greg
7

Anda bisa melakukan seperti di bawah ini

Menambahkan

elem.classList.add("first", "second", "third");

Menghapus

elem.classList.remove("first", "second", "third");

Referensi

TLDR;

Dalam kasus lurus ke depan penghapusan harus bekerja. Tetapi dalam hal penghapusan, Anda harus memastikan kelas ada sebelum Anda menghapusnya

const classes = ["first","second","third"];
classes.forEach(c => {
  if (elem.classList.contains(c)) {
     element.classList.remove(c);
  }
})
Pankaj Parkar
sumber
5

Ini adalah solusi untuk pengguna IE 10 dan 11 yang tampaknya cukup mudah.

var elem = document.getElementById('elem');

['first','second','third'].map(item => elem.classList.add(item));
<div id="elem">Hello World!</div>

Atau

var elem = document.getElementById('elem'),
    classes = ['first','second','third'];

classes.map(function(item) {
    return elem.classList.add(item);
});
<div id="elem">Hello World!</div>

colecmc
sumber
5
Ide bagus. Saya akan menggunakan .forEach () alih-alih .map () - lebih bersih / lebih efisien untuk situasi seperti ini di mana Anda tidak menggunakan array yang dikembalikan.
tenni
Ya itu benar.
colecmc
2

Definisi standar hanya memungkinkan untuk menambah atau menghapus satu kelas. Beberapa fungsi pembungkus kecil dapat melakukan apa yang Anda minta:

function addClasses (el, classes) {
  classes = Array.prototype.slice.call (arguments, 1);
  console.log (classes);
  for (var i = classes.length; i--;) {
    classes[i] = classes[i].trim ().split (/\s*,\s*|\s+/);
    for (var j = classes[i].length; j--;)
      el.classList.add (classes[i][j]);
  }
}

function removeClasses (el, classes) {
  classes = Array.prototype.slice.call (arguments, 1);
  for (var i = classes.length; i--;) {
    classes[i] = classes[i].trim ().split (/\s*,\s*|\s+/);
    for (var j = classes[i].length; j--;)
      el.classList.remove (classes[i][j]);
  }
}

Pembungkus ini memungkinkan Anda untuk menentukan daftar kelas sebagai argumen terpisah, sebagai string dengan spasi atau item yang dipisahkan koma, atau kombinasi. Sebagai contoh, lihat http://jsfiddle.net/jstoolsmith/eCqy7

HBP
sumber
2

Solusi yang sangat sederhana, tidak mewah, tetapi berfungsi yang harus saya percayai adalah browser yang sangat lintas:

Buat fungsi ini

function removeAddClasses(classList,removeCollection,addCollection){
    for (var i=0;i<removeCollection.length;i++){ 
        classList.remove(removeCollection[i]); 
    }
    for (var i=0;i<addCollection.length;i++){ 
        classList.add(addCollection[i]); 
    }
}

Sebut saja seperti ini: removeAddClasses (node.classList, arrayToRemove, arrayToAdd);

... dimana arrayToRemove adalah larik nama kelas yang akan dihapus: ['myClass1', 'myClass2'] etcetera

... dan arrayToAdd adalah array nama kelas untuk ditambahkan: ['myClass3', 'myClass4'] dan sebagainya

Soren
sumber
1

Asumsikan bahwa Anda memiliki array kelas yang akan ditambahkan, Anda dapat menggunakan sintaksis penyebaran ES6:

let classes = ['first', 'second', 'third']; elem.classList.add(...classes);

Dong Nguyen
sumber
0

Saya menyukai jawaban @ rich.kelly, tetapi saya ingin menggunakan nomenklatur yang sama dengan classList.add()(string dipisahkan koma), jadi sedikit penyimpangan.

DOMTokenList.prototype.addMany = DOMTokenList.prototype.addMany || function() {
  for (var i = 0; i < arguments.length; i++) {
    this.add(arguments[i]);
  }
}
DOMTokenList.prototype.removeMany = DOMTokenList.prototype.removeMany || function() {
  for (var i = 0; i < arguments.length; i++) {
    this.remove(arguments[i]);
  }
}

Jadi Anda dapat menggunakan:

document.body.classList.addMany('class-one','class-two','class-three');

Saya perlu menguji semua browser, tetapi ini berhasil untuk Chrome.
Haruskah kita memeriksa sesuatu yang lebih spesifik daripada keberadaan DOMTokenList.prototype.addMany? Apa sebenarnya yang menyebabkan classList.add()kegagalan di IE11?

Jason Lydon
sumber
0

Untuk polyfill lain element.classListada di sini . Saya menemukannya melalui MDN .

Saya menyertakan skrip itu dan menggunakannya element.classList.add("first","second","third")sesuai dengan tujuannya.

Rafi
sumber