Carattere jolly di jQuery removeClass


370

Esiste un modo semplice per rimuovere tutte le classi corrispondenti, ad esempio,

color-*

quindi se ho un elemento:

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

dopo averlo rimosso, lo sarebbe

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

Grazie!


1
Una regex come nella "risposta accettata" si spezzerà sui confini delle parole non spaziali. Di seguito ho pubblicato una soluzione alternativa. Vedi anche: stackoverflow.com/questions/57812/...
sarink

@KabirSarin da allora la risposta accettata è stata aggiornata per risolvere questo problema.
Emile Bergeron,

Risposte:


680

La funzione removeClass accetta un argomento di funzione da jQuery 1.4 .

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

Esempio live: http://jsfiddle.net/xa9xS/1409/


4
Ho pensato che valesse la pena notare che questo catturerà uno spazio bianco principale di classi abbinate che non iniziano all'inizio. Javascript non supporta il lookbehind positivo, quindi dovresti usare una soluzione alternativa al gruppo di acquisizione. Tuttavia è un argomento controverso, perché la funzione removeClass eliminerà per te gli spazi bianchi dalla stringa della classe tramiteclasses = ( value || "" ).match( rnotwhite ) || [];
eephillip

Mi piace di più questa soluzione! Come posso verificare la rimozione di due o più classi? cioè sport-, nav-e color-?
lowtechsun,

Come faresti per abbinare un finale di classe simile *-color?
Cerchio B,

3
@lowtechsun puoi aggiungere la tua regex in questo modo (color-|sport-|nav-). Abbinerà color-, o sport-, o nav-. Quindi, la risposta sopra sarebbe diventata /(^|\s)(color-|sport-|nav-)\S+/g.
Bogie,

1
La risposta accettata è corretta, ma idiomaticamente, userei \ b che corrisponde a qualsiasi limite di parole piuttosto che al più prolisso (^ | \ s). Quindi, per esempio, per rimuovere tutte le classi costituite dalla parola magia seguita da un numero intero non negativo e solo da quelle, corrisponderei a / \ bmagic \ d + \ b /.
CarlEdman,

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

5
Mi piace questo in quanto riduce il sovraccarico e arriva dritto al punto. Perché usare remove class quando attr fa meglio il lavoro?
Angry Dan,

2
penso che devi proteggere da classi vuote ( c is undefined)? Almeno quando l'ho provato di seguito nel mio plugin in questa pagina, ho$('a').stripClass('post', 1) lanciato "TypeError: Impossibile chiamare il metodo 'sostituisci' di undefined"
drzaus,

1
@Kobi sì, non credo sia possibile filtrare un attributo e restituire un risultato che non lo ha - $('div[class]')dovrebbe restituire solo elementi con class, che abbiano o meno un valore. scenari di test: jsfiddle.net/drzaus/m83mv
drzaus

1
@Kobi - Penso di vedere cosa stai ottenendo; nei casi limite come .removeProp('class')o .className=undefinedil filtro [class]restituisce ancora qualcosa, sono solo undefined. Quindi tecnicamente ha ancora una classe (al contrario .removeAttr('class'), ecco perché interrompe la tua funzione ma non la mia variante. Jsfiddle.net/drzaus/m83mv/4
drzaus

1
Aggiungere un test rapido funziona per me:return c && c.replace(/\bcolor-\S+/g, '');
ssmith

50

Ho scritto un plugin che si chiama alterClass: rimuove le classi di elementi con la corrispondenza jolly. Opzionalmente aggiungere classi: https://gist.github.com/1517285

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

1
Davvero molto bello ... mi ha aiutato a riutilizzare un po 'di codice in cui avevo solo bisogno di rimuovere Twitter Boostrapclassi come questa:$(".search div").children('div').alterClass('span* row-fluid');
Leniel Maccaferri,

15

L'ho generalizzato in un plugin di Jquery che accetta una regex come argomento.

Caffè:

$.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(' ');
  });
};

Quindi, in questo caso, l'utilizzo sarebbe (sia Coffee che Javascript):

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

Si noti che sto usando la Array.filterfunzione che non esiste in IE <9. È possibile utilizzare invece la funzione di filtro di Underscore o Google per un polyfill come questo WTFPL .


11

Se vuoi usarlo in altri posti ti suggerisco un'estensione. Questo funziona bene per me.

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

Uso:

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

4

possiamo ottenere tutte le classi da .attr("class"), e da Array, e loop e filtro:

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/


Aggiunto var prefix='color';e modificato ...if (classArr[i].substr(0, prefix.length) != prefix)
Rich C

4

Simile a @ di tremby risposta , ecco @ di Kobi risposta come un plugin che abbinerà sia prefissi o suffissi.

  • ex) strisce btn-minie btn-dangernon btnquando stripClass("btn-").
  • ex) strisce horsebtne cowbtnma non btn-minio btnquandostripClass('btn', 1)

Codice:

$.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
Per la cronaca, non sono d'accordo sul fatto che sia più semplice.
tremby,

@tremby mi dispiace, intendevo più semplice nell'uso tipico (cioè prefissi e suffissi), dal momento che non devi scrivere una regex ogni volta
drzaus,

3
Non sono ancora d'accordo. Con il tuo metodo devi leggere la documentazione e ricordare quale endOrBegindeve essere esattamente il valore . Non è autoesplicativo. Cosa c'è di difficile nello scrivere una regex? /^match-at-start/e /match-at-end$/sono noti a tutti gli sviluppatori JS. Ma ognuno per conto suo.
tremby,

1
@tremby se non per essere abusati regex accattonaggio, un'opzione non-regex più si avvicina la firma esistente di addClass, removeClasse toggleClass, che è noto per tutti gli sviluppatori jQuery. Cosa c'è di difficile nella lettura della documentazione? ;)
drzaus,

2
Non c'è nulla di difficile nella lettura della documentazione, ma come dice @tremby, la sua soluzione è autoesplicativa, mentre la tua richiede documentazione. Le soluzioni autoesplicative sono più semplici da usare per definizione.
Francisco Hodge,

2

Per un plugin jQuery prova questo

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

o questo

$.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

Sulla base di ARS81 's risposta (che corrisponde solo i nomi delle classi iniziano con), ecco una versione più flessibile. Anche una hasClass()versione regex.

Uso: $('.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

Questo rimuoverà efficacemente tutti i nomi di classe che iniziano con prefixl' classattributo di un nodo . Altre risposte non supportano gli elementi SVG (al momento della stesura di questo), ma questa soluzione fa:

$.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, ''));
    });
};

Non sarebbe più efficiente creare l' RegExpoggetto una volta, al di fuori di ogni callback?
Emile Bergeron,

1
@EmileBergeron - sì, lo sarebbe!
Apporterò

2

Ho avuto lo stesso problema e ho trovato quanto segue che utilizza il metodo _.filter di underscore. Una volta scoperto che removeClass ha una funzione e ti fornisce un elenco di nomi di classe, è stato facile trasformarlo in un array e filtrare il nome della classe per tornare al metodo 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
Puoi spiegare cosa fa il carattere di sottolineatura in _.filter
bart

2

Puoi farlo anche con JavaScript vanilla usando Element.classList . Non è necessario nemmeno usare un'espressione regolare:

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

Nota: si noti che creiamo una Arraycopia del classListprima di iniziare, è importante poiché classListè un live DomTokenListche verrà aggiornato man mano che le classi vengono rimosse.


1

Puoi anche usare la classNameproprietà dell'oggetto DOM dell'elemento:

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

1

Una funzione generica che rimuove qualsiasi classe che inizia con 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

Una regex che divide i confini delle parole \bnon è la soluzione migliore per questo:

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

o come 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

se hai più di un elemento con un nome di classe 'esempio', per rimuovere le classi di 'color-' in tutti loro puoi farlo: [usando jquery]

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

se non inserisci [a-z1-9 -] * nella tua regex, non rimuoverà le classi che hanno un numero o alcuni "-" nei loro nomi.


0

Se devi solo rimuovere l'ultimo colore impostato, potrebbe essere adatto a te.

Nella mia situazione, avevo bisogno di aggiungere una classe di colore al tag body in un evento click e rimuovere l'ultimo colore impostato. In tal caso, si memorizza il colore corrente e quindi si cerca il tag di dati per rimuovere l'ultimo colore impostato.

Codice:

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

Potrebbe non essere esattamente quello di cui hai bisogno, ma per me lo è stato e questa è stata la prima domanda SO che ho guardato, quindi ho pensato di condividere la mia soluzione nel caso in cui aiuti qualcuno.


Questo è irrilevante qui. Avresti potuto rispondere alla tua domanda poiché si tratta di un comportamento incoraggiato su SO.
Emile Bergeron,

@Emile: è vero. Potrei farlo poiché non risponde direttamente alla domanda originale. Devo lasciare questa risposta o rimuoverla?
Redfox05

A quel punto, è a tuo rischio, non è stato ancora votato né votato. Quindi potresti spostarlo sulla tua domanda senza rischi. Inoltre, cerca di evitare i duplicati controllando se c'è già una domanda al riguardo.
Emile Bergeron,

0

Un modo alternativo di affrontare questo problema è utilizzare gli attributi dei dati, che sono per loro natura unici.

Dovresti impostare il colore di un elemento come: $el.attr('data-color', 'red');

E lo modifichi in css come: [data-color="red"]{ color: tomato; }

Ciò annulla la necessità di utilizzare le classi, il che ha l'effetto collaterale di dover rimuovere le vecchie classi.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.