Wrapping consecutive list items in separate groups using jQuery

喜你入骨 提交于 2019-12-10 17:09:47

问题


I have an unordered list exported by a CMS and need to identify <li> elements that have the class .sub and wrap them in a <ul>.

I have tried the wrapAll() method but that finds all <li class="sub"> elements and wraps them in one <ul>. I need it to maintain seperate groupings.

The exported code is as follows:

<ul>
  <li></li>
  <li></li>
  <li></li>
  <li class="sub"></li>
  <li class="sub"></li>
  <li class="sub"></li>
  <li></li>
  <li></li>
  <li class="sub"></li>
  <li class="sub"></li>
  <li class="sub"></li>
  <li></li>
 </ul>

I need it to be:

<ul>
  <li></li>
  <li></li>
  <li></li>
  <ul>
     <li class="sub"></li>
     <li class="sub"></li>
     <li class="sub"></li>
  </ul>
  <li></li>
  <li></li>
  <li></li>
  <ul>
     <li class="sub"></li>
     <li class="sub"></li>
     <li class="sub"></li>
   </ul>
   <li></li>
   <li></li>
</ul>

Any help would be greatly appreciated.


回答1:


  1. Use .each to walk through all .sub elements.
  2. Ignore elements whose parent has class wrapped, using hasClass()
  3. Use nextUntil(:not(.sub)) to select all consecutive sub elements (include itself using .andSelf()).
    The given first parameter means: Stop looking forward when the element does not match .sub.
  4. wrapAll

Demo: http://jsfiddle.net/8MVKu/

For completeness, I have wrapped the set of <li> elements in <li><ul>...</ul></li> instead of a plain <ul>.

Code:

$('.sub').each(function() {
   if ($(this.parentNode).hasClass('wrapped')) return;
   $(this).nextUntil(':not(.sub)').andSelf().wrapAll('<li><ul class="wrapped">');
});
$('ul.wrapped').removeClass('wrapped'); // Remove temporary dummy



回答2:


I would like to expand on Rob W's already awesome solution, providing a way to eliminate the temporary wrap class:

$(document).ready(function() {
    $('li.sub').filter(':not(li.sub + li.sub)').each(function() {
        $(this).nextUntil(':not(li.sub)').andSelf().wrapAll('<li><ul>');
    });
});

http://jsfiddle.net/m8yW3/

Edit: The filter isn't even needed:

$('li.sub:not(li.sub + li.sub)').each(function() {
    $(this).nextUntil(':not(li.sub)').andSelf().wrapAll('<li><ul>');
});



回答3:


I believe what you should have is this jQuery:

$('li.sub').wrap('<li><ul>');

This will properly wrap your <li> elements in a new <ul> tag while wrapped them within <li> tags. The output of your example would then be:

<ul>
  <li></li>
  <li></li>
  <li></li>
  <li><ul><li class="sub"></li></ul></li>
  <li><ul><li class="sub"></li></ul></li>
  <li><ul><li class="sub"></li></ul></li>
  <li></li>
  <li></li>
  <li><ul><li class="sub"></li></ul></li>
  <li><ul><li class="sub"></li></ul></li>
  <li><ul><li class="sub"></li></ul></li>
  <li></li>
 </ul>


来源:https://stackoverflow.com/questions/9022601/wrapping-consecutive-list-items-in-separate-groups-using-jquery

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!