jQuery - sugerencias para un “próximo Mientras que” el recorrido?
-
23-08-2019 - |
Pregunta
jQuery actualmente tiene .next(filter)
y .nextAll(filter)
pero necesito algo que encaja en el medio de estos -. Efectivamente, un .nextWhile(filter)
que hace varias veces al lado hasta que el filtro ya no es así, entonces se detiene (en lugar de seguir hasta el final)
Para demostrar esto, el siguiente es algo de HTML simplificada -. (En realidad, se genera dinámicamente, de forma aleatoria / datos, más columnas, nombres de las clases apropiadas, y así sucesivamente)
<table>
<thead>
<tr>
<th>...</th>
</tr>
</thead>
<tbody>
<tr class="x"><td>a <button>Show/Hide</button></td></tr>
<tr class="x y"><td>a1</td></tr>
<tr class="x y"><td>a2</td></tr>
<tr class="z"><td>b</td></tr>
<tr class="z"><td>c</td></tr>
<tr class="x"><td>d <button>Show/Hide</button></td></tr>
<tr class="x y"><td>d1</td></tr>
<tr class="x y"><td>d2</td></tr>
<tr class="x y"><td>d3</td></tr>
<tr class="z"><td>e</td></tr>
<tr class="x"><td>f</td></tr>
<tr class="x"><td>g <button>Show/Hide</button></td></tr>
<tr class="x y"><td>g1</td></tr>
<tr class="x y"><td>g2</td></tr>
</tbody>
</table>
Y en contra de este código JavaScript se ejecuta:
<script type="text/javascript">
var $j = jQuery.noConflict();
$j().ready(init);
function init()
{
$j('tr.y').hide();
$j('tr.x button').click( toggleRelated );
}
function toggleRelated()
{
// Only toggles one row
// $j(this).parents('tr').next('.y').toggle();
// Toggles unrelated ones also
$j(this).parents('tr').nextAll('.y').toggle();
// Not currently a jQuery construct
// $j(this).parents('tr').nextWhile('.y').toggle();
}
</script>
¿Hay una manera fácil de poner en práctica esta construcción nextWhile
?
Lo ideal sería que esto debe lograrse sin modificar el código HTML actual.
Solución
En jQuery puede crear nextWhile()
equivalente utilizando nextUntil()
método y Selección :not
. En pocas palabras, while (condition is true) { do something }
es lo mismo que decir until (condition is false) { do something }
.
Considere este ejemplo truco en el que es necesario seleccionar todos los elementos .child
que siguen a la primera .parent
:
<ul id="test">
<li class="parent"></li>
<li class="child"></li>
<li class="child"></li>
<li class="child"></li>
<li class="divider"></li>
<li class="parent"></li>
<li class="child"></li>
<li class="child"></li>
<li class="child"></li>
</ul>
El código siguiente es aproximadamente equivalente a .nextWhile(".child")
y selecciona los tres elementos .child
:
$("#test .parent:first").nextUntil(":not(.child)");
Otros consejos
ACTUALIZACIÓN:. abandonó la idea de recursividad y decidió contar y rebanada (véase el último ejemplo)
intento inicial:
Este código está libre de errores - que sólo devuelve los dos últimos elementos, por lo que no funciona para más de 3 artículos
jQuery.fn.nextWhile = function(f)
{
if( this.next(f).html() )
{
return this.next(f).nextWhile(f).andSelf();
}
else
{
return this;
}
};
Versión actual:
jQuery.fn.nextWhile = function(f)
{
var Next = this.next(f);
var Pos = 0;
while( Next.length > 0 )
{
Pos++;
Next = Next.next(f);
}
return this.nextAll(f).slice(0,Pos);
}
Esto parece funcionar bien, pero no estoy seguro de si hay algún penalizaciones de rendimiento a la selección de todo y luego rebanar sólo un puñado de ella?
Mi versión:
$.fn.extend({
nextWhile: function(selector) {
var $result = $([]);
this.each(function() {
var $next = $(this).next();
while ($next.is(selector)) {
$result = $result.add($next);
$next = $next.next();
}
});
return $result;
}
});