Usar el selector 'comienza con' en los nombres de clase individuales

158

Si tengo lo siguiente:

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

Puedo usar el siguiente selector para encontrar los dos primeros DIV:

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

Sin embargo, si tengo esto:

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

Solo encontrará el segundo DIV, ya que la clase del primer div se devuelve como una cadena (creo) y en realidad no comienza con 'apple-' sino más bien 'some-'

Una forma de evitar esto es no usar comienza con, sino que contiene:

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

El problema con eso es que también seleccionará el 3er DIV en mi ejemplo.

Pregunta: A través de jQuery, ¿cuál es la forma correcta de usar selectores de predicados en nombres de clase individuales, en lugar de todo el atributo de clase como una cadena? ¿Es solo una cuestión de agarrar la CLASE, luego dividirla en una matriz y luego recorrer cada una individualmente con expresiones regulares? ¿O hay una solución más elegante / menos detallada?

DA.
fuente

Respuestas:

304

Clases que comienzan con "apple-" más clases que contienen "apple-"

$("div[class^='apple-'],div[class*=' apple-']")
Josh Stodola
fuente
55
+1. Aunque estoy de acuerdo con la sugerencia de @parrots de que "apple" debería ser su propia clase aquí, ya que obviamente se superpone a múltiples divs, pero es una entidad distinta. Pero esto resuelve el problema.
jvenema 01 de
Hmm ... ¡listo! No había pensado en usar el espacio allí. ¿Se pueden usar operadores booleanos en un selector jquery? Idealmente, lo anterior sería 'OR' para evitar el caso (raro y probablemente evitable) en el que hay más de una clase mirando con 'apple-'
DA.
No estoy seguro de entender, pero si solo quieres usar el segundo selector cuando el primer selector devuelve cero elementos, puedes hacer algo como esto: var divs = $("div[class^='apple-']"); if(divs.length == 0) divs = $("div[class*=' apple-']");
Josh Stodola
Ahora que lo pienso, su solución inicial funciona bien. Una DIV que tenía una clase como "apple-brick apple-horse" aún se seleccionaría una vez en el objeto jQuery.
DA.
use * en lugar de div si no limita la clase para un elemento específico :)
Hidayt Rahman
13

Recomiendo hacer de "apple" su propia clase. Debería evitar los comienzos con / termina con si puede porque poder seleccionar usando div.applesería mucho más rápido. Esa es la solución más elegante. No tenga miedo de dividir las cosas en clases separadas si hace que la tarea sea más simple / rápida.

Loros
fuente
¿Cómo crees que sería mucho más rápido? Todavía tiene que escanear todo el DOM y evaluar el atributo de clase. Sería marginalmente más rápido (en el mejor de los casos) porque no tendría que subcadenar el atributo de clase. Despreciable.
Josh Stodola
2
componenthouse.com/article-19 : si mira en la sección obtener por clase, el uso de la sintaxis de puntos normal suele ser un poco más rápido que tratar la clase como un atributo. Agregue la búsqueda de subcadenas (y el trabajo adicional que tendrá que hacer para separar los elementos con varios nombres de clase) y se sumarán a un ahorro decente en el rendimiento.
Loros
1
Estoy de acuerdo. El problema es que todavía admitimos IE6 y no admite selectores compuestos en CSS: .class1.class2.class3 como tal, confiamos en usar nombres de clase más largos donde los 'parámetros' están divididos por guiones.
DA.
6

esto es para prefijo con

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

esto es para empezar, así que no necesitas tener el caracter '-' ahí

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

Puede encontrar muchas otras variaciones interesantes del selector jQuery aquí https://api.jquery.com/category/selectors/

Mexicanista
fuente
6

Si bien la respuesta principal aquí es una solución para el caso particular del autor de la pregunta, si está buscando una solución para usar realmente 'comienza con' en nombres de clase individuales:

Puede usar este selector jQuery personalizado, al que llamo :acp()"A Class Prefix". El código está al final de esta publicación.

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

Esto seleccionará todos y cada uno de los <div>elementos que tengan al menos un nombre de clase que comience con la cadena dada ("texto_inicio" en este ejemplo), independientemente de si esa clase está al principio o en otra parte de las cadenas de atributos de clase.

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

Esto devolverá los elementos 1, 2 y 3, pero no 4 o 5.

Aquí está la declaración para el :acpselector personalizado, que puede poner en cualquier lugar:

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

Hice esto porque hago un montón de pirateo de sitios web de GreaseMonkey en los que no tengo control de back-end, por lo que a menudo necesito encontrar elementos con nombres de clase que tengan sufijos dinámicos. Ha sido muy útil

equazcion
fuente
2

Prueba esto:

$("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;
})
Gumbo
fuente
2
<div class="apple-monkey"></div>
<div class="apple-horse"></div>
<div class="cow-apple-brick"></div>

en este caso, la pregunta de Josh Stodola es correcta Clases que comienzan con "apple-" más clases que contienen "apple-"

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

pero si el elemento tiene múltiples clases como esta

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

entonces la solución de Josh Stodola no funcionará
porque esto tiene que hacer algo como esto

$('.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");

puede ser que ayuda a alguien más gracias

code.rider
fuente
0

Si un elemento tiene múltiples clases "[class ^ = 'apple-']" no funcionan, por ejemplo

<div class="fruits apple-monkey"></div>
Ramón Mtz
fuente
El OP menciona esto en la pregunta.
Ganso