jQuery currently has .next(filter)
and .nextAll(filter)
but I need something that fits in the middle of these - effectively, a .nextWhile(filter)
that repeatedly does next until the filter is no longer true, then stops (rather than continuing to the end).
To demonstrate this, the following is some simplified HTML - (in reality, it is dynamically generated, random order/data, more columns, proper class names, and so on).
<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>
And against this some JavaScript is run:
<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>
Is there an easy way to implement this nextWhile
construct?
Ideally this needs to be achieved without modifying the current HTML.
In jQuery you can create nextWhile()
equivalent using nextUntil()
method and :not
selector. Simply put, while (condition is true) { do something }
is same as saying until (condition is false) { do something }
.
Consider this trick example where you are required to select all .child
elements that follow the first .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>
The following code is roughly equivalent to .nextWhile(".child")
and selects the three .child
elements:
$("#test .parent:first").nextUntil(":not(.child)");
UPDATE: Gave up on the recursion idea and decided to count and slice (see last example).
Initial Attempt:
This code is buggy - it only returns the last two items, so doesn't work for 3+ items.
jQuery.fn.nextWhile = function(f)
{
if( this.next(f).html() )
{
return this.next(f).nextWhile(f).andSelf();
}
else
{
return this;
}
};
Current Version:
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);
}
This appears to work fine, but I'm not sure if there are any performance penalties to selecting everything and then slicing only a handful from it?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With