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

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

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

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


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

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

Desde jQuery v1.4, este es el mejor enfoque.
Dinei


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

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

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

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

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

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

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

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
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
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.