8

假设我有一个像这样的“项目”集合:

<p class="item">Item 1</p>
<p class="item">Item 2</p>
<p class="item group">Item 3</p>
<p class="item group">Item 4</p>
<p class="item">Item 5</p>

我想遍历项目并在任何具有“组”类的对象周围包装一个包含 div,以产生类似这样的结果(分组的项目总是彼此相邻):

这是我得到的脚本:

var group = [];

$('.item').each(function(i, item) {
  if ($(item).hasClass('group')) {
    group.push(item);
  }
});

$(group).wrap('<div class="wrapper" />');
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<p class="item">Item 1</p>
<p class="item">Item 2</p>
<div class="wrapper">
  <p class="item group">Item 3</p>
  <p class="item group">Item 4</p>
</div>
<p class="item">Item 5</p>

发生的情况是包装 div 分别包装在数组中的每个元素周围(这是有道理的),但我需要它将所有元素包装在一起。有什么办法可以做到这一点吗?这是一个jsFiddle

这个问题可能有一个更复杂的变体,这将是这样一种情况,即这些组有几个“组”,每个组都被包装在自己的“组”div中。初始状态:

<p class="item">Item 1</p>
<p class="item">Item 2</p>
<p class="item group">Item 3</p>
<p class="item group">Item 4</p>
<p class="item">Item 5</p>
<p class="item group">Item 6</p>
<p class="item group">Item 7</p>
<p class="item group">Item 8</p>
<p class="item">Item 9</p>

期望状态:

<p class="item">Item 1</p>
<p class="item">Item 2</p>
<div class="wrapper">
  <p class="item group">Item 3</p>
  <p class="item group">Item 4</p>
</div>
<p class="item">Item 5</p>
<div class="wrapper">
  <p class="item group">Item 6</p>
  <p class="item group">Item 7</p>
  <p class="item group">Item 8</p>
</div>
<p class="item">Item 9</p>

4

3 回答 3

8

尝试wrapAll方法:

$(".group").wrapAll("<div class='wrap' />");

演示:http: //jsfiddle.net/LanMt/3/


为了包装单独的.group元素组,您可以使用以下内容:

$(".group").map(function() {
    if (!$(this).prev().hasClass("group")) {
        return $(this).nextUntil(":not(.group)").andSelf();
    }
}).wrap("<div class='wrap' />");

演示:http: //jsfiddle.net/LanMt/5/

上面的代码是在@Jon's answer的帮助下组装而成的。

于 2012-06-28T10:16:35.313 回答
5

您可以使用.filter和的组合.map来实现所需的结果:

$(".item.group")
.filter(function() {
    return !$(this).prev().is(".group");
})
.map(function() {
    return $(this).nextUntil(":not(.group)").andSelf();
})
.wrap('<div class="wrap" />');

看到它在行动

解决当前 JSFiddle 问题的JS Bin 示例。

基本原理

该方法将每个项目.wrap嵌入到您选择的标记内的当前 jQuery 对象中。因此,如果你想在同一个包装器中包装多个元素,你必须将这 N 个元素与一个 jQuery 对象匹配,然后创建另一个包含一个元素的 jQuery 对象:第一个 jQuery 对象。您应该将后一个对象传递给..wrap

所以我们需要在这里为每个组创建一个 jQuery 对象,然后将所有这些放入另一个“主”jQuery 对象中。首先选择所有.group自身之前没有.group兄弟元素的元素:

$(".item.group")
.filter(function() {
    return !$(this).prev().is(".group");
})

从每个这样的元素,创建一个 jQuery 对象,其中包含该元素和所有以下同级元素.group

.map(function() {
    return $(this).nextUntil(":not(.group)").andSelf();
})

生成的 jQuery 对象会自动放置在“主”对象中,因为它们取代了.filter我们在创建的 jQuery 对象中选择的裸元素$(".item.group")。最后一次调用.wrap... 结束了。:)

于 2012-06-28T10:24:25.623 回答
4

使用 wrapAll 而不是 wrap。

$(".group").wrapAll('<div class="wrap" />');

wrapAll 的文档可以在 - http://api.jquery.com/wrapAll/找到

可以在以下位置找到其他可用的包装方法 - http://api.jquery.com/category/manipulation/dom-insertion-around/

编辑:

对于可能有多个组的复杂情况,我们可以使用带有 $.each 的 wrapAll 来实现它,如下所示 -

var group = [];
        $(".item").each(
          function(i, item) {            
            if ($(item).hasClass("group")) {
                group.push(item);
            }
            else {
                $(group).wrapAll('<div class="wrap" />');
                group = [];
            }
          }
        );
于 2012-06-28T10:22:02.893 回答