jQuery.replaceWith,将 <br /><br /> 替换为 </p>?

6

我正在使用一个CMS,它在我喜欢的段落标签的位置产生了双换行符。 我尝试过:

$('<br /><br />').replaceWith('</p>');

现在,如果你已经笑完了,请告诉我是否可能实现,如果是的话,最好的方法是什么。
更新(来自OP的评论): 段落不是空的,它们有一个以<p>开始的标签,最后一个段落以</p>结束,中间的段落用双<br>标签间隔。
我的问题是我无法访问编辑器代码。它是定制构建的,非常糟糕。

1
这是一个空的 <p></p> 吗?如果是,那有什么意义呢? - Kobi
2
这是服务器端的工作,不是jQuery/前端的工作。 - Matt
2
你有编辑器代码的访问权限吗?大多数所见即所得编辑器都有更改此设置的选项。 - Andy
这些段落并不是空的,它们在开头有一个 p 标签,最后一个段落用 /p 结尾,在中间的段落之间用双 br 标签分隔。我的问题是我无法访问编辑器代码,因为它是定制构建的,而且很糟糕。 - Laurence L
自从什么时候开始操作DOM成为服务器的工作了?你的服务器是否具备HTML意识?听起来你可能需要稍微分离一下逻辑和表现。 - Jason
4个回答

3

有几种方法可以尝试这个。最好的方法(因为您已经在使用jQuery)可能是使用contents()

$('.your_cms_container').contents().filter(function() {
    return this.nodeType == 3;  // Only text nodes
}).wrap('<p></p>')

这将用段落标签包裹所有文本节点。接下来,移除所有的
标签:

$('.your_cms_container').filter('br').remove();

当然,如果您的文本节点不都是主要文本容器的简单子元素,则情况会变得更加复杂。
另一个(不太优雅的)选项是手动操纵HTML,然后在完成后将其放回jQuery中:
var htmlAsString = $('.your_cms_container').html();    // Get the contents as simple text

... // Do nasty things to the string here

$('.your_cms_container').html(htmlAsString);    // Put it back and let jQuery try and sort out any mess

我并不是说第二种方式是错误的,有时这是唯一的方法,可以在不重写所有内容的情况下完成任务。但如果我必须这样做,它仍然让我感到不舒服;-)


2
获取所有的<br>节点。可选择忽略直接位于<p>块内部的节点。 然后,对于每个<br>节点,包装紧随其前或紧随其后的任何文本节点。 最后,删除<br>节点。 这种方法处理嵌套并且不破坏链接、页面布局等。 代码如下:
$('.your_cms_container br').each ( function () {
    if (this.parentNode.nodeName != "P") {
        $.each ([this.previousSibling, this.nextSibling], function () {
            if (this.nodeType === 3) { // 3 == text
                $(this).wrap ('<p></p>');
            }
        } );

        $(this).remove (); //-- Kill the <br>
    }
} );


更新:
在编辑了原帖问题后,我意识到我没有完全解决他的特定情况。(我在用户脚本中使用上述代码,效果很好。)
他想改变这个:
<p> "Paragraph 1" <br />
    <a href="http://xkcd.com/246/">Link, the first</a>
    Line after single break.
    <br /><br />
    "Paragraph 2"
</p>

into this:

<p> "Paragraph 1" <br />
    <a href="http://xkcd.com/246/">Link, the first</a>
    Line after single break.
</p>
<p> "Paragraph 2" </p>

翻译如下:


困难在于:您不想删除嵌套元素(如果有的话)或事件处理程序(如果有的话)。

为此,请使用以下方法:

  1. 使用类似p:has(br+br)的选择器仅获取有问题的段落。请注意,相邻选择器会忽略文本节点 - 这正是我们在这种情况下不想要它做的事情。
  2. 逐一遍历每个有问题的段落的内容。
  3. 使用状态机在每个<br><br>处创建一个新段落,并将内容节点移动到适当的<p>中。

代码如下。 您可以在jsFiddle上查看它的实际效果:

var badGraphs   = $("#content p:has(br+br)");
var targetP     = null;
var justSplit   = false;

badGraphs.each ( function () {
    var parentP = $(this);

    parentP.contents ().each ( function (J) {
        if (justSplit) {
            justSplit = false;
            // Continue the loop. Otherwise, it would copy an unwanted <br>.
            return true;    
        }
        var thisjNode   = $(this);
        var nextjNode   = $(this.nextSibling);

        if (thisjNode.is ("br")  &&  nextjNode.is ("br") ) {
            thisjNode.remove (); //-- Kill this <br>
            nextjNode.remove (); //-- and the next

            //-- Create a new p for any following content
            targetP     = targetP || parentP;
            targetP.after ('<p></p>');
            targetP     = targetP.next ("p");

            justSplit   = true;
        }
        else if (targetP) {
            //-- Move the node to its new home.
            targetP.append (this);
        }
    } );
} );

0

-5

这是你问题的答案:

$( 'br' ).before( '<p></p>' ).remove();

正如所说,最好在服务器端完成这样的操作。


最好不要在服务器上操纵表示层。 - Jason
这实际上只是在原来的<br>元素位置添加了一堆空的<p></p>节点。 - Brock Adams

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