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!

atp
sumber
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
css wildcard surfingsuccess.com/css/…
Max Hodges

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/

jimmystormig
sumber
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, '');
});
Kobi
sumber
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' )
Pete B
sumber
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 .

gemetar
sumber
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');
Charly Guirao
sumber
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/

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

drzaus
sumber
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;
};
ARS81
sumber
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;
};
Pascal Polleunus
sumber
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, ''));
    });
};
vsync
sumber
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;
});
nynyny
sumber
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.

kzar
sumber
1

Anda juga bisa menggunakan classNameproperti objek DOM elemen:

var $hello = $('#hello');
$('#hello').attr('class', $hello.get(0).className.replace(/\bcolor-\S+/g, ''));
Alexander Wallin
sumber
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>

Fifi
sumber
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;
};
sarung
sumber
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.

mohammad eslahi sani
sumber
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.

redfox05
sumber
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.

rorymorris89
sumber