开发者

jQuery.replaceWith, changing <br /><br /> to </p>?

I am working with a CMS that produces double break tags in place of my preferred paragraph tag. I tried:

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

Now after you finish laughing; could you please let me know if this is possible and if yes, the best way to approach this.

Update (from OP comment):

The paragraphs are not empty they have a <p> tag at the start and the last para closes with a </p> the paragraphs in between are spaced with the double <br> tag.

I have no access to the editor code, which is my problem. It was cu开发者_开发知识库stom build and awful.


There are a couple of ways you could try this. The preferable one (since you're already using jQuery) is probably using contents():

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

This will wrap all text nodes in paragraph tags. Follow that by ripping out all of the
tags:

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

Of course it gets more complicated if your text nodes aren't all simple children of the main text container.

The other (dirty) option is simply to mangle the html manually and then put it back in to jQuery once you're done:

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

I'm not saying the second way is wrong and sometimes it's the only way to get things done without rewriting everything. But it still makes me feel dirty if I have to do it ;-)


  1. Get all the <br> nodes. Optionally, ignore the ones directly inside a <p> block.
  2. Then, for each <br> node, wrap any text nodes that immediately precede or immediately follow it.
  3. Finally, delete the <br> node.

This approach handles nesting and doesn't trash links, the page layout, etc.

The code:

$('.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>
    }
} );


Update:

After editing the OP's question, I realized that I hadn't quite addressed his specific situation. (I use the above code, to great effect in userscripts.)

He wants to change this:

<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>


The difficulties being: You don't want to trash nested elements (if any) or event handlers (if any).

For this, use the following approach:

  1. Grab just the offending paragraphs with a selector like p:has(br+br). Beware that the adjacent selector ignores text nodes -- the very thing we don't want it to do, in this case.
  2. Loop through each offending paragraph's contents, one by one.
  3. Use a state machine to create a new paragraph at each <br><br> and to move the content nodes to the appropriate <p>.

The code looks like this. You can see it in action at 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);
        }
    } );
} );


if your server language is php then you can use str_replace()

http://php.net/manual/en/function.str-replace.php


This is the answer to your question:

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

but as said, it's better doing stuff like that server-side

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜