So I have a list of siblings like so;
<div class="b"></div>
<div class="a"></div>
<div class="b"></div>
<div class="b"></div>
<div class="b"></div>
<div class="b"></div>
<div class="a"></div>
<div class="b"></div>
<div class="b"></div>
<div class="a"></div>
<div class="c"></div>
<div class="b"></div>
<div class="b"></div>
<div class="b"></div>
<div class="b"></div>
<div class="b"></div>
<div class="b"></div>
<div class="b"></div>
(Note: The b
's are not children of the a
's, they're all siblings. Indentation is for emphasis.)
In jQuery, I need to select each b
, forgoing the first n elements in a streak. There is no specific type/class of element that breaks the streak, nor any dependable number of b
's in a streak, or non-b
elements in between.
If I used the selector to add a class selected
, and supposing n = 2, my DOM would then look like so;
<div class="b"></div>
<div class="a"></div>
<div class="b"></div>
<div class="b"></div>
<div class="b selected"></div>
<div class="b selected"></div>
<div class="a"></div>
<div class="b"></div>
<div class="b"></div>
<div class="a"></div>
<div class="c"></div>
<div class="b"></div>
<div class="b"></div>
<div class="b selected"></div>
<div class="b selected"></div>
<div class="b selected"></div>
<div class="b selected"></div>
<div class="b selected"></div>
In other words, select every b
except for n elements after anything else than b
, or the beginning.
I've tried :nth-child(n+3)
, but that simply seems to take all the b
's into account, despite the a
's that break them.
I also tried fiddling around with .nextUntil()
and .filter()
, but it must take a better man than me to crack this. Ideas?
Since these elements are all siblings that share the same parent, some clever use of sibling combinators will do the trick:
$('.b + .b + .b').addClass('selected');
For any n, simply repeat .b +
n times before the last .b
.
No need for :nth-child()
or any traversing/filtering functions, and is also a valid and well-supported CSS selector, in case you're looking to apply styles to these elements.
jsFiddle preview
If you need to add an intermediate element before each set of .b + .b + .b
elements, add the class first, then prepend the intermediate element before the first of each set of those matched elements. The first of these elements can be matched by looking behind it for an element that isn't .selected
, which excludes everything that does have a .selected
directly behind it:
$('.b + .b + .b').addClass('selected')
.filter(':not(.selected) + .selected')
.before('<div class="inserted"></div>');
Updated jsFiddle preview
If chaining too many methods gets confusing, you can always do each step separately:
$('.b + .b + .b').addClass('selected');
$(':not(.selected) + .selected').before('<div class="inserted"></div>');
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