Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Looking for a first and last class for grouping items with javascript

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?

like image 1000
Jaison James Avatar asked Apr 01 '14 04:04

Jaison James


2 Answers

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

like image 88
Irvin Zhan Avatar answered Nov 15 '22 18:11

Irvin Zhan


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');
    }
like image 39
BoltClock Avatar answered Nov 15 '22 18:11

BoltClock