Jquery .insertBefore忽略结束标记并自动关闭缺少的标记

时间:2015-11-06 22:18:14

标签: javascript jquery

我尝试拆分一个名为" foo"通过关闭第一个然后使用.insertBefore打开一个具有相同类的新的div来分成两个div。但是jquery会忽略div结束标记并自动用缺少的结束标记完成div。

$( '</div><div class="foo">' ).insertBefore( 'h2:first' );

我明白了:

<div class="foo"></div>
<h2>Title</h2>

但想要做到这一点:

</div><div class="foo">
<h2>Title</h2>

我正在尝试拆分一个名为&#34; foo&#34;分成两个div,通过关闭现有的div,然后添加一个新的开始标记,它将导致两个div&#34; foo&#34;。

对此有何解决方案?

完整的html结构:(我想在&#34; foo&#34;的较小块中拆分几次。来自&#34; foo&#34;的所有内容来自数据库,我无法操纵它除了使用jquery / js。

<div class="foo">
    <span>Text here</span>
    <h2>Title</h2>
    <p>Text</p>
    <h2>Title</h2>
    <p>Text</p>
    <h2>Title</h2>
    <p>Text</p>
    <h3>Another title</h3>
    <h2>Title</h2>
    <p>Text</p>
    <h2>Title</h2>
    <p>Text</p>
    <h3>Another title</h3>
    <h2>Title</h2>
    <p>Text</p>
</div>

4 个答案:

答案 0 :(得分:1)

这会将从第一个h2开始的所有内容移动到新的div,紧跟在h2的父级之后。它使用contents()方法包含文本节点:

var h2 = $('h2:first'),
    hp = h2.parent(),
    move;

$('<div class="foo"/>')
  .insertAfter(hp)
  .append(hp.contents().filter(function() { //use contents() to include text nodes
    move = move || $(this).is(h2);          //move everything beginning with the first h2
    return move;
  }));
.foo {
  background: yellow;
  border: 1px solid red;
  margin-bottom: 1em;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="foo">
  <span>Text here</span>
  <h2>Title</h2>
  <p>Text</p>
  Text node here.
  <h2>Title</h2>
  <p>Text</p>
  <h2>Title</h2>
  <p>Text</p>
  <h3>Another title</h3>
  <h2>Title</h2>
  <p>Text</p>
  <h2>Title</h2>
  <p>Text</p>
  <h3>Another title</h3>
  <h2>Title</h2>
  <p>Text</p>
</div>

答案 1 :(得分:1)

您可以简单地在要拆分的div之后插入一个新div,而不是尝试将其全部解析为字符串,并将其中的一些内容移入其中。

&#13;
&#13;
jQuery(function() {
    var $moving = $('h2:first, h2:first ~ *');
    $('<div class="foo"></div>')
        .insertAfter($moving.parent())
        .append($moving);
});
&#13;
.foo {
    border: 1px solid black;
}
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="foo">
    <h1>Title</h1>
    <p>dummy paragraph</p>
    <h2>Title</h2>
    <p>dummy paragraph</p>
    <p>dummy paragraph</p>
</div>
&#13;
&#13;
&#13;

注意:如果您将文本节点作为foo的直接子节点,则不会移动它们。对于您的示例HTML,这不是问题。

如果 真的 想要在HTML字符串级别上执行此操作,我想您可以将外部DOM元素转换为HTML字符串,并在之前执行字符串放置重置HTML。

但是要注意,这会重新创建此元素及其兄弟元素的整个内容,并且任何元素引用和事件侦听器都将成为孤立的。

&#13;
&#13;
jQuery(function() {
    var $wrapper = $('h2:first').parent().parent();
    $wrapper.html($wrapper.html().replace('<h2', '</div><div class="foo"><h2'))
});
&#13;
.foo {
    border: 1px solid black;
}
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="foo">
    <h1>Title</h1>
    <p>dummy paragraph</p>
    <h2>Title</h2>
    <p>dummy paragraph</p>
    <p>dummy paragraph</p>
</div>
&#13;
&#13;
&#13;

您可以将此效果限制为仅使用原生outerHTML定位的DIV,但仍会重新创建包装内的元素。

&#13;
&#13;
jQuery(function() {
    var wrapper = $('h2:first').parent().parent()[0];
    wrapper.outerHTML = wrapper.outerHTML.replace('<h2', '</div><div class="foo"><h2');
});
&#13;
.foo {
    border: 1px solid black;
}
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="foo">
    <h1>Title</h1>
    <p>dummy paragraph</p>
    <h2>Title</h2>
    <p>dummy paragraph</p>
    <p>dummy paragraph</p>
</div>
&#13;
&#13;
&#13;

答案 2 :(得分:0)

您可以在文档插入之前看到:

http://api.jquery.com/insertbefore/

它实际上是添加了一个像jquery一样创建的元素

<div class="container">
  <h2>Greetings</h2>
  <div class="inner">Hello</div>
  <div class="inner">Goodbye</div>
</div>
$( "<p>Test</p>" ).insertBefore( ".inner" );

导致此;

<div class="container">
  <h2>Greetings</h2>
  <p>Test</p>
  <div class="inner">Hello</div>
  <p>Test</p>
  <div class="inner">Goodbye</div>
</div>

因此它是使用jquery

创建的有效div html

答案 3 :(得分:0)

根据this SO answer,您无法向DOM添加独立的结束标记。

我认为最简单的方法是向DOM添加两个<div>元素,然后删除额外的标记(第一个<div>和最后一个</div>)必要时。