My requirement is slightly different from the traditional method for get first and last method, so I am asking expert help.
I will explain with code sample
My code structure is
<div class="wrap">
<div class="group-a"></div>
<div class="group-a"></div>
<div class="group-a"></div>
<div class="group-a"></div>
<div class="group-b"></div>
<div class="group-b"></div>
<div class="group-b"></div>
<div class="group-a"></div>
<div class="group-a"></div>
<div class="group-a"></div>
</div>
When I use a jquery method like below
$('div.group-a:first').addClass('first');
$('div.group-a:last').addClass('last');
Result is like
<div class="wrap">
<div class="group-a first"></div>
<div class="group-a"></div>
<div class="group-a"></div>
<div class="group-a"></div>
<div class="group-b"></div>
<div class="group-b"></div>
<div class="group-b"></div>
<div class="group-a"></div>
<div class="group-a"></div>
<div class="group-a last"></div>
</div>
But I want the result should be like below with first and last class for each group.
<div class="wrap">
<div class="group-a first"></div>
<div class="group-a"></div>
<div class="group-a"></div>
<div class="group-a last"></div>
<div class="group-b"></div>
<div class="group-b"></div>
<div class="group-b"></div>
<div class="group-a first"></div>
<div class="group-a"></div>
<div class="group-a last"></div>
Is it possible with javascript or jquery?
Why iterate through the classes when you can use CSS adjacent sibling selectors and :not
? Here's a much cleaner method!
// adding first
$(':not(.group-a) + .group-a, .group-a:first').addClass('first');
// adding last
$('.group-a:last').addClass('last');
$('.group-a + :not(.group-a)').prev().addClass('last');
Note that this works for any number of group-a
and group-b
, and for other classes such as group-c
, as requested. The prev()
is needed because for the CSS adjacency selector, only the second element, not the first, may be selected. Hope this helps!
Demo Here
The naïve way would be to iterate through each .group-a
element and check if it's either the first child or comes directly after a .group-b
, and if it's either the last child or comes directly before a .group-b
:
$('div.group-a').each(function() {
var t = $(this);
if (t.is(':first-child, div.group-b + div')) {
t.addClass('first');
}
if (t.is(':last-child') || t.next('div.group-b').length > 0) {
t.addClass('last');
}
});
You'll need to use the .next()
method to check its next sibling because there isn't a selector for matching an element that precedes another.
(You can use .prev()
in lieu of the +
selector if you like your if
statements to be congruent.)
Adapting it for any number of groups as long as you're only looking for .group-a
elements is easy, just replace .group-b
with :not(.group-a)
:
if (t.is(':first-child, div:not(.group-a) + div')) {
t.addClass('first');
}
if (t.is(':last-child') || t.next('div:not(.group-a)').length > 0) {
t.addClass('last');
}
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