我可以围绕数组中的元素集合$ .wrap()吗?

ign*_*aur 8 javascript jquery dom

假设我有一个'项目'的集合,如下所示:

<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>
Run Code Online (Sandbox Code Playgroud)

我想循环遍历项目并将包含div的任何具有'group'类的内容包装起来以产生类似这样的内容(分组项目将始终紧挨着彼此):

var group = [];

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

$(group).wrap('<div class="wrapper" />');
Run Code Online (Sandbox Code Playgroud)

这是我得到的剧本:

<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>
Run Code Online (Sandbox Code Playgroud)

会发生的是,包装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>
Run Code Online (Sandbox Code Playgroud)

期望的状态:

<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>
Run Code Online (Sandbox Code Playgroud)

对不起我之前没有提到过.谢谢!

Vis*_*ioN 8

尝试wrapAll方法:

$(".group").wrapAll("<div class='wrap' />");
Run Code Online (Sandbox Code Playgroud)

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


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

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

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

上面的代码是在@ Jon的回答的帮助下组装.


Abh*_*jit 5

使用wrapAll代替wrap。

$(".group").wrapAll('<div class="wrap" />');
Run Code Online (Sandbox Code Playgroud)

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 = [];
            }
          }
        );
Run Code Online (Sandbox Code Playgroud)


Jon*_*Jon 5

您可以使用的组合.filter.map达到预期的结果:

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

看到它在行动.

关于JS Bin解决当前JSFiddle问题的示例.

合理

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

所以我们需要做的是为每个组创建一个jQuery对象,然后将所有这些对象放入另一个"master"jQuery对象中.首先选择所有.group不在.group兄弟之前的元素:

$(".item.group")
.filter(function() {
    return !$(this).prev().is(".group");
})
Run Code Online (Sandbox Code Playgroud)

从每个这样的元素,创建一个jQuery对象,其中包含元素和所有后续兄弟.group:

.map(function() {
    return $(this).nextUntil(":not(.group)").andSelf();
})
Run Code Online (Sandbox Code Playgroud)

生成的jQuery对象会自动放在"master"对象中,因为它们取代了我们.filter在我们创建的jQuery对象中选择的裸元素$(".item.group").最后一次打电话.wrap......包装好了.:)