2008-09-17 16 views
7

Teniendo en cuenta este ejemplo:Cómo seleccionar elementos consecutivos que coinciden con un filtro de

<img class="a" /> 
<img /> 
<img class="a" /> 
<img class="a" id="active" /> 
<img class="a" /> 
<img class="a" /> 
<img /> 
<img class="a" /> 

(yo sólo he utilizado las etiquetas img como un ejemplo, que no es lo que está en mi código)

Usando jQuery, ¿cómo seleccionarías las etiquetas img con la clase "a" que son adyacentes a #activo (las cuatro centrales, en este ejemplo)?

Podrías hacerlo bastante fácil haciendo un bucle sobre todos los elementos siguientes y anteriores, deteniéndote cuando falla la condición del filtro, pero me preguntaba si jQuery podría hacerlo de forma nativa.

Respuesta

4

Esto es lo que se me ocurrió al final.

// here's our active element. 
var $active = $('#active'); 

// here is the filter we'll be testing against. 
var filter = "img.a"; 

// $all will be the final jQuery object with all the consecutively matched elements. 
// start it out by populating it with the current object. 
var $all = $active; 

for ($curr = $active.prev(filter); $curr.length > 0; $curr = $curr.prev(filter)) { 
    $all = $all.add($curr); 
} 
for ($curr = $td.next(filter); $curr.length > 0; $curr = $curr.next(filter)) { 
    $all = $all.add($curr); 
} 

Para una pregunta de seguimiento, pude ver cómo esto podría ser fácilmente generalizable al convertirlo en una función que toma dos argumentos: un elemento inicial, y una cadena de filtro - alguien me puede apuntar en la dirección correcta para averiguar cómo extender el objeto jQuery para agregar dicha función?


Editar: Desde entonces, he encontrado que la función de cada uno() haría esto bastante bien para algunos propósitos. En mi caso, no funciona tan limpiamente, ya que quiero un único objeto jQuery para todos esos elementos, pero he aquí cómo puedes usar cada uno para un propósito diferente (ocultando elementos consecutivos ".a", en este ejemplo :)

$('#active') 
    .nextAll() 
    .each(hideConsecutive) 
    .end() 
    .prevAll() 
    .each(hideConsecutive) 
; 
function hideConsecutive(index, element) { 
    var $e = $(element); 
    if (!$e.is(".a")) { 
     return false; // this stops the each function. 
    } else { 
     $e.hide('slow'); 
    } 
} 

-

Edición: he puesto esto juntos en un plugin ahora. Eche un vistazo a http://plugins.jquery.com/project/Adjacent si le interesa.

2

Creo que el bucle es su mejor apuesta. Pero podría intentar, cada uno activo, y luego moverse antes y después hasta que se rompa la condición, que si el conjunto es lo suficientemente grande sería más rápido.

+0

Podría proporcionar algún fragmento de código, por favor. Sería útil ya que no entiendo lo que quieres decir. –

0

Esta es otra manera de hacerlo, aunque la respuesta del selector de hermanos está muy bien:

var next = $('#active').next('.a'); 
var prev = $('#active').prev('.a'); 

Editar: que releer sus necesidades y esto no es exactamente lo que quieren . Podrías usar nextAll y prevAll, pero esos también no se detendrían en los IMG sin el nombre de la clase.

1

El siguiente código agregará dos nuevas funciones, nextConsecutive() y prevConsecutive(). Deben hacer lo que quieras.

$ .each (['prev', 'next'], function (unusedIndex, name) { $.fn [nombre + 'Consecutivo'] = función (matchExpr) {

var $all = 
     (name == 'prev') 
      ? $(this).prevAll() 
      : $(this).nextAll(); 
    if (!matchExpr) 
     return $all; 

    var $notMatch = $($all).not(matchExpr).filter(':first'); 
    if ($all.index($notMatch) != -1) 
     return $allConsecutive = $all.slice(0, $all.index($notMatch)); 

    return $all; 
}; 

});

Cuestiones relacionadas