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

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

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

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

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

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>​]

Depuis jQuery v1.4, c'est la meilleure approche.
Dinei le


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

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

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

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

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

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

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

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
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
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.