Supprimer toutes les classes qui commencent par une certaine chaîne

99

J'ai un div avec id="a"qui peut avoir n'importe quel nombre de classes attachées, de plusieurs groupes. Chaque groupe a un préfixe spécifique. Dans le javascript, je ne sais pas quelle classe du groupe est sur le div. Je veux pouvoir effacer toutes les classes avec un préfixe donné, puis en ajouter une nouvelle. Si je souhaite supprimer toutes les classes commençant par "bg", comment puis-je faire? Quelque chose comme ça, mais qui fonctionne réellement:

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

Réponses:

59

Avec jQuery, l'élément DOM réel est à l'index zéro, cela devrait fonctionner

$('#a')[0].className = $('#a')[0].className.replace(/\bbg.*?\b/g, '');
Tapoter
la source
34
Attention à celui-ci. La limite de mot se divise sur le caractère tiret ('-') et les points et autres, ainsi les noms de classe comme "bg.a", "bg-a" etc. ne seront pas supprimés mais remplacés par ".a", "-a" etc. Donc, si vous avez des noms de classe avec des caractères de ponctuation, vous risquez de rencontrer des problèmes en exécutant simplement une simple regex replace. Voici un fil de
Jakub P.
6
La réponse de Kabir Sarin ci-dessous avec split ('') et indexOf est meilleure IMO car elle ne fera pas apparaître ces classes «zombies» à caractères spéciaux.
Jakub P.
2
Cette méthode peut toujours être utilisée avec une meilleure regex, comme celle trouvée ici: stackoverflow.com/a/2644364/1333402
ssmith
109

Une regex fractionnée sur la limite du mot \bn'est pas la meilleure solution pour cela:

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

ou en tant que 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;
};

Mise à jour ES6 2018:

const prefix = "prefix";
const classes = el.className.split(" ").filter(c => !c.startsWith(prefix));
el.className = classes.join(" ").trim();
couler
la source
9
C'est une meilleure approche que d'utiliser RegExp avec \ b (vérification des limites de mots) car elle empêche les «classes zombies» d'apparaître. Si vous avez des classes comme "préfixe-suffixe", la 'meilleure réponse' de ce fil laissera la classe '-suffixe' car \ b se séparera avant le caractère '-'. Votre solution split-map-join fonctionne autour de cela :) J'ai créé un petit plugin jQuery autour de votre solution, Kabir: ( gist.github.com/2881585 )
Jakub P.
3
+1 Je suis également d'accord, toutes les autres réponses semblent n'être qu'une simple expression régulière qui briserait les limites des mots non spatiaux. Si j'ai le temps demain, je fournirai un test unitaire qui le prouve.
gerges
1
Je l'aime bien que ce ne soit pas du code valide, car la fonction anonyme filterdoit renvoyer un booléen. Cela fonctionnera: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
Une solution plus valide utilise la carte:$e.attr('class', $.map($e.attr('class').split(' '), function (klass) { return klass.indexOf(prefix) != 0 ? klass : undefined; }).join(' '));
M Miller
2
Cette approche fonctionne le mieux. J'ai utilisé le plugin de @ JakubP. Une suggestion si je puis me permettre: ce qu'il fait, quand il retourne maintenant les classes, cela crée beaucoup d'espace. Par exemple class="blackRow blackText orangeFace blackHead"reviendra class=" orangeFace "si vous exécutez removeClassPrefix("black");. Je résolu ce problème en coupe le résultat comme ceci: el.className = $.trim(classes.join(" "));.
Albert
29

J'ai écrit un simple plugin jQuery - alterClass , qui supprime les classes génériques. Ajoutera éventuellement des classes aussi.

$( '#foo' ).alterClass( 'foo-* bar-*', 'foobar' ) 
Pete B
la source
Merci Pete! Je viens d'utiliser votre plugin et cela fonctionne très bien ... m'a fait gagner du temps!
jordan.baucke
11

Vous n'avez besoin d'aucun code spécifique à jQuery pour gérer cela. Utilisez simplement un RegExp pour les remplacer:

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

Vous pouvez le modifier pour prendre en charge n'importe quel préfixe, mais la méthode la plus rapide est ci-dessus car RegExp ne sera compilé qu'une seule fois:

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

En utilisant la 2ème signature de $.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
la source
Depuis jQuery v1.4, c'est la meilleure approche.
Dinei le
3

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

... et .removeClass () supprimerait toutes les classes ...

Ça marche pour moi ;)

à votre santé


la source
C'est un meilleur choix! Travaux.
Afshin Mehrabani
12
La question ne demande pas comment supprimer toutes les classes, mais comment supprimer toutes les classes commençant par une certaine chaîne. Ces deux choses sont très, très différentes.
Chris Harrison
3

Une approche que j'utiliserais en utilisant des constructions jQuery simples et des fonctions de gestion de tableau consiste à déclarer une fonction qui prend l'identifiant du contrôle et du préfixe de la classe et supprime tout classé. Le code est joint:

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

Maintenant, cette fonction peut être appelée de n'importe où, en cliquant sur un bouton ou à partir du code:

removeclasses("a","bg");
nhahtdh
la source
2

Je cherchais une solution pour exactement le même problème. Pour supprimer toutes les classes commençant par le préfixe "fontid_" Après avoir lu cet article, j'ai écrit un petit plugin que j'utilise maintenant.

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

Usage:

$('#elementId').removePrefixedClasses('prefix-of-classes_');
Pawel
la source
Ce n'est rien de plus que ma solution avec 10x plus de lignes et une "chaîne commence par" moins efficace check: - /
sarink
2

Pour les navigateurs modernes:

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

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

Je sais que c'est une vieille question, mais j'ai trouvé une nouvelle solution et je veux savoir si elle a des inconvénients?

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

En une seule ligne ... Supprime toutes les classes qui correspondent à une expression régulière someRegExp

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

La réponse de Prestaul a été utile, mais cela n'a pas vraiment fonctionné pour moi. La méthode jQuery pour sélectionner un objet par identifiant ne fonctionnait pas. Je devais utiliser

document.getElementById("a").className

au lieu de

$("#a").className
Brad
la source
ou $ ("# a") [0] .className as className n'est disponible que sur l'élément DOM et non sur l'objet jQuery
Naeem Sarfraz
ceci est un commentaire pour la réponse de quelqu'un, pas une réponse
TJ
0

J'utilise également un tiret "-" et des chiffres pour le nom de la classe. Donc ma version inclut '\ d-'

$('#a')[0].className = $('#a')[0].className.replace(/\bbg.\d-*?\b/g, '');
Jamland
la source
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);
Rob
la source
-6
$("#element").removeAttr("class").addClass("yourClass");
majorsk8
la source
3
Je ne pense pas que vous ayez bien lu la question. L'utilisateur ne demandait pas simplement de supprimer une classe et d'en ajouter une autre.
Andrew Barber
1
@Andrew Barber: vous avez raison, ce n'est pas la bonne réponse, mais majorsk8 a suggéré comment effacer toutes les classes (removeAttr), pas seulement une seule;)
Tilt