jQuery removeClass wildcard


370

Apakah ada cara mudah untuk menghapus semua kelas yang cocok, misalnya,

color-*

jadi jika saya memiliki elemen:

<div id="hello" class="color-red color-brown foo bar"></div>

setelah menghapus, itu akan menjadi

<div id="hello" class="foo bar"></div>

Terima kasih!


1
Regex seperti dalam "jawaban yang diterima" akan melanggar batas kata non-spasi. Saya telah memposting solusi alternatif di bawah ini. Lihat juga: stackoverflow.com/questions/57812/...
sarink

@KabirSarin jawaban yang diterima telah diperbarui untuk memperbaikinya.
Emile Bergeron

Jawaban:


679

Fungsi removeClass mengambil argumen fungsi sejak jQuery 1.4 .

$("#hello").removeClass (function (index, className) {
    return (className.match (/(^|\s)color-\S+/g) || []).join(' ');
});

Contoh langsung: http://jsfiddle.net/xa9xS/1409/


4
Saya pikir perlu dicatat bahwa ini akan menangkap ruang kelas terkemuka yang cocok yang tidak dimulai pada awal. Javascript tidak mendukung tampilan positif di belakang sehingga Anda harus menggunakan solusi capture group. Namun ini adalah moot, karena fungsi removeClass akan menghapus spasi putih dari string kelas Anda untuk Anda melaluiclasses = ( value || "" ).match( rnotwhite ) || [];
eephillip

Saya paling suka solusi ini! Bagaimana saya memeriksa dua kelas atau lebih yang akan dihapus? yaitu sport-, nav-dan color-?
lowtechsun

Bagaimana Anda melakukan ini agar sesuai dengan kelas yang berakhir seperti *-color?
Lingkaran B

3
@lowtechsun Anda dapat menambahkan di regex Anda seperti ini (color-|sport-|nav-). Itu akan cocok color-, atau sport-, atau nav-. Jadi, jawaban di atas akan menjadi /(^|\s)(color-|sport-|nav-)\S+/g.
Bogie

1
Jawaban yang diterima benar, tetapi secara idiomatis, saya akan menggunakan \ b yang cocok dengan batas kata apa pun daripada yang lebih bertele-tele (^ | \ s). Jadi, misalnya, untuk menghapus semua kelas yang terdiri dari kata ajaib diikuti oleh integer non-negatif dan hanya itu, saya akan cocok dengan / \ bmagic \ d + \ b /.
CarlEdman

98
$('div').attr('class', function(i, c){
    return c.replace(/(^|\s)color-\S+/g, '');
});

5
Saya suka ini karena mengurangi overhead dan langsung ke titik. Mengapa menggunakan remove class ketika attr melakukan pekerjaan dengan lebih baik?
Angry Dan

2
saya pikir Anda perlu melindungi terhadap kelas kosong ( c is undefined)? Setidaknya ketika saya mencobanya di bawah ini di plugin saya di halaman ini, $('a').stripClass('post', 1)melemparkan "TypeError: Tidak dapat memanggil metode 'ganti' yang tidak terdefinisi"
drzaus

1
@ Kobi ya saya tidak berpikir itu mungkin untuk memfilter pada atribut dan mengembalikan hasil yang tidak memilikinya - $('div[class]')hanya boleh mengembalikan elemen dengan class, apakah mereka memiliki nilai atau tidak. skenario pengujian: jsfiddle.net/drzaus/m83mv
drzaus

1
@ Kobi - Saya pikir saya mengerti apa yang Anda maksud; dalam kasus tepi suka .removeProp('class')atau .className=undefinedfilter [class]masih mengembalikan sesuatu, mereka hanya undefined. Jadi secara teknis masih memiliki kelas (sebagai lawan dari .removeAttr('class'), itulah sebabnya ia merusak fungsi Anda tetapi bukan varian saya. Jsfiddle.net/drzaus/m83mv/4
drzaus

1
Menambahkan tes cepat berfungsi untuk saya:return c && c.replace(/\bcolor-\S+/g, '');
ssmith

50

Saya telah menulis sebuah plugin yang melakukan ini disebut alterClass - Hapus elemen kelas dengan pencocokan wildcard. Opsional tambahkan kelas: https://gist.github.com/1517285

$( '#foo' ).alterClass( 'foo-* bar-*', 'foobar' )

1
Sangat bagus memang ... membantu saya menggunakan kembali beberapa kode di mana saya hanya perlu menghapus Twitter Boostrapkelas-kelas seperti ini:$(".search div").children('div').alterClass('span* row-fluid');
Leniel Maccaferri

15

Saya telah menyamaratakan ini menjadi plugin Jquery yang menggunakan regex sebagai argumen.

Kopi:

$.fn.removeClassRegex = (regex) ->
  $(@).removeClass (index, classes) ->
    classes.split(/\s+/).filter (c) ->
      regex.test c
    .join ' '

Javascript:

$.fn.removeClassRegex = function(regex) {
  return $(this).removeClass(function(index, classes) {
    return classes.split(/\s+/).filter(function(c) {
      return regex.test(c);
    }).join(' ');
  });
};

Jadi, untuk kasus ini, penggunaannya adalah (Kopi dan Javascript):

$('#hello').removeClassRegex(/^color-/)

Perhatikan bahwa saya menggunakan Array.filterfungsi yang tidak ada di IE <9. Anda dapat menggunakan fungsi filter Underscore sebagai gantinya atau Google untuk polyfill seperti ini WTFPL .


11

Jika Anda ingin menggunakannya di tempat lain saya sarankan Anda ekstensi. Yang ini berfungsi dengan baik untuk saya.

 $.fn.removeClassStartingWith = function (filter) {
    $(this).removeClass(function (index, className) {
        return (className.match(new RegExp("\\S*" + filter + "\\S*", 'g')) || []).join(' ')
    });
    return this;
};

Pemakaian:

$(".myClass").removeClassStartingWith('color');

4

kita bisa mendapatkan semua kelas dengan .attr("class"), dan ke Array, Dan loop & filter:

var classArr = $("#sample").attr("class").split(" ")
$("#sample").attr("class", "")
for(var i = 0; i < classArr.length; i ++) {
    // some condition/filter
    if(classArr[i].substr(0, 5) != "color") {
        $("#sample").addClass(classArr[i]);
    }
}

demo: http://jsfiddle.net/L2A27/1/


Ditambahkan var prefix='color';dan diubah ...if (classArr[i].substr(0, prefix.length) != prefix)
Rich C

4

Mirip dengan jawaban @ tremby , berikut adalah jawaban @ Kobi sebagai plugin yang akan cocok dengan awalan atau sufiks.

  • ex) strip btn-minidan btn-dangertetapi tidak btnkapan stripClass("btn-").
  • ex) strip horsebtndan cowbtntetapi tidak btn-miniatau btnkapanstripClass('btn', 1)

Kode:

$.fn.stripClass = function (partialMatch, endOrBegin) {
    /// <summary>
    /// The way removeClass should have been implemented -- accepts a partialMatch (like "btn-") to search on and remove
    /// </summary>
    /// <param name="partialMatch">the class partial to match against, like "btn-" to match "btn-danger btn-active" but not "btn"</param>
    /// <param name="endOrBegin">omit for beginning match; provide a 'truthy' value to only find classes ending with match</param>
    /// <returns type=""></returns>
    var x = new RegExp((!endOrBegin ? "\\b" : "\\S+") + partialMatch + "\\S*", 'g');

    // https://stackoverflow.com/a/2644364/1037948
    this.attr('class', function (i, c) {
        if (!c) return; // protect against no class
        return c.replace(x, '');
    });
    return this;
};

https://gist.github.com/zaus/6734731


1
Sebagai catatan, saya tidak setuju bahwa ini lebih sederhana.
gemetar

@tremby maaf, maksudku lebih sederhana dalam penggunaan umum (yaitu awalan dan sufiks), karena Anda tidak harus menulis regex setiap kali
drzaus

3
Saya masih tidak setuju. Dengan metode Anda, Anda harus membaca dokumentasi dan mengingat apa sebenarnya nilai yang endOrBegindiperlukan. Itu tidak jelas. Apa yang sulit tentang menulis regex? /^match-at-start/dan /match-at-end$/diketahui oleh setiap pengembang JS. Tetapi masing-masing untuk dirinya sendiri.
gemetar

1
@tremby selain regexes memohon untuk disalahgunakan, pilihan non-regex lebih erat sesuai tanda tangan yang ada addClass, removeClassdan toggleClass, yang dikenal untuk setiap pengembang jQuery. Apa yang sulit tentang membaca dokumentasi? ;)
drzaus

2
Tidak ada yang sulit tentang membaca dokumentasi, tetapi seperti yang dikatakan @tremby, solusinya cukup jelas, sedangkan milik Anda memerlukan dokumentasi. Solusi penjelasan sendiri lebih mudah digunakan menurut definisi.
Francisco Hodge

2

Untuk plugin jQuery coba ini

$.fn.removeClassLike = function(name) {
    return this.removeClass(function(index, css) {
        return (css.match(new RegExp('\\b(' + name + '\\S*)\\b', 'g')) || []).join(' ');
    });
};

atau ini

$.fn.removeClassLike = function(name) {
    var classes = this.attr('class');
    if (classes) {
        classes = classes.replace(new RegExp('\\b' + name + '\\S*\\s?', 'g'), '').trim();
        classes ? this.attr('class', classes) : this.removeAttr('class');
    }
    return this;
};

2

Berdasarkan ARS81 's jawaban (yang hanya cocok nama kelas diawali dengan), inilah versi yang lebih fleksibel. Juga hasClass()versi regex.

Pemakaian: $('.selector').removeClassRegex('\\S*-foo[0-9]+')

$.fn.removeClassRegex = function(name) {
  return this.removeClass(function(index, css) {
    return (css.match(new RegExp('\\b(' + name + ')\\b', 'g')) || []).join(' ');
  });
};

$.fn.hasClassRegex = function(name) {
  return this.attr('class').match(new RegExp('\\b(' + name + ')\\b', 'g')) !== null;
};

2

Ini akan secara efektif menghapus semua nama kelas yang dimulai dengan prefixdari classatribut node . Jawaban lain tidak mendukung elemen SVG (saat penulisan ini), tetapi solusi ini tidak:

$.fn.removeClassPrefix = function(prefix){
    var c, regex = new RegExp("(^|\\s)" + prefix + "\\S+", 'g');
    return this.each(function(){
        c = this.getAttribute('class');
        this.setAttribute('class', c.replace(regex, ''));
    });
};

Bukankah lebih efisien untuk membuat RegExpobjek sekali, keluar dari setiap panggilan balik?
Emile Bergeron

1
@ EmileBergeron - ya itu akan terjadi! Saya akan melakukan perubahan
vsync

2

Saya memiliki masalah yang sama dan muncul dengan berikut ini yang menggunakan metode _.filter garis bawah. Setelah saya menemukan bahwa removeClass mengambil fungsi dan memberi Anda daftar nama kelas, mudah untuk mengubahnya menjadi array dan memfilter nama kelas untuk kembali ke metode removeClass.

// Wildcard removeClass on 'color-*'
$('[class^="color-"]').removeClass (function (index, classes) {
  var
    classesArray = classes.split(' '),
    removeClass = _.filter(classesArray, function(className){ return className.indexOf('color-') === 0; }).toString();

  return removeClass;
});

1
Bisakah Anda jelaskan apa yang garis bawah lakukan di _.filter
bart

2

Anda juga bisa melakukan ini dengan JavaScript vanilla menggunakan Element.classList . Tidak perlu menggunakan ekspresi reguler juga:

function removeColorClasses(element) { for (let className of Array.from(element.classList)) if (className.startsWith("color-")) element.classList.remove(className); }

Catatan: Perhatikan bahwa kami membuat Arraysalinan dari classListsebelum memulai, itu penting karena classListlive DomTokenListyang akan diperbarui ketika kelas dihapus.


1

Anda juga bisa menggunakan classNameproperti objek DOM elemen:

var $hello = $('#hello');
$('#hello').attr('class', $hello.get(0).className.replace(/\bcolor-\S+/g, ''));

1

Fungsi generik yang menghapus kelas apa pun yang dimulai dengan begin:

function removeClassStartingWith(node, begin) {
    node.removeClass (function (index, className) {
        return (className.match ( new RegExp("\\b"+begin+"\\S+", "g") ) || []).join(' ');
    });
}

http://jsfiddle.net/xa9xS/2900/

var begin = 'color-';

function removeClassStartingWith(node, begin) {
    node.removeClass (function (index, className) {
        return (className.match ( new RegExp("\\b"+begin+"\\S+", "g") ) || []).join(' ');
    });
}

removeClassStartingWith($('#hello'), 'color-');

console.log($("#hello")[0].className);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="hello" class="color-red color-brown foo bar"></div>


0

Pemisahan regex pada batas kata \bbukan 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(" ");

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 = classes.join(" ");
    });
    return this;
};

0

jika Anda memiliki lebih dari satu elemen yang memiliki nama kelas 'contoh', untuk menghapus kelas 'warna-' pada semuanya, Anda dapat melakukan ini: [menggunakan jquery]

var objs = $('html').find('.example');
for(index=0 ; index < obj1s.length ; index++){
    objs[index].className = objs[index].className.replace(/col-[a-z1-9\-]*/,'');
}

jika Anda tidak memasukkan [a-z1-9 -] * di regex Anda, ia tidak akan menghapus kelas yang memiliki nomor atau '-' dalam namanya.


0

Jika Anda hanya perlu menghapus warna set terakhir, berikut ini mungkin cocok untuk Anda.

Dalam situasi saya, saya perlu menambahkan kelas warna ke tag tubuh pada acara klik dan menghapus warna terakhir yang telah ditetapkan. Dalam hal ini, Anda menyimpan warna saat ini, dan kemudian mencari tag data untuk menghapus warna set terakhir.

Kode:

var colorID = 'Whatever your new color is';

var bodyTag = $('body');
var prevColor = bodyTag.data('currentColor'); // get current color
bodyTag.removeClass(prevColor);
bodyTag.addClass(colorID);
bodyTag.data('currentColor',colorID); // set the new color as current

Mungkin tidak persis apa yang Anda butuhkan, tetapi bagi saya itu dan ini adalah pertanyaan SO pertama yang saya lihat, jadi saya pikir saya akan membagikan solusi saya jika itu membantu siapa pun.


Itu tidak relevan di sini. Anda bisa menjawab pertanyaan Anda sendiri karena ini adalah perilaku yang dianjurkan di SO.
Emile Bergeron

@ Emile: Itu benar. Saya mungkin melakukan itu karena tidak langsung menjawab pertanyaan awal. Haruskah saya meninggalkan jawaban ini atau menghapusnya?
redfox05

Pada saat itu, itu adalah risiko Anda sendiri, itu belum terpilih atau belum dipilih. Jadi Anda bisa memindahkannya ke pertanyaan Anda sendiri tanpa risiko. Juga, cobalah untuk menghindari duplikat dengan memeriksa apakah sudah ada pertanyaan tentang ini.
Emile Bergeron

0

Cara alternatif untuk mendekati masalah ini adalah dengan menggunakan atribut data, yang pada dasarnya unik.

Anda telah mengatur warna elemen seperti: $el.attr('data-color', 'red');

Dan Anda akan menggunakannya dalam css seperti: [data-color="red"]{ color: tomato; }

Ini meniadakan kebutuhan untuk menggunakan kelas, yang memiliki efek samping dari keharusan untuk menghapus kelas lama.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.