Futures Me
Futures Me

Reputation: 33

How to remove <br> from text nodes and wrapping with <p> tag when its contains <b>, <i>, <a>, etc

My condition (EDIT):

<div class="entry-content">
    <h1>This header won't be included</h1>
    Write by: Me
    <br></br>
    On: 01/01/2017
    <br></br>
    <br></br>
    When you quote: "<i>And whoever strives only strives for [the benefit of] himself.</i>"
    <br></br>
    <br></br>
    <i>There</i> is another: "And that <b>there is not for man</b> except that [good] for which he strives, and that his effort is going to be seen, then <a href="#">he will be</a> recompensed for it with the fullest recompense."
    <br></br>
    <br></br>
    <h2>And neither will this one</h2>
    I fight for myself.
</div>

My goal (EDIT):

<div class="entry-content">
    <h1>This header won't be included</h1>
    <p>Write by: Me
    <br></br>
    On: 01/01/2017</p>
    <p>When you quote: "<i>And whoever strives only strives for [the benefit of] himself.</i>"</p>
    </p><i>There</i> is another: "And that <b>there is not for man</b> except that [good] for which he strives, and that his effort is going to be seen, then <a hre="#">he will be</a> recompensed for it with the fullest recompense."</p>
    <h2>And neither will this one</h2>
    <p>I fight for myself.</p>
</div>

I have tried:

$( ".entry-content" )
  .contents()
  .filter(function() {
     return this.nodeType === 3;
   })
  .wrap( "<p></p>" )
  .end()
  .filter( "br" )
  .remove();

I have also reads many like this before: How can I wrap text nodes. But they can't handle <i>, <b>, <a>, etc.

They just look like this:

<div class="entry-content">
    <p><h1>This header won't be included</h1></p>
    <p>Write by: Me</p>
    <p>On: 01/01/2017</p>
    <p>When you quote: "</p>
    <i>And whoever strives only strives for [the benefit of] himself.</i>
    <p>"</p>
    <i>There</i>
    <p>is another: "And that <b>there is not for man</b> except that [good] for which he strives, and that his effort is going to be seen, then</p>
    <a hre="#">he will be</a>
    <p>recompensed for it with the fullest recompense."</p>
    <p><h2>And neither will this one</h2></p>
    <p>I fight for myself.</p>
</div>

Upvotes: 3

Views: 463

Answers (2)

gyre
gyre

Reputation: 16777

Here is a "one-liner" that doesn't involve touching the inner HTML text. It works by wrapping every node with its own paragraph and then unwrapping every br, so that the adjacent sibling and first-child selectors can be used to find the point where the wrapping paragraphs should start.

Edit: I had to make this even longer in order to specially exclude headers, blockquotes, and anchors containing images with source attributes. A more performant implementation would be to loop over the child nodes without jQuery; if you need this to run often then let me know and I can provide an alternate implementation. It was difficult to work around the way jQuery handles text nodes, which is by pretty much discarding them for every operation except .contents().

console.log(
  
// Begin magic
$('.entry-content')
    .contents()
    .wrap('<p>')
    .filter('br, :header, blockquote, a:has(img[src])')
    .unwrap()
    .end()
    .end()
    .children(':first-child, :not(p) + p')
    .each(function (i, e) {
        $(e).nextUntil(':not(p)').addBack().wrapAll('<p>').contents().unwrap()
    })
    .end()
    .children(':first-child, :not(p) + p')
    .each(function (i, e) {
        e.firstElementChild || e.textContent.trim() || $(e).remove()
    })
    .end()
    .children('br')
    .remove()
// End magic

.end().html())
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="entry-content">
    <h1>This header won't be included</h1>
    When you quote: "<i>And whoever strives only strives for [the benefit of] himself.</i>"
    <br><br>
    <i>There</i> is another: "And that <b>there is not for man</b> except that [good] for which he strives, and that his effort is going to be seen, then <a href="#">he will be</a> recompensed for it with the fullest recompense."
    <br><br>
    <h2>And neither will this one</h2>
    I fight for myself.
    <blockquote>Keep me</blockquote>
    I am special.
    <a><img src="http://ignore-me.com"></a>
    There <b>is</b> nothing more special than everything
    <a><img src="http://ignore-me-too.com"></a>
</div>

Upvotes: 1

Ionut Necula
Ionut Necula

Reputation: 11480

I hope this is what you need:

var rows = $(".entry-content").html().split("<br>");
rows = $.map(rows, function(value) {
  return value === "" ? null : value;
});
$(".entry-content").html('<p>' + rows.join("</p>\n<p>") + '</p>');
console.log($(".entry-content").html());
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="entry-content">
    When you quote: "<i>And whoever strives only strives for [the benefit of] himself.</i>"
    <br><br>
    <i>There</i> is another: "And that <b>there is not for man</b> except that [good] for which he strives, and that his effort is going to be seen, then <a hre="#">he will be</a> recompensed for it with the fullest recompense."
    <br><br>
    I fight for myself.
</div>

Upvotes: 1

Related Questions