Usando o seletor 'começa com' em nomes de classe individuais

158

Se eu tiver o seguinte:

<div class="apple-monkey"></div>
<div class="apple-horse"></div>
<div class="cow-apple-brick"></div>

Posso usar o seguinte seletor para encontrar os dois primeiros DIVs:

$("div[class^='apple-']")

No entanto, se eu tiver isso:

<div class="some-other-class apple-monkey"></div>
<div class="apple-horse"></div>
<div class="cow-apple-brick"></div>

Ele só encontrará o segundo DIV, já que a classe da primeira div é retornada como uma string (acho) e, na verdade, não começa com 'apple-', mas sim 'some-'

Uma maneira de contornar isso é não usar, começa com, mas contém:

$("div[class*='apple-']")

O problema é que ele também selecionará o 3º DIV no meu exemplo.

Pergunta: Por jQuery, qual é a maneira correta de usar seletores de predicado em nomes de classes individuais, em vez de todo o atributo de classe como uma string? É apenas uma questão de pegar a CLASS, dividi-la em uma matriz e, em seguida, percorrer cada uma com regex? Ou existe uma solução mais elegante / menos detalhada?

DA.
fonte

Respostas:

304

Classes que começam com "apple-" mais classes que contêm "apple-"

$("div[class^='apple-'],div[class*=' apple-']")
Josh Stodola
fonte
5
+1. Embora eu concorde com a sugestão dos @parrots de que "apple" deva ser sua própria classe aqui, pois obviamente se sobrepõe a vários divs, ainda assim é uma entidade distinta. Mas isso resolve o problema.
jvenema
Hmm ... esperto! Eu não tinha pensado em usar espaço lá. Pode-se usar operadores booleanos em um seletor de jquery? Idealmente, o acima seria 'OR' para evitar o caso (raro e provavelmente evitável) em que há mais de uma classe observando 'apple-'
DA.
Não sei se entendi, mas se você quiser usar o segundo seletor apenas quando o primeiro seletor retornar zero elementos, poderá fazer algo assim: var divs = $("div[class^='apple-']"); if(divs.length == 0) divs = $("div[class*=' apple-']");
Josh Stodola
agora que penso nisso, sua solução inicial funciona perfeitamente. Um DIV que tivesse uma classe como "apple-brick apple-horse" ainda seria selecionado apenas uma vez no objeto jQuery.
DA.
usar * em vez de div se você não delimitadora classe para o elemento específico :)
Hidayt Rahman
13

Eu recomendo fazer "apple" sua própria classe. Você deve evitar o início com / termina com, se puder, porque ser capaz de selecionar usando div.appleseria muito mais rápido. Essa é a solução mais elegante. Não tenha medo de dividir as coisas em classes separadas, se isso tornar a tarefa mais simples / rápida.

Papagaios
fonte
Como você acha que seria muito mais rápido? Ele ainda precisa varrer o DOM inteiro e avaliar o atributo da classe. Seria marginalmente mais rápido (na melhor das hipóteses) porque não teria que substring o atributo de classe. Insignificante.
Josh Stodola
2
componenthouse.com/article-19 : se você olhar na seção obter por classe, o uso da sintaxe de ponto comum é geralmente um pouco mais rápido do que tratar a classe como um atributo. Adicione a pesquisa de substring (e o trabalho adicional que ele terá que fazer para separar elementos com vários nomes de classe) e isso resultará em uma economia decente de desempenho.
Papagaios
1
Concordo. O problema é que ainda apoiamos fortemente o IE6 e ele não suporta seletores compostos em CSS: .class1.class2.class3, como tal, estamos contando com o uso de nomes de classe mais longos, onde 'parâmetros' são divididos por traços.
DA.
6

isto é para prefixo com

$("div[class^='apple-']")

isso é para começar, então você não precisa ter o '-' char lá

$("div[class|='apple']")

você pode encontrar várias outras variações interessantes do seletor jQuery aqui https://api.jquery.com/category/selectors/

Mexicoder
fonte
6

Embora a resposta principal aqui seja uma solução alternativa para o caso específico do solicitante, se você estiver procurando uma solução para realmente usar 'começa com' em nomes de classes individuais:

Você pode usar esse seletor jQuery personalizado, que chamo :acp()de "Um prefixo de classe". O código está na parte inferior desta postagem.

var test = $('div:acp("starting_text")');

Isso selecionará todos e quaisquer <div>elementos que tenham pelo menos um nome de classe começando com a sequência especificada ("texto_de_inicialização" neste exemplo), independentemente de essa classe estar no início ou em outro lugar nas sequências de atributos da classe.

<div id="1" class="apple orange lemon" />
<div id="2" class="orange applelemon banana" />
<div id="3" class="orange lemon apple" />
<div id="4" class="lemon orangeapple" />
<div id="5" class="lemon orange" />

var startsWithapp = $('div:acp("app")');

Isso retornará os elementos 1, 2 e 3, mas não 4 ou 5.

Aqui está a declaração do :acpseletor personalizado, que você pode colocar em qualquer lugar:

$(function(){
    $.expr[":"].acp = function(elem, index, m){
          var regString = '\\b' + m[3];
          var reg = new RegExp(regString, "g");
          return elem.className.match(reg);
    }
});

Fiz isso porque faço muitos hackers no GreaseMonkey de sites nos quais não tenho controle de back-end; portanto, muitas vezes preciso encontrar elementos com nomes de classes que tenham sufixos dinâmicos. Tem sido muito útil.

equação
fonte
2

Tente o seguinte:

$("div[class]").filter(function() {
    var classNames = this.className.split(/\s+/);
    for (var i=0; i<classNames.length; ++i) {
        if (classNames[i].substr(0, 6) === "apple-") {
            return true;
        }
    }
    return false;
})
quiabo
fonte
2
<div class="apple-monkey"></div>
<div class="apple-horse"></div>
<div class="cow-apple-brick"></div>

nesse caso, como a resposta de Josh Stodola da pergunta está correta Classes que começam com "apple-" mais classes que contêm "apple-"

$("div[class^='apple-'],div[class*=' apple-']")

mas se o elemento tiver várias classes como esta

<div class="some-class apple-monkey"></div>
<div class="some-class apple-horse"></div>
<div class="some-class cow-apple-brick"></div>

então a solução de Josh Stodola não funcionará,
pois isso tem que fazer algo assim

$('.some-parent-class div').filter(function () {
  return this.className.match(/\bapple-/);// this is for start with
  //return this.className.match(/apple-/g);// this is for contain selector
}).css("color","red");

pode ser que ajuda alguém mais graças

code.rider
fonte
0

Se um elemento tiver múltiplas classes "[class ^ = 'apple-']" não funcionará, por exemplo,

<div class="fruits apple-monkey"></div>
Ramón Mtz
fonte
O OP menciona isso na pergunta.
Ganso