Hapus semua kelas yang dimulai dengan string tertentu

99

Saya memiliki div id="a"yang mungkin memiliki sejumlah kelas yang menyertainya, dari beberapa grup. Setiap kelompok memiliki prefiks tertentu. Di javascript, saya tidak tahu kelas mana dari grup yang ada di div. Saya ingin menghapus semua kelas dengan prefiks tertentu dan kemudian menambahkan yang baru. Jika saya ingin menghapus semua kelas yang dimulai dengan "bg", bagaimana cara melakukannya? Sesuatu seperti ini, tetapi itu benar-benar berfungsi:

$("#a").removeClass("bg*");
Brad
sumber

Jawaban:

59

Dengan jQuery, elemen DOM sebenarnya berada di indeks nol, ini seharusnya berfungsi

$('#a')[0].className = $('#a')[0].className.replace(/\bbg.*?\b/g, '');
Menepuk
sumber
34
Hati-hati dengan yang satu ini. Pembagian batas kata pada karakter tanda hubung ('-') dan titik dan lainnya, jadi nama kelas seperti "bg.a", "bg-a" dll. Tidak akan dihapus tetapi diganti dengan ".a", "-a" dll. Jadi, jika Anda memiliki nama kelas dengan karakter tanda baca, Anda mungkin mengalami masalah hanya dengan menjalankan penggantian regex sederhana. Berikut adalah utas SO tentang definisi batas kata
Jakub P.
6
Jawaban Kabir Sarin di bawah ini dengan split ('') dan indexOf adalah IMO yang lebih baik karena tidak akan menyebabkan kelas "zombie" berkarakter khusus itu muncul.
Jakub P.
2
Metode ini masih dapat digunakan dengan regex yang lebih baik, seperti yang ditemukan di sini: stackoverflow.com/a/2644364/1333402
ssmith
109

Pemisahan regex pada batas kata \bbukanlah solusi terbaik untuk ini:

var prefix = "prefix";
var classes = el.className.split(" ").filter(function(c) {
    return c.lastIndexOf(prefix, 0) !== 0;
});
el.className = classes.join(" ").trim();

atau sebagai mixin jQuery:

$.fn.removeClassPrefix = function(prefix) {
    this.each(function(i, el) {
        var classes = el.className.split(" ").filter(function(c) {
            return c.lastIndexOf(prefix, 0) !== 0;
        });
        el.className = $.trim(classes.join(" "));
    });
    return this;
};

Pembaruan ES6 2018:

const prefix = "prefix";
const classes = el.className.split(" ").filter(c => !c.startsWith(prefix));
el.className = classes.join(" ").trim();
sarink
sumber
9
Ini adalah pendekatan yang lebih baik daripada menggunakan RegExp dengan \ b (pemeriksaan batas kata) karena mencegah 'kelas zombie' muncul. Jika Anda memiliki kelas seperti "prefix-suffix", 'jawaban terbaik' di utas ini akan meninggalkan kelas '-suffix' karena \ b akan dipisahkan sebelum '-' char. Solusi split-map-join Anda mengatasinya :) Saya membuat plugin jQuery kecil di sekitar solusi Anda, Kabir: ( gist.github.com/2881585 )
Jakub P.
3
+1 Saya juga setuju, setiap jawaban lain tampaknya hanya berupa ekspresi reguler sederhana yang akan melanggar batas kata non-spasi. Jika saya punya waktu besok, saya akan memberikan tes unit yang membuktikan ini.
gerges
1
Saya suka meskipun ini sebenarnya bukan kode yang valid, karena fungsi anonim filterharus mengembalikan boolean. Ini akan berhasil:var classes = $(e).attr("class").split(" "); $(classes).each(function(i, item) { classes[i] = item.indexOf("prefix") === -1 ? item : "prefix-new"); }); $(e).attr("class", classes.join(" "));
Tim
Solusi yang lebih valid menggunakan peta:$e.attr('class', $.map($e.attr('class').split(' '), function (klass) { return klass.indexOf(prefix) != 0 ? klass : undefined; }).join(' '));
M Miller
2
Pendekatan ini bekerja paling baik. Saya menggunakan plugin @ JakubP. Satu saran jika saya boleh: Apa yang dilakukannya, ketika sekarang mengembalikan kelas, itu menyebabkan banyak ruang. Misalnya class="blackRow blackText orangeFace blackHead"akan kembali class=" orangeFace "jika Anda menjalankan removeClassPrefix("black");. Aku memecahkan ini dengan pemangkasan hasil seperti: el.className = $.trim(classes.join(" "));.
Albert
29

Saya telah menulis plugin jQuery sederhana - alterClass , yang melakukan penghapusan kelas wildcard. Secara opsional akan menambahkan kelas juga.

$( '#foo' ).alterClass( 'foo-* bar-*', 'foobar' ) 
Pete B
sumber
Terima kasih Pete! Baru saja menggunakan plugin Anda dan berfungsi dengan baik ... menghemat waktu saya!
jordan.baucke
11

Anda tidak memerlukan kode khusus jQuery untuk menangani ini. Cukup gunakan RegExp untuk menggantinya:

$("#a").className = $("#a").className.replace(/\bbg.*?\b/g, '');

Anda dapat memodifikasi ini untuk mendukung awalan apa pun tetapi metode yang lebih cepat ada di atas karena RegExp hanya akan dikompilasi sekali:

function removeClassByPrefix(el, prefix) {
    var regx = new RegExp('\\b' + prefix + '.*?\\b', 'g');
    el.className = el.className.replace(regx, '');
    return el;
}
Prestaul
sumber
9

Menggunakan tanda tangan kedua dari $.fn.removeClass:

// Considering:
var $el = $('<div class="  foo-1 a b foo-2 c foo"/>');

function makeRemoveClassHandler(regex) {
  return function (index, classes) {
    return classes.split(/\s+/).filter(function (el) {return regex.test(el);}).join(' ');
  }
}

$el.removeClass(makeRemoveClassHandler(/^foo-/));
//> [<div class=​"a b c foo">​</div>​]
abernier
sumber
Sejak jQuery v1.4, ini adalah pendekatan terbaik.
Dinei
3

http://www.mail-archive.com/[email protected]/msg03998.html mengatakan:

... dan .removeClass () akan menghapus semua kelas ...

Ini bekerja untuk saya;)

Bersulang


sumber
Ini adalah pilihan yang lebih baik! Bekerja.
Afshin Mehrabani
12
Pertanyaannya tidak menanyakan cara menghapus semua kelas, tetapi pertanyaannya adalah cara menghapus semua kelas yang dimulai dengan string tertentu. Kedua hal ini sangat, sangat berbeda.
Chris Harrison
3

Pendekatan yang akan saya gunakan menggunakan konstruksi jQuery sederhana dan fungsi penanganan array, adalah mendeklarasikan fungsi yang mengambil id dari kontrol dan awalan kelas dan menghapus semua yang diklasifikasikan. Kode terlampir:

function removeclasses(controlIndex,classPrefix){
    var classes = $("#"+controlIndex).attr("class").split(" ");
    $.each(classes,function(index) {
        if(classes[index].indexOf(classPrefix)==0) {
            $("#"+controlIndex).removeClass(classes[index]);
        }
    });
}

Sekarang fungsi ini bisa dipanggil dari mana saja, dengan mengklik tombol atau dari kode:

removeclasses("a","bg");
nhahtdh
sumber
2

Saya sedang mencari solusi untuk masalah yang persis sama. Untuk menghapus semua kelas dimulai dengan awalan "fontid_" Setelah membaca artikel ini saya menulis sebuah plugin kecil yang saya gunakan sekarang.

(function ($) {
        $.fn.removePrefixedClasses = function (prefix) {
            var classNames = $(this).attr('class').split(' '),
                className,
                newClassNames = [],
                i;
            //loop class names
            for(i = 0; i < classNames.length; i++) {
                className = classNames[i];
                // if prefix not found at the beggining of class name
                if(className.indexOf(prefix) !== 0) {
                    newClassNames.push(className);
                    continue;
                }
            }
            // write new list excluding filtered classNames
            $(this).attr('class', newClassNames.join(' '));
        };
    }(fQuery));

Pemakaian:

$('#elementId').removePrefixedClasses('prefix-of-classes_');
Pawel
sumber
Ini tidak lebih dari solusi saya dengan 10x lebih banyak baris dan "string dimulai dengan" yang kurang efisien periksa: - /
sarink
2

Untuk browser modern:

let element = $('#a')[0];
let cls = 'bg';

element.classList.remove.apply(element.classList, Array.from(element.classList).filter(v=>v.startsWith(cls)));
Max
sumber
1

Saya tahu ini pertanyaan lama, tetapi saya menemukan solusi baru dan ingin tahu apakah ada kerugiannya?

$('#a')[0].className = $('#a')[0].className
                              .replace(/(^|\s)bg.*?(\s|$)/g, ' ')
                              .replace(/\s\s+/g, ' ')
                              .replace(/(^\s|\s$)/g, '');
Jan.
sumber
1

Dalam satu baris ... Menghapus semua kelas yang cocok dengan ekspresi reguler someRegExp

$('#my_element_id').removeClass( function() { return (this.className.match(/someRegExp/g) || []).join(' ').replace(prog.status.toLowerCase(),'');});
Adam111p
sumber
0

Jawaban Prestaul sangat membantu, tetapi tidak berhasil bagi saya. Cara jQuery untuk memilih objek berdasarkan id tidak berfungsi. Saya harus menggunakan

document.getElementById("a").className

dari pada

$("#a").className
Brad
sumber
atau $ ("# a") [0] .className sebagai className hanya tersedia pada elemen DOM dan bukan objek jQuery
Naeem Sarfraz
ini adalah komentar untuk jawaban seseorang, bukan jawaban
TJ
0

Saya juga menggunakan tanda hubung'- 'dan angka untuk nama kelas. Jadi versi saya menyertakan '\ d-'

$('#a')[0].className = $('#a')[0].className.replace(/\bbg.\d-*?\b/g, '');
Jamland
sumber
0
(function($)
{
    return this.each(function()
    {
        var classes = $(this).attr('class');

        if(!classes || !regex) return false;

        var classArray = [];

        classes = classes.split(' ');

        for(var i=0, len=classes.length; i<len; i++) if(!classes[i].match(regex)) classArray.push(classes[i]);

        $(this).attr('class', classArray.join(' '));
    });
})(jQuery);
rampok
sumber
-6
$("#element").removeAttr("class").addClass("yourClass");
mayork8
sumber
3
Saya rasa Anda tidak membaca pertanyaan dengan baik. Pengguna tidak bertanya tentang menghapus kelas dan menambahkan kelas lain.
Andrew Barber
1
@ Andrew Barber: Anda benar, ini bukan jawaban yang benar, tetapi majorsk8 menyarankan cara menghapus semua kelas (removeAttr), bukan hanya satu kelas;)
Miringkan