curinga jQuery removeClass


370

Existe alguma maneira fácil de remover todas as classes correspondentes, por exemplo,

color-*

então se eu tiver um elemento:

<div id="hello" class="color-red color-brown foo bar"></div>

após a remoção, seria

<div id="hello" class="foo bar"></div>

Obrigado!


11
Uma regex como na "resposta aceita" será quebrada nos limites de palavras que não são espaços. Publiquei uma solução alternativa abaixo. Consulte também: stackoverflow.com/questions/57812/…
sarink

@KabirSarin, a resposta aceita foi atualizada para corrigir isso.
Emile Bergeron

Respostas:


679

A função removeClass usa um argumento de função desde o jQuery 1.4 .

$("#hello").removeClass (function (index, className) {
    return (className.match (/(^|\s)color-\S+/g) || []).join(' ');
});

Exemplo ao vivo: http://jsfiddle.net/xa9xS/1409/


4
Eu pensei que vale a pena notar que isso irá capturar um espaço em branco líder de classes correspondentes que não começam no início. O Javascript não oferece suporte positivo, portanto você teria que usar uma solução alternativa para o grupo de captura. No entanto, é discutível, porque a função removeClass retira o espaço em branco da string de classe para você viaclasses = ( value || "" ).match( rnotwhite ) || [];
eephillip

Eu gosto mais desta solução! Como posso verificar se duas ou mais classes serão removidas? ou seja sport-, nav-e color-?
lowtechsun

Como você faria isso para combinar com um final de classe como *-color?
Circle B

3
@lowtechsun, você pode adicionar seu regex assim (color-|sport-|nav-). Combina color-, ou sport-, ou nav-. Então, a resposta acima se tornaria /(^|\s)(color-|sport-|nav-)\S+/g.
Bogie

11
A resposta aceita está correta, mas, em termos linguísticos, eu usaria \ b, que corresponde a qualquer limite de palavras, e não ao mais prolixo (^ | \ s). Assim, por exemplo, para remover todas as classes que consistem na palavra mágica, seguidas por um número inteiro não negativo e somente aquelas, eu corresponderia em / \ bmagic \ d + \ b /.
CarlEdman

98
$('div').attr('class', function(i, c){
    return c.replace(/(^|\s)color-\S+/g, '');
});

5
Eu gosto disso, pois reduz a sobrecarga e vai direto ao ponto. Por que usar remove class quando attr faz o trabalho melhor?
Angry Dan

2
Eu acho que você precisa se proteger contra classes vazias ( c is undefined)? Pelo menos quando eu tentei seguir no meu plugin nesta página, $('a').stripClass('post', 1)jogou "TypeError: Não é possível chamar o método 'substituir' de indefinido"
drzaus

11
@ Kobi Sim, eu não acho que é possível filtrar um atributo e retornar um resultado que não o possui - $('div[class]')só deve retornar elementos com class, se eles têm um valor ou não. testando cenários: jsfiddle.net/drzaus/m83mv
drzaus

11
@Kobi - Acho que vejo o que você está recebendo; nos casos extremos como .removeProp('class')ou .className=undefinedo filtro [class]ainda retorna algo, eles são justos undefined. Então, tecnicamente ele ainda tem uma classe (em oposição a .removeAttr('class'), razão pela qual ele quebra sua função, mas não a minha variante. Jsfiddle.net/drzaus/m83mv/4
drzaus

11
A adição de um teste rápido funciona para mim:return c && c.replace(/\bcolor-\S+/g, '');
ssmith

50

Eu escrevi um plugin que faz isso chamado alterClass - Remove classes de elemento com correspondência de curinga. Opcionalmente, adicione classes: https://gist.github.com/1517285

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

11
Muito bom de facto ... me ajudou a reutilizar algum código onde eu só precisava para remover Twitter Boostrapas classes como este:$(".search div").children('div').alterClass('span* row-fluid');
Leniel Maccaferri

15

Eu generalizei isso em um plugin Jquery que usa uma expressão regular como argumento.

Café:

$.fn.removeClassRegex = (regex) ->
  $(@).removeClass (index, classes) ->
    classes.split(/\s+/).filter (c) ->
      regex.test c
    .join ' '

Javascript:

$.fn.removeClassRegex = function(regex) {
  return $(this).removeClass(function(index, classes) {
    return classes.split(/\s+/).filter(function(c) {
      return regex.test(c);
    }).join(' ');
  });
};

Portanto, nesse caso, o uso seria (Coffee e Javascript):

$('#hello').removeClassRegex(/^color-/)

Observe que estou usando a Array.filterfunção que não existe no IE <9. Você poderia usar a função de filtro do Underscore ou o Google para um polyfill como este WTFPL .


11

Se você quiser usá-lo em outros lugares, sugiro uma extensão. Este está funcionando bem para mim.

 $.fn.removeClassStartingWith = function (filter) {
    $(this).removeClass(function (index, className) {
        return (className.match(new RegExp("\\S*" + filter + "\\S*", 'g')) || []).join(' ')
    });
    return this;
};

Uso:

$(".myClass").removeClassStartingWith('color');

4

podemos obter todas as classes por .attr("class"), e para Array, And loop & filter:

var classArr = $("#sample").attr("class").split(" ")
$("#sample").attr("class", "")
for(var i = 0; i < classArr.length; i ++) {
    // some condition/filter
    if(classArr[i].substr(0, 5) != "color") {
        $("#sample").addClass(classArr[i]);
    }
}

demo: http://jsfiddle.net/L2A27/1/


Adicionado var prefix='color';e alterado ...if (classArr[i].substr(0, prefix.length) != prefix)
Rich C

4

Semelhante à resposta de @ tremby , aqui está a resposta de @ Kobi como um plug-in que corresponderá a prefixos ou sufixos.

  • ex) tiras btn-minie btn-dangermas não btnquando stripClass("btn-").
  • ex) tiras horsebtne cowbtnmas não btn-miniou btnquandostripClass('btn', 1)

Código:

$.fn.stripClass = function (partialMatch, endOrBegin) {
    /// <summary>
    /// The way removeClass should have been implemented -- accepts a partialMatch (like "btn-") to search on and remove
    /// </summary>
    /// <param name="partialMatch">the class partial to match against, like "btn-" to match "btn-danger btn-active" but not "btn"</param>
    /// <param name="endOrBegin">omit for beginning match; provide a 'truthy' value to only find classes ending with match</param>
    /// <returns type=""></returns>
    var x = new RegExp((!endOrBegin ? "\\b" : "\\S+") + partialMatch + "\\S*", 'g');

    // https://stackoverflow.com/a/2644364/1037948
    this.attr('class', function (i, c) {
        if (!c) return; // protect against no class
        return c.replace(x, '');
    });
    return this;
};

https://gist.github.com/zaus/6734731


11
Para constar, discordo que isso é mais simples.
tremby 30/07

@tremby desculpe, eu quis dizer mais simples em típico de uso (ou seja, prefixos e sufixos), desde que você não tem que escrever um regex de cada vez
drzaus

3
Eu ainda discordo. Com o seu método, você deve ler a documentação e lembrar qual endOrBegindeve ser exatamente o valor . Não é auto-explicativo. O que é difícil escrever um regex? /^match-at-start/e /match-at-end$/são conhecidos por todo desenvolvedor JS. Mas cada um por conta própria.
21814 tremby

11
@tremby diferente de expressões regulares implorando para ser abusado, uma opção não-regex corresponda melhor a assinatura existente addClass, removeClasse toggleClass, o que é conhecido por todos os desenvolvedores jQuery. O que é difícil de ler na documentação? ;)
drzaus

2
Não é difícil ler a documentação, mas como o @tremby diz, a solução dele é auto-explicativa, enquanto a sua requer documentação. Soluções auto-explicativas são mais simples de usar por definição.
Francisco Hodge

2

Para um plugin jQuery, tente este

$.fn.removeClassLike = function(name) {
    return this.removeClass(function(index, css) {
        return (css.match(new RegExp('\\b(' + name + '\\S*)\\b', 'g')) || []).join(' ');
    });
};

ou isto

$.fn.removeClassLike = function(name) {
    var classes = this.attr('class');
    if (classes) {
        classes = classes.replace(new RegExp('\\b' + name + '\\S*\\s?', 'g'), '').trim();
        classes ? this.attr('class', classes) : this.removeAttr('class');
    }
    return this;
};

2

Baseado em ARS81 's resposta (que corresponde apenas nomes de classe começando com), aqui está uma versão mais flexível. Também uma hasClass()versão regex.

Uso: $('.selector').removeClassRegex('\\S*-foo[0-9]+')

$.fn.removeClassRegex = function(name) {
  return this.removeClass(function(index, css) {
    return (css.match(new RegExp('\\b(' + name + ')\\b', 'g')) || []).join(' ');
  });
};

$.fn.hasClassRegex = function(name) {
  return this.attr('class').match(new RegExp('\\b(' + name + ')\\b', 'g')) !== null;
};

2

Isso removerá efetivamente todos os nomes de classe que começam com prefixo classatributo de um nó . Outras respostas não suportam elementos SVG (no momento em que escrevemos isso), mas esta solução:

$.fn.removeClassPrefix = function(prefix){
    var c, regex = new RegExp("(^|\\s)" + prefix + "\\S+", 'g');
    return this.each(function(){
        c = this.getAttribute('class');
        this.setAttribute('class', c.replace(regex, ''));
    });
};

Não seria mais eficiente criar o RegExpobjeto uma vez, a partir de cada retorno de chamada?
Emile Bergeron

11
@EmileBergeron - sim, seria! Vou fazer alterações
vsync

2

Eu tive o mesmo problema e criei o seguinte que usa o método _.filter do sublinhado. Depois que descobri que removeClass usa uma função e fornece uma lista de nomes de classe, foi fácil transformá-lo em uma matriz e filtrar o nome da classe para retornar ao método removeClass.

// Wildcard removeClass on 'color-*'
$('[class^="color-"]').removeClass (function (index, classes) {
  var
    classesArray = classes.split(' '),
    removeClass = _.filter(classesArray, function(className){ return className.indexOf('color-') === 0; }).toString();

  return removeClass;
});

11
Pode explicar o que o sublinhado faz em _.filter
Bart

2

Você também pode fazer isso com JavaScript vanilla usando Element.classList . Também não é necessário usar uma expressão regular:

function removeColorClasses(element) { for (let className of Array.from(element.classList)) if (className.startsWith("color-")) element.classList.remove(className); }

Nota: Observe que criamos uma Arraycópia do classListantes de iniciar, o que é importante, pois classListé um live DomTokenListque será atualizado à medida que as classes forem removidas.


1

Você também pode usar a classNamepropriedade do objeto DOM do elemento:

var $hello = $('#hello');
$('#hello').attr('class', $hello.get(0).className.replace(/\bcolor-\S+/g, ''));

1

Uma função genérica que remove qualquer classe que comece com begin:

function removeClassStartingWith(node, begin) {
    node.removeClass (function (index, className) {
        return (className.match ( new RegExp("\\b"+begin+"\\S+", "g") ) || []).join(' ');
    });
}

http://jsfiddle.net/xa9xS/2900/

var begin = 'color-';

function removeClassStartingWith(node, begin) {
    node.removeClass (function (index, className) {
        return (className.match ( new RegExp("\\b"+begin+"\\S+", "g") ) || []).join(' ');
    });
}

removeClassStartingWith($('#hello'), 'color-');

console.log($("#hello")[0].className);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="hello" class="color-red color-brown foo bar"></div>


0

Uma regex dividida no limite da 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(" ");

ou como um mix 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 = classes.join(" ");
    });
    return this;
};

0

se você tiver mais de um elemento com um nome de classe 'exemplo', para remover classes de 'cor-' em todas elas, você pode fazer isso: [using jquery]

var objs = $('html').find('.example');
for(index=0 ; index < obj1s.length ; index++){
    objs[index].className = objs[index].className.replace(/col-[a-z1-9\-]*/,'');
}

se você não colocar [a-z1-9 -] * no seu regex, não removerá as classes que têm um número ou algum '-' em seus nomes.


0

Se você apenas precisar remover a última cor definida, o seguinte poderá lhe agradar.

Na minha situação, eu precisava adicionar uma classe de cores à tag body em um evento de clique e remover a última cor definida. Nesse caso, você armazena a cor atual e procura a etiqueta de dados para remover a última cor definida.

Código:

var colorID = 'Whatever your new color is';

var bodyTag = $('body');
var prevColor = bodyTag.data('currentColor'); // get current color
bodyTag.removeClass(prevColor);
bodyTag.addClass(colorID);
bodyTag.data('currentColor',colorID); // set the new color as current

Pode não ser exatamente o que você precisa, mas para mim foi e essa foi a primeira pergunta do SO que eu olhei, então pensei em compartilhar minha solução caso isso ajude alguém.


Isso é irrelevante aqui. Você poderia ter respondido sua própria pergunta, pois é um comportamento incentivado no SO.
Emile Bergeron

@Emile: Isso é verdade. Eu poderia fazer isso, pois não está respondendo diretamente à pergunta original. Devo deixar essa resposta ou removê-la?
precisa saber é o seguinte

Nesse ponto, é por seu próprio risco, não foi votado nem votado ainda. Então você pode passar para sua própria pergunta sem risco. Além disso, tente evitar duplicatas verificando se já existe uma pergunta sobre isso.
Emile Bergeron

0

Uma maneira alternativa de abordar esse problema é usar atributos de dados, que são por natureza exclusivos.

Você definiria a cor de um elemento como: $el.attr('data-color', 'red');

E você o estilizaria em css como: [data-color="red"]{ color: tomato; }

Isso nega a necessidade de usar classes, que tem o efeito colateral de precisar remover classes antigas.

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.