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 custom build and awful.
<br>
nodes. Optionally, ignore the ones directly
inside a <p>
block.<br>
node, wrap any text nodes that immediately precede or immediately follow it.<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>
}
} );
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:
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.<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);
}
} );
} );
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 ;-)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With