Поиск первого и последнего класса для группировки элементов с помощью javascript

Мое требование немного отличается от традиционного метода получения первого и последнего метода, поэтому я прошу экспертную помощь.

Я объясню с помощью примера кода

Моя структура кода

<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>

Когда я использую метод jquery, как показано ниже

$('div.group-a:first').addClass('first');
$('div.group-a:last').addClass('last');

Результат похож на

<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>

Но я хочу, чтобы результат был как ниже, с первым и последним классом для каждой группы.

<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>

Возможно ли с помощью javascript или jquery?

Ответ 1

Зачем перебирать классы, когда вы можете использовать смежные селекторные ролики CSS и :not? Здесь гораздо более чистый метод!

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

Обратите внимание, что это работает для любого числа group-a и group-b, а для других классов, таких как group-c, по запросу. prev() необходим, потому что для селектора смежности CSS может быть выбран только второй элемент, а не первый. Надеюсь, это поможет!

Демо здесь

Ответ 2

Наивный способ состоял бы в итерации через каждый элемент .group-a и проверить, является ли это либо первым потомком, либо приходит непосредственно после .group-b, и если он либо последний ребенок, либо находится непосредственно перед .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');
    }
});

Вам нужно использовать метод .next(), чтобы проверить его следующий брат, потому что не существует селектора для сопоставления элемента, предшествующего другому.

( Вы можете использовать .prev() вместо селектора +, если вы хотите, чтобы ваши операторы if были конгруэнтными.)

Адаптировать его для любого количества групп до тех пор, пока вы ищете только элементы .group-a, просто замените .group-b на :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');
    }

Ответ 3

Обновление

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

См. рабочий код:

JSFiddle

Ответ 4

Есть ли что-то не так с обертыванием групп вместе, а затем просто с использованием первого и последнего для каждой группы?

<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>

Ответ 5

Метод заключается в использовании метода .prev:

$(".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

Ответ 6

Вы можете получить группы путем фильтрации последовательных элементов, имеющих группу классов-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;
    }    
});

Ответ 7

$(".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/