Eliminar todas las clases que comienzan con una determinada cadena

99

Tengo un div con id="a"que puede tener cualquier cantidad de clases adjuntas, de varios grupos. Cada grupo tiene un prefijo específico. En javascript, no sé qué clase del grupo está en el div. Quiero poder borrar todas las clases con un prefijo dado y luego agregar una nueva. Si quiero eliminar todas las clases que comienzan con "bg", ¿cómo lo hago? Algo como esto, pero que realmente funciona:

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

Respuestas:

59

Con jQuery, el elemento DOM real está en el índice cero, esto debería funcionar

$('#a')[0].className = $('#a')[0].className.replace(/\bbg.*?\b/g, '');
Palmadita
fuente
34
Cuidado con este. El límite de la palabra se divide en el carácter de guión ('-') y los puntos y otros, por lo que los nombres de clases como "bg.a", "bg-a", etc. no se eliminarán, sino que se reemplazarán con ".a", "-a", etc. Por lo tanto, si tiene nombres de clases con caracteres de puntuación, puede tener problemas simplemente ejecutando un simple reemplazo de expresiones regulares. Aquí hay un hilo SO sobre la definición de límites de palabras
Jakub P.
6
La respuesta de Kabir Sarin a continuación con split ('') e indexOf es mejor en mi opinión porque no hará que aparezcan esas clases de "zombies" con caracteres especiales.
Jakub P.
2
Este método aún se puede usar con una mejor expresión regular, como la que se encuentra aquí: stackoverflow.com/a/2644364/1333402
ssmith
109

Una expresión regular dividida en el límite de la palabra \bno es la mejor solución para esto:

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

o como una mezcla de 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;
};

Actualización de 2018 ES6:

const prefix = "prefix";
const classes = el.className.split(" ").filter(c => !c.startsWith(prefix));
el.className = classes.join(" ").trim();
sarink
fuente
9
Este es un mejor enfoque que usar RegExp con \ b (verificación de límites de palabras) porque evita que aparezcan 'clases zombies'. Si tiene clases como "prefijo-sufijo", la 'mejor respuesta' en este hilo dejará la clase '-sufijo' porque \ b se dividirá antes de '-' char. Su solución split-map-join funciona en torno a eso :) Creé un pequeño complemento jQuery alrededor de su solución, Kabir: ( gist.github.com/2881585 )
Jakub P.
3
+1 También estoy de acuerdo, todas las demás respuestas parecen ser simplemente una expresión regular simple que se rompería en los límites de palabras sin espacio. Si tengo tiempo mañana, proporcionaré una prueba unitaria que lo demuestre.
Gerges
1
Me gusta, aunque esto en realidad no es un código válido, ya que la función anónima filterdebe devolver un booleano. Esto funcionará: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 solución más válida usa el mapa:$e.attr('class', $.map($e.attr('class').split(' '), function (klass) { return klass.indexOf(prefix) != 0 ? klass : undefined; }).join(' '));
M Miller
2
Este enfoque funciona mejor. Usé el complemento de @ JakubP. Una sugerencia, si se me permite: lo que hace, cuando ahora devuelve las clases, genera mucho espacio. Por ejemplo class="blackRow blackText orangeFace blackHead", volverá class=" orangeFace "si corre removeClassPrefix("black");. He resuelto este recortando el resultado de este modo: el.className = $.trim(classes.join(" "));.
Albert
29

Escribí un complemento jQuery simple : alterClass , que elimina la clase comodín. Opcionalmente también agregará clases.

$( '#foo' ).alterClass( 'foo-* bar-*', 'foobar' ) 
Pete B
fuente
¡Gracias Pete! Acabo de usar su complemento y funciona muy bien ... ¡me ahorró algo de tiempo!
jordan.baucke
11

No necesita ningún código específico de jQuery para manejar esto. Simplemente use una expresión regular para reemplazarlos:

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

Puede modificar esto para admitir cualquier prefijo, pero el método más rápido está arriba, ya que la expresión regular se compilará solo una vez:

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

Usando la segunda firma 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
fuente
Desde jQuery v1.4, este es el mejor enfoque.
Dinei
3

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

... y .removeClass () eliminaría todas las clases ...

Esto funciona para mi ;)

salud


fuente
¡Esta es una mejor opción! Trabajos.
Afshin Mehrabani
12
La pregunta no pregunta cómo eliminar todas las clases, sino cómo eliminar todas las clases que comienzan con una determinada cadena. Estas dos cosas son muy, muy diferentes.
Chris Harrison
3

Un enfoque que usaría usando construcciones jQuery simples y funciones de manejo de matrices, es declarar una función que toma la identificación del control y el prefijo de la clase y borra todas las clasificadas. Se adjunta el código:

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

Ahora, esta función se puede llamar desde cualquier lugar, al hacer clic en el botón o desde el código:

removeclasses("a","bg");
nhahtdh
fuente
2

Estaba buscando una solución para exactamente el mismo problema. Para eliminar todas las clases que comienzan con el prefijo "fontid_" Después de leer este artículo, escribí un pequeño complemento que estoy usando ahora.

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

Uso:

$('#elementId').removePrefixedClasses('prefix-of-classes_');
Pawel
fuente
Esto no es más que mi solución con 10 veces más líneas y una "cadena comienza con" menos eficiente comprobar: - /
sarink
2

Para navegadores modernos:

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

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

Sé que es una pregunta antigua, pero encontré una nueva solución y quiero saber si tiene desventajas.

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

En una línea ... Elimina todas las clases que coinciden con una expresión regular someRegExp

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

La respuesta de Prestaul fue útil, pero no funcionó para mí. La forma jQuery de seleccionar un objeto por id no funcionó. Tuve que usar

document.getElementById("a").className

en vez de

$("#a").className
Puntilla
fuente
o $ ("# a") [0] .className como className solo está disponible en el elemento DOM y no en el objeto jQuery
Naeem Sarfraz
este es un comentario para la respuesta de alguien, no una respuesta
TJ
0

También utilizo guiones'- 'y dígitos para el nombre de la clase. Entonces mi versión incluye '\ d-'

$('#a')[0].className = $('#a')[0].className.replace(/\bbg.\d-*?\b/g, '');
Jamland
fuente
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);
Robar
fuente
-6
$("#element").removeAttr("class").addClass("yourClass");
majorsk8
fuente
3
No creo que hayas leído muy bien la pregunta. El usuario no preguntaba simplemente por eliminar una clase y agregar otra.
Andrew Barber
1
@Andrew Barber: tienes razón, esta no es la respuesta correcta, pero majorsk8 sugirió cómo borrar todas las clases (removeAttr), no solo una;)
Tilt