2011-12-20 26 views
12

¿Cuál sería la mejor forma de obtener todos los divs que tengan cualquier clase que comience con input? En otras palabras, a y b deben devolverse de lo que está debajo, pero no c.jQuery - tiene clase que comienza con

<div id="a" class="input1 foo"></div> 
<div id="b" class="foo input2"></div> 
<div id="c" class="xinput3 foo"></div> 

La forma ostensible, que sorprendentemente fue aceptado here, es hacer $("div[class^='input']"); pero por supuesto que pierde b. Y, por supuesto, $("div[class*='input']"); dará un falso positivo en c.

Lo mejor que pude llegar a este engendro fue

function getAllInputDivs() { 
    return $("div").filter(function (i, currentDiv) { 
     return $.grep($(currentDiv).attr("class").split(" "), function (val) { 
      return val.substr(0, "input".length) === "input"; 
     }).length > 0; 
    }); 
} 

¿Hay una manera más limpia? Esto es un working fiddle de lo anterior

+0

No creo que los nombres de clase sean la mejor opción cuando se tienen cosas como input1 y input2. Si la entrada es lo suficientemente única para ser enumerada de esa manera, puede usar identificadores o nombres que se pueden seleccionar con '$ (" [id^= entrada] ")' –

+0

@KevinB - probablemente tenga razón. No estoy seguro de si hay un buen caso de uso para esto o no. En este momento es solo una pregunta teórica para ver si se puede hacer. –

+0

Pregunta similar: [jQuery selector para apuntar a cualquier nombre de clase (de presente múltiple) comenzando con un prefijo?] (Http://stackoverflow.com/questions/4524412/jquery-selector-to-target-any-css-name- of-multiple-present-starting-with-a-pre) pero no he hecho expresiones de selector personalizadas antes, así que me gustan bastante las respuestas a esta pregunta :) – BoltClock

Respuesta

22

Usted puede crear su propia expresión en jQuery

$.expr[':'].hasClassStartingWithInput = function(obj){ 
    return (/\binput/).test(obj.className); 
}; 

y puede recuperar esos div con

$('div:hasClassStartingWithInput'); 

un ejemplo jsFiddle: http://jsfiddle.net/7zFD6/


Editar: también podría usar un parámetro (sin dificultad codificar el nombre de la clase en el interior del identificador de función) de esta manera

$.expr[':'].hasClassStartingWith = function(el, i, selector) { 
    var re = new RegExp("\\b" + selector[3]); 
    return re.test(el.className); 
} 

nuevo ejemplo de http://jsfiddle.net/pMepk/1/

+1

¿No debería ese '\ b' ser un'^'en su lugar? – Blazemonger

+0

no, no lo hace. el '^' verificará solo si una clase que comienza con la entrada también es la primera clase enumerada en el atributo de la clase. Como él especificó dentro de la pregunta que necesita tener a y b casos – fcalderan

+1

, creo que '\ b' podría fallar en algunas situaciones (restringidas) ya que una clase puede contener caracteres que se interpretarían como un límite de palabras. Me gusta 'my.input', que es una clase válida. –

6

Ésta es una forma ...

function getAllInputDivs() { 
    return $("div").filter(function() { 
     return /(?:^|\s)input/.test(this.className); 
    }); 
} 

O que sea más versátil ..

function classStartsWith(tag, s) { 
    var re = new RegExp('(?:^|\\s)' + s); 
    return $(tag || '*').filter(function() { 
     return re.test(this.className); 
    }); 
} 

O tomar el enfoque indexOf si no te gusta expresiones regulares ...

function classStartsWith(tag, s) { 
    return $(tag || '*').filter(function() { 
     return this.className.indexOf(s)===0 || this.className.indexOf(' ' + s)>-1; 
    }); 
} 

Aunque usted debe ser consciente de que does't prueba para los caracteres de tabulación, sólo los caracteres de espacio, por lo que podría fallar si se utilizó una pestaña en lugar de un espacio.


Volviendo a las versiones de expresiones regulares, puede mejorar la eficiencia agregando la cadena buscada al selector.

Luego solo está probando un subconjunto de divs.

function getAllInputDivs() { 
    return $("div[class*='input']").filter(function() { 
     return /(?:^|\s)input/.test(this.className); 
    }); 
} 

Con la .filter() aplicado únicamente a los divs que conozco tienen input en algún lugar de la clase, el rendimiento mejorará.

o la versión versátil se vería así:

function classStartsWith(tag, s) { 
    var re = new RegExp('(?:^|\\s)' + s); 
    return $((tag || '*') + '[class*="' + s + '"]').filter(function() { 
     return re.test(this.className); 
    }); 
} 
+1

+1 - bien - parece que ha corregido la expresión regular en la respuesta de Fabrizio. –

2

Ésta es mi solución para el problema:

(function($) { 
    $.fn.hasClassStartsWith = function(klass) { 
    var _return = []; 
    for(var i = 0; i < this.length; i++){ 
     if((' ' + $(this[i]).attr('class')).indexOf(klass) != -1) 
      _return.push(this[i]); 
    } 
    return _return; 
    } 
})(jQuery); 

utilizarlo como sigue:

var divs = $('div').hasClassStartsWith("my_class_prefix"); 

funciona también para el caso, alguien crea una clase con un punto en el medio.

Cuestiones relacionadas