Rimuovi tutte le classi che iniziano con una determinata stringa


99

Ho un div con id="a"cui possono essere associate qualsiasi numero di classi, da diversi gruppi. Ogni gruppo ha un prefisso specifico. Nel javascript, non so quale classe del gruppo sia sul div. Voglio essere in grado di cancellare tutte le classi con un dato prefisso e quindi aggiungerne uno nuovo. Se desidero rimuovere tutte le classi che iniziano con "bg", come posso farlo? Qualcosa di simile, ma funziona davvero:

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

Risposte:


59

Con jQuery, l'elemento DOM effettivo è all'indice zero, dovrebbe funzionare

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

34
Attento a questo. Il confine della parola si divide sul trattino ('-') e sui punti e altri, quindi i nomi delle classi come "bg.a", "bg-a" ecc. Non verranno rimossi ma sostituiti con ".a", "-a" ecc. Quindi, se hai nomi di classi con caratteri di punteggiatura, potresti incontrare dei problemi semplicemente eseguendo una semplice sostituzione regex. Ecco un thread SO sulla definizione del confine di parola
Jakub P.

6
La risposta di Kabir Sarin di seguito con split ('') e indexOf è migliore IMO perché non farà apparire quelle classi "zombi" con caratteri speciali.
Jakub P.

2
Questo metodo può ancora essere utilizzato con un'espressione regolare meglio, come quello trovato qui: stackoverflow.com/a/2644364/1333402
ssmith

109

Una divisione delle espressioni regolari sul confine di parola \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(" ").trim();

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

Aggiornamento ES6 2018:

const prefix = "prefix";
const classes = el.className.split(" ").filter(c => !c.startsWith(prefix));
el.className = classes.join(" ").trim();

9
Questo è un approccio migliore rispetto all'utilizzo di RegExp con \ b (controllo del limite di parola) perché impedisce la comparsa di "classi zombie". Se hai classi come "prefix-suffix", la 'risposta migliore' in questo thread lascerà la classe '-suffix' perché \ b si dividerà prima di '-' char. La tua soluzione split-map-join funziona intorno a questo :) Ho creato un piccolo plugin jQuery attorno alla tua soluzione, Kabir: ( gist.github.com/2881585 )
Jakub P.

3
+1 Anch'io sono d'accordo, ogni altra risposta sembra essere solo una semplice regex che interromperebbe i confini delle parole non spaziali. Se domani avrò tempo, fornirò un test unitario che lo provi.
gerges

1
Mi piace anche se questo in realtà non è un codice valido, poiché la funzione anonima in filterdeve restituire un booleano. Funzionerà: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

Una soluzione più valida utilizza la mappa:$e.attr('class', $.map($e.attr('class').split(' '), function (klass) { return klass.indexOf(prefix) != 0 ? klass : undefined; }).join(' '));
M Miller

2
Questo approccio funziona al meglio. Ho usato il plugin di @ JakubP. Un suggerimento, se posso: quello che fa, quando ora restituisce le classi, crea molto spazio. Ad esempio class="blackRow blackText orangeFace blackHead", tornerà class=" orangeFace "se corri removeClassPrefix("black");. Ho risolto questo tagliando il risultato in questo modo: el.className = $.trim(classes.join(" "));.
Albert

29

Ho scritto un semplice plugin jQuery - alterClass , che fa la rimozione della classe jolly. Opzionalmente aggiungerà anche classi.

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

Grazie Pete! Ho appena usato il tuo plugin e funziona benissimo ... mi ha fatto risparmiare tempo!
jordan.baucke

11

Non hai bisogno di alcun codice specifico di jQuery per gestirlo. Basta usare una RegExp per sostituirli:

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

Puoi modificarlo per supportare qualsiasi prefisso, ma il metodo più veloce è sopra poiché RegExp verrà compilato solo una volta:

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

9

Utilizzando la seconda firma di $.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>​]

A partire da jQuery v1.4, questo è l'approccio migliore.
Dinei


3

Un approccio che utilizzerei utilizzando semplici costrutti jQuery e funzioni di gestione degli array, è quello di dichiarare una funzione che prende l'ID del controllo e il prefisso della classe e cancella tutte le classi. Il codice è allegato:

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

Ora questa funzione può essere chiamata da qualsiasi luogo, con un clic del pulsante o dal codice:

removeclasses("a","bg");

2

Stavo cercando una soluzione esattamente per lo stesso problema. Per rimuovere tutte le classi che iniziano con il prefisso "fontid_" Dopo aver letto questo articolo ho scritto un piccolo plugin che sto usando ora.

(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));

Utilizzo:

$('#elementId').removePrefixedClasses('prefix-of-classes_');

Questa non è altro che la mia soluzione con 10 volte più righe e una "stringa che inizia con" meno efficiente controlla: - /
sarink

2

Per i browser moderni:

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

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

1

So che è una vecchia domanda, ma ho trovato una nuova soluzione e voglio sapere se ha degli svantaggi?

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

1

In una riga ... Rimuove tutte le classi che corrispondono a un'espressione regolare someRegExp

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

0

La risposta di Prestaul è stata utile, ma non ha funzionato per me. Il modo jQuery per selezionare un oggetto per id non ha funzionato. Ho dovuto usare

document.getElementById("a").className

invece di

$("#a").className

o $ ("# a") [0] .className come className è disponibile solo sull'elemento DOM e non sull'oggetto jQuery
Naeem Sarfraz

questo è un commento per la risposta di qualcuno, non una risposta
TJ

0

Uso anche il trattino "-" e le cifre per il nome della classe. Quindi la mia versione include "\ d-"

$('#a')[0].className = $('#a')[0].className.replace(/\bbg.\d-*?\b/g, '');

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);

-6
$("#element").removeAttr("class").addClass("yourClass");

3
Non credo che tu abbia letto molto bene la domanda. L'utente non chiedeva semplicemente di rimuovere una classe e aggiungerne un'altra.
Andrew Barber

1
@Andrew Barber: hai ragione questa non è la risposta giusta, ma majorsk8 ha suggerito come cancellare tutte le classi (removeAttr), non solo una;)
Inclina l'
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.