最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

jquery - Looking for a first and last class for grouping items with javascript - Stack Overflow

programmeradmin0浏览0评论

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?

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?

Share Improve this question asked Apr 1, 2014 at 4:28 Jaison JamesJaison James 4,5524 gold badges43 silver badges56 bronze badges 2
  • Yes my code structure is like above, unfortunately I can't made any change for it because its coming from an external plugin – Jaison James Commented Apr 1, 2014 at 4:42
  • I want to share one more information after reviewing below answers. My code structure not a static one there are chance to came many div's with different class like group-a, group-b, group-c, group-d etc. So I am looking a dynamic solution like below BoltClock's answer. – Jaison James Commented Apr 1, 2014 at 4:57
Add a comment  | 

7 Answers 7

Reset to default 6

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');
    }

Updated

function colorFirstLast(thisClass){
    $('div').find("."+thisClass).each(function () {
        var node = $(this);
        var prevNode = node.prev();
        var nextNode = node.next();
        if (prevNode == undefined || !prevNode.hasClass(thisClass)) {
            node.addClass('first');
        }
        if (nextNode == undefined || !nextNode.hasClass(thisClass)) {
            node.addClass('last');
        }
    });
}

colorFirstLast('group-a');

See the working code at:

JSFiddle

Is there something wrong with wrapping the groups together and then just using first and last for each group?

<div class="wrap">
<div>
    <div class="group-a first"></div>
    <div class="group-a"></div>
    <div class="group-a"></div>
    <div class="group-a last"></div>
</div>
<div class="group-b"></div>
<div class="group-b"></div>
<div class="group-b"></div>
<div>
    <div class="group-a first"></div>
    <div class="group-a"></div>
    <div class="group-a last"></div>
</div>

A method would be to use the .prev method:

$(".group-a:first").addClass("first");  // the normal one
$(".group-a:last").addClass("last");    // the normal one


$(".group-b:first").prev(".group-a").addClass("last");  // the `.group-a` which is followed by the first `.group-b`

$(".group-b + .group-a").addClass("first"); // the `.group-a` whose previous element is `.group-b`

DEMO

You can get the groups by filtering the consecutive elements having class group-a

Live Demo

arr = [];
groupDivs = $('.wrap div')
groupDivs.each(function(index){   
   if(this.className == 'group-a') 
       arr.push($(this));
    if(this.className != 'group-a' || index == groupDivs.length-1)
    {
        if(arr.length > 0)
            arr[0].addClass('first');
        if(arr.length > 1)
            arr[arr.length-1].addClass('last');        
        arr.length = 0;
    }    
});
$(".group-a:eq(0), .group-b + .group-a")
.addClass("first")
.addBack()
.find(".group-a:eq(-1), .group-a:eq(3)")
.addClass("last")

jsfiddle http://jsfiddle.net/guest271314/jF868/

发布评论

评论列表(0)

  1. 暂无评论