jQuery包装相邻元素组

7

我有一个内容管理系统,可以让用户在页面上插入内容块。用户可以使用不同类型的内容块,并可以按任何顺序插入它们。例如,高级 dom 结构可能如下所示:

<p>Some rich text</p>

<div class="box">...</div>
<div class="box">...</div>
<div class="box">...</div>

<h3>Some  more rich text</h3>
<p>Lorem ipsum</p>

<div class="box">...</div>
<div class="box">...</div>

我希望做的是将任何相邻的“box” div包装到一个包含的“container” div中。因此,在上面的示例中,将插入两个“container” div,因为有两组box div,结果如下:

<p>Some rich text</p>

<div class="container">
    <div class="box">...</div>
    <div class="box">...</div>
    <div class="box">...</div>
</div>

<h3>Some  more rich text</h3>
<p>Lorem ipsum</p>

<div class="container">
    <div class="box">...</div>
    <div class="box">...</div>
</div>

我认为使用CSS选择器没有聪明的方法来做到这一点,那么有人知道用jQuery如何实现吗?


发布期望的结果。你尝试过什么吗? - iappwebdev
3个回答

5
您可以使用以下方法:
1. 使用.nextUntil获取所有接下来的.box元素。
2. 使用.andSelf将当前元素添加到集合中。
3. 使用.wrapAll将每个集合包装到不同的.container中。

$('.box').not('.box+.box').each(function(){
  $(this).nextUntil(':not(.box)').addBack().wrapAll('<div class="container" />');
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p>Some rich text</p>

<div class="box">...</div>
<div class="box">...</div>
<div class="box">...</div>

<h3>Some  more rich text</h3>
<p>Lorem ipsum</p>

<div class="box">...</div>
<div class="box">...</div>

http://jsbin.com/gonino/edit?html,js


1
完美,但是andSelf()已经被弃用了。现在使用addBack。在使用cheerio(Node的jQuery克隆)时遇到了这个问题。 - Moss
这个也没有wrapAll,所以也许对我来说这不起作用。:( :P - Moss
谢谢。我尝试用.addBack()替换,看起来工作得很好。是吧? - Mosh Feu

4

您可以像这样做JSFiddle示例。我刚刚为您创建了此页面。

代码的功能是循环每个 .box 元素并将其添加到数组中,然后确定下一个元素是否也具有 .box 类:

var collection = [];
$('.box').each(function() {
    var nextBox = $(this).next().hasClass('box');
    ...
    collection.push($(this));
})

如果下一个元素没有 .box 类,它将创建包含分隔符,并将其放置在页面上,位于 collection 数组中第一个 .box 之前,然后使用 appendTo 将所有 .box 分隔符移入其中:

    if(!nextBox)
    {
        var container = $('<div class="collection"></div>');
        container.insertBefore(collection[0]);
        for(i=0;i<collection.length;i++)
        {
            collection[i].appendTo(container);
        }
        collection = [];
    }

在我的情况下,这证明是最强大的解决方案。 - benb

2

这里是小提琴: http://jsfiddle.net/jdelight/XutA6/5/ 以下是使用CSS的可能解决方案,可以使用单一背景颜色和边框样式来设计块。HTML代码如下:

    <div class="block">this is block 1</div>
    <div class="block">this is block 2</div>
    <div class="block">this is block 3</div>
    <div class="block">this is block 4</div>
    <div class="block">this is block 5</div>

相应的CSS代码如下:

            /* style all blocks with the required background colour and border */
        .block {
            background: #eee;
            color: #000;
            border: 1px solid red;
            border-bottom: 0;
            padding: 20px;
            width: 400px;
            border-radius: 20px;
            /* remove the rounded corners from he bottom left/right */
            border-bottom-left-radius:0;
            border-bottom-right-radius:0;
            position: relative;
        }
        /* style all adjacent blocks and remove the radius - so the top block has a radius and the others don't */
        .block + .block {
            border-radius: 0;
            border-top: 0;
        }

        /* create a cheeky block with content after which sits below all blocks */
        /* so it's hidden from all the blocks above it apart from the very bottom one (see bottom: -10px) */
        /* then style the rounded corners on that one */
        .block::after {
            content:'.';
            display: block;
            background: red;
            height: 10px;
            position: absolute;
            border-bottom: 1px solid red;
            border-left:  1px solid red;
            border-right:  1px solid red;
            bottom: -10px;
            width: 440px;
            background: #eee;
            left:-1px;
            border-bottom-left-radius:10px;
            border-bottom-right-radius:10px;
        }

让我的答案相形见绌!干得好! - James Donnelly
这个几乎可以,但最终我没用它,因为绝对定位会导致底部重叠的问题。 - benb

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接