Remova todas as classes que começam com uma certa string


99

Eu tenho um div com id="a"que pode ter qualquer número de classes anexadas a ele, de vários grupos. Cada grupo possui um prefixo específico. No javascript, não sei qual turma do grupo está no div. Quero ser capaz de limpar todas as classes com um determinado prefixo e, em seguida, adicionar um novo. Se eu quiser remover todas as classes que começam com "bg", como faço isso? Algo assim, mas realmente funciona:

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

Respostas:


59

Com jQuery, o elemento DOM real está no índice zero, isso deve funcionar

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

34
Cuidado com este. O limite da palavra se divide no caractere de traço ('-') e pontos e outros, de modo que nomes de classe como "bg.a", "bg-a" etc. não serão removidos, mas substituídos por ".a", "-a" etc. Portanto, se você tiver nomes de classe com caracteres de pontuação, poderá ter problemas apenas executando uma substituição simples de regex. Aqui está um tópico do SO sobre definição de limite de palavras
Jakub P.

6
A resposta de Kabir Sarin abaixo com split ('') e indexOf é melhor IMO porque não fará com que essas classes "zumbis" com caracteres especiais apareçam.
Jakub P.

2
Esse método ainda pode ser usado com um regex melhor, como o encontrado aqui: stackoverflow.com/a/2644364/1333402
ssmith

109

Uma divisão regex no limite de palavra \bnão é a melhor solução para isso:

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

ou como um 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;
};

Atualização ES6 2018:

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

9
Esta é uma abordagem melhor do que usar RegExp com \ b (verificação de limite de palavra) porque evita que 'classes zumbis' apareçam. Se você tem classes como "prefixo-sufixo", a 'melhor resposta' neste tópico deixará a classe '-sufixo' porque \ b será dividido antes de '-' char. Sua solução de divisão-mapa-junção funciona em torno disso :) Eu criei um pequeno plugin jQuery em torno de sua solução, Kabir: ( gist.github.com/2881585 )
Jakub P.

3
+1 Eu também concordo, todas as outras respostas parecem ser apenas uma regex simples que quebraria em limites de palavra não espaciais. Se eu tiver tempo amanhã, vou fornecer um teste de unidade que prova isso.
gerges

1
Eu gosto, embora este não seja um código válido, já que a função anônima em filterdeve retornar um booleano. Isso 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

Uma solução mais válida usa o mapa:$e.attr('class', $.map($e.attr('class').split(' '), function (klass) { return klass.indexOf(prefix) != 0 ? klass : undefined; }).join(' '));
M Miller

2
Essa abordagem funciona melhor. Eu usei o plugin do @JakubP. Uma sugestão se me permite: o que faz, quando agora retorna as classes, causa muito espaço. Por exemplo class="blackRow blackText orangeFace blackHead", retornará class=" orangeFace "se você executar removeClassPrefix("black");. Eu resolvi esse aparando o resultado assim: el.className = $.trim(classes.join(" "));.
Albert

29

Eu escrevi um plugin jQuery simples - alterClass , que remove a classe curinga. Opcionalmente, adicionará classes também.

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

Obrigado Pete! Acabei de usar seu plugin e funciona muito bem ... me economizou algum tempo!
jordan.baucke

11

Você não precisa de nenhum código específico do jQuery para lidar com isso. Basta usar um RegExp para substituí-los:

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

Você pode modificar isso para suportar qualquer prefixo, mas o método mais rápido está acima, pois o RegExp será compilado apenas uma vez:

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

9

Usando a 2ª assinatura 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, esta é a melhor abordagem.
Dinei,


3

Uma abordagem que eu usaria usando construções jQuery simples e funções de manipulação de array é declarar uma função que leva id do controle e prefixo da classe e excluiu todas as classes. O código está anexado:

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

Agora, esta função pode ser chamada de qualquer lugar, ao clicar no botão ou a partir do código:

removeclasses("a","bg");

2

Eu estava procurando uma solução exatamente para o mesmo problema. Para remover todas as classes começando com o prefixo "fontid_" Depois de ler este artigo, escrevi um pequeno plugin que estou usando agora.

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

Isso nada mais é do que minha solução com 10x mais linhas e uma "string começa com" menos eficiente, verifique: - /
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

Sei que é uma pergunta antiga, mas descobri uma nova solução e quero saber se ela tem desvantagens?

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

1

Em uma linha ... Remove todas as classes que correspondem a uma expressão regular someRegExp

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

0

A resposta de Prestaul foi útil, mas não funcionou muito bem para mim. A maneira jQuery de selecionar um objeto por id não funcionou. Eu tive que usar

document.getElementById("a").className

ao invés de

$("#a").className

ou $ ("# a") [0] .className as className está disponível apenas no elemento DOM e não no objeto jQuery
Naeem Sarfraz

este é um comentário para a resposta de alguém, não uma resposta
TJ

0

Eu também uso hífen'- 'e dígitos para o nome da classe. Portanto, minha versão inclui '\ 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
Eu não acho que você leu a pergunta muito bem. O usuário não estava perguntando sobre simplesmente remover uma classe e adicionar outra.
Andrew Barber

1
@Andrew Barber: você está certo, essa não é a resposta certa, mas majorsk8 sugeriu como limpar todas as classes (removeAttr), não apenas uma;)
Inclinação
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.