2010-10-03 4 views
3

Используя jQuery, я пытаюсь группировать похожие элементы в списке. Вот что я пытаюсь сделать. Учитывая список, как следующее:jQuery: группировка подобных элементов

<ul> 
    <li class="foo">Item #1</li> 
    <li class="foo">Item #2</li> 
    <li class="foo">Item #3</li> 
    <li class="bar">Item #4</li> 
    <li class="bar">Item #5</li> 
    <li class="foo">Item #6</li> 
    <li class="foo">Item #7</li> 
    <li class="bar">Item #8</li> 
</ul> 

Я хотел бы, чтобы в итоге следующее:

<ul> 
    <li class="foo">Item #1 <a>2 More Like This</a> 
     <ul> 
      <li class="foo">Item #2</li> 
      <li class="foo">Item #3</li> 
     </ul> 
    </li> 
    <li class="bar">Item #4</li> 
    <li class="bar">Item #5</li> 
    <li class="foo">Item #6 <a>1 More Like This</a> 
     <ul> 
      <li class="foo">Item #7</li> 
     </ul> 
    </li> 
    <li class="bar">Item #8</li> 
</ul> 

Короче говоря, в любое время есть 2 или более элементов с классом = «Foo», они должны группироваться вместе до достижения элемента non-class = "foo". Затем я могу использовать ссылку, чтобы показать или скрыть сгруппированные элементы.

+0

Конечный результат является первым в каждой группе, и он имеет новый привязку, прикрепленную для переключения видимости остальной группы. Мне удалось написать какой-то код, который работает, но он немного запутан, и я подозреваю, что существует более чистый способ jQuery для этого. – mellowsoon

ответ

3

Вот одна возможность:

Пример:http://jsbin.com/ipiki3/3/

$('ul > li.foo') 
    .filter(function() { 
     var $th = $(this); 
     return $th.next('li.foo').length && !$th.prev('li.foo').length; 
    }) 
    .each(function() { 
     var $th = $(this); 
     var len= $th.append('<a href="#"> more like this</a>') 
        .nextUntil(':not(li.foo)').wrapAll('<ul>').length; 
     $th.next('ul').appendTo(this); 
     $th.children('a').prepend(len); 
    }); 

EDIT: Исправлена ​​ошибка с переменной len, и добавлен пример.


Объяснение: Что происходит с .filter() является то, что она сужает li.foo элементов вплоть до первого в группе (имеет, по меньшей мере, один li.foo после него, и ни перед).

Затем с .each() он добавляет <a>, получите это следующие элементы, пока он не достигнет тот, который не li.foo, обертывания тех, с <ul> и возвращает, сколько там было с помощью length собственности.

Затем мы переходим к этому новому <ul> и добавим его к первому li.foo в группе.

И наконец, мы добавим количество, которое мы храним в собственности length, к элементу <a>.

+0

Спасибо за отличный ответ и объяснение! – mellowsoon

+1

+1 для рабочего примера – galambalazs

+0

@mellowsoon - Добро пожаловать. : o) @galambalazs - Спасибо за +1. : o) – user113716

1

Я придумал это:

$(document).ready(function() { 
    var groups = {} 
    $('ul li').each(function() { 
     var self = $(this); 
     var class_name = self.attr('class'); 
     if (class_name) { 
      if (typeof groups[class] == 'undefined') { 
       groups[class_name] = []; 
      } 
      groups[class_name].push(self); 
     } 
    }); 
    var ul = $('ul'); 
    ul.empty(); 
    for (class_name in groups) { 
     var array = groups[class_name]; 
     ul.append('<li class="' + class_name + '">' + $(array[0]).html() + 
      '<a>More Like this</a><ul></ul>'); 
     $(array.splice(1)).each(function() { 
      ul.find('li.' + class_name + ' ul').append(this); 
     }); 

    } 

}); 
+1

Не используйте 'class' как имя переменной. Это ломается в некоторых браузерах, потому что это будущее зарезервированное слово. – user113716

+0

Спасибо @patrick Я меняю его. – jcubic

Смежные вопросы