将<br/>标签转换为<div>或<p>标签</p> </div>

时间:2013-08-28 17:23:10

标签: javascript jquery html html5 dom

我正在接收各种格式的HTML,并且我正在尝试使用jQuery标准化代码。在某些情况下,我会使用中断<br>来分隔行。我需要将这些标记改为<div>(或<p>)标记。例如,以下代码:

a<br>b<br>c

需要转换为

<div>a</div><div>b</div><div>c</div>

这是一个简单的案例,因为a中的内容可能被各种<font><span>和其他格式选项所包围,所有这些都需要保留。

这是我的第一次尝试。它会查找整个文档中的所有<br>标记,然后访问父级内容以获取<br>周围的所有HTML。如果内容长度为1,则<br>是其中唯一的元素(表示空行),因此请跳到下一个。否则,请查看每个元素,并使用<div>(或<p>)将其包围,然后删除<br>,因为不再需要它。变量wrapper可以是"<div />""<p />",具体取决于浏览器。

$("br").each(function() {
  // Find all the br tags' parent nodes
  var elements = $(this).parent().contents();
  if (elements.length > 1) {
    // If there is one element than it is br so skip on.
    elements.each(function() {
      // Loop through each child element of the parent 
      var nodeName = this.nodeName.toLowerCase();
      if (nodeName !== 'div' && nodeName !== 'p') {
      // Make sure each child that is not <br> is wrapped. Remove <br> tags.
        if (nodeName == 'br') {
          $(this).remove();
        } else {
          $(this).wrap(wrapper);
        }
      }
    });
  }
});

但这不起作用,因为它会在每个子元素周围添加<div>(或<p>)个标记,因此<font>a</font>bc<br>de<b>f</b>之类的内容最终会像

一样
<div><font>a</font></div>
<div>bc</div>
<div>de</div>
<div><b>f</b></div>

当它真的需要

<div><font>a</font>bc</div>
<div>de<b>f</b></div>

(我把它分解为更容易阅读。)

如果我在文本解析器中执行此操作,我会发现内容与上面的变量elements一样,在开头添加<div>,在</div>处添加<br>最后,然后用</div><div>替换每个<div><br></div>(除非它已经<br>,此时我会跳过它)。我不知道如何在jQuery / Javascript中执行此操作。但是,特别是关于用</div><div>部分替换elements.wrap(wrapper)。 (第一部分是$("br").each(function(idx, el) { var $el = $(el), $parent = $el.parent(), $contents = $parent.contents(), $cur, $set, i; $set = $(); if ($contents.length > 1) { for (i = 0; i < $contents.length; i++) { $cur = $contents.eq(i); if ($cur.is("br")) { $set.wrapAll(wrapper); $cur.remove(); $set = $(); } else { $set = $set.add($cur); } } $set.wrapAll(wrapper); } }); 。)

对此方法或替代方法的任何帮助将不胜感激。

---更新---

@Ian提供了必须使用的代码。我稍微扩展了它,并认为我将它包含在这里。我已在FF,Safari,Chrome和IE 9 +中测试过它。

{{1}}

6 个答案:

答案 0 :(得分:5)

我的建议是将文字拆分为<br>

var lines = content.split("<br>");

现在,您可以将每一行包装在<div>

var newContent = "";
for(var i=0,l=lines.length;i<l;i++){
     newContent += "<div>"+lines[i]+"</div>";

}

答案 1 :(得分:3)

您可以执行您所描述的确切文本替换方法。

function changeBrToDiv(node) {
  var html = $(node).html();
  html = "<div>" + html.split("<br>").join("</div><div>") + "</div>";
  node.html(html);
}

你可以see this in action on jsFiddle

答案 2 :(得分:1)

对我而言,似乎您可能希望将br标记保留在DOM中,直到您完成遍历它。对于第二个示例,除非您将div标记作为参考点,否则您不会知道使用开始br标记达到多高。我会抓住父元素,查找DOM,直到找到开头<body><br>,然后在那里打开开始标记。冲洗并重复

答案 3 :(得分:1)

<br>标记不包含文本,并且父标记对于多个<br>可能完全相同,如下所示:

<div id="theOne">text<br>more text<br>even more text</div>

执行$('br').each()然后$(this).parent()会给你<div id="theOne">两次。

如果你可以接近html作为文本,你可以这样做(类似于Ibu但更简单):

var newContent = '<div>'+content.split('<br>').join('</div><div>')+'</div>';

如果你想使用节点操作(你倾向于使用类似的答案),那么你将不得不使用本机Javascript .childNodes来访问文本节点,据我所知,jQuery不允许你这样做。 / p>

答案 4 :(得分:0)

我认为这可能是你的问题:

var elements = $(this).parent().contents();

应该是

var elements = $(this).parent().children();

因为内容也将文本元素作为节点返回,而子节点只返回实际的dom元素

答案 5 :(得分:0)

你可以在POJS中尝试这样的事情;操纵DOM而不是将标记视为文本。您可能需要稍微修改它以满足您的确切要求。

HTML

<div>one
    <br>two</div>
<br>
<div>
    <br>
</div>
<div>
    <div>three
        <br><font>a</font>bc
        <br>de<b>f</b>

    </div>
</div>
<span>a</span>

<br>b<span>c</span>d
<br>e<span>f</span>g

的Javascript

function prepend(referenceNode, newNode) {
    if (referenceNode.firstChild) {
        referenceNode.insertBefore(newNode, referenceNode.firstChild);
    } else {
        referenceNode.appendChild(newNode);
    }
}

var brs = document.getElementsByTagName("br"),
    docFragment = document.createDocumentFragment(),
    index1,
    index2,
    parent,
    siblings,
    sibling,
    br;

for (index1 = brs.length - 1; index1 >= 0; index1 -= 1) {
    div = document.createElement("div");
    br = brs[index1];
    parent = br.parentNode;
    siblings = parent.childNodes;
    for (index2 = siblings.length - 1; index2 >= 0; index2 -= 1) {
        sibling = siblings[index2];
        if (sibling === br) {
            break;
        }

        prepend(div, sibling);
    }

    prepend(docFragment, div);
    br.parentNode.removeChild(br);
    if (!brs.length && siblings.length) {
        div = document.createElement("div");
        for (index2 = siblings.length - 1; index2 >= 0; index2 -= 1) {
            prepend(div, siblings[index2]);
        }

        prepend(docFragment, div);
    }

    if (docFragment.childNodes.length && !siblings.length) {
        parent.appendChild(docFragment);
    }
}

jsfiddle