P.Seta
P.Seta

Reputation: 3

Remove HTML paragraph using removeChild

I wrote a code like below:

     <input type="button" value="remove" onclick="remove()"/>

     <p id="p2">
        before hr 
        <hr/>
        after hr 
     </p>

  <script>
     function remove() {
        var p = document.getElementById('p2');
        p.parentNode.removeChild(p);
     }
  </script>

When I hit the button, only "before hr" disappear - hr and "after hr" text don't.

If I change <p> to <div> :

<div id="p2">
    before hr 
    <hr/>
    after hr 
 </div>

everything works properly (i.e. like I supposed it should works ;) )

Could somebody explain me the reasons, please?

Upvotes: 0

Views: 1736

Answers (4)

Renzo Calla
Renzo Calla

Reputation: 7706

Your problem is expected... due to P tag can only contain Phrasing content. Semantically is incorrect and the browser automatically adds a new P element after the HR tag... https://stackoverflow.com/a/23536324/2894798

As you said with a div this will work.. that would be the correct answer..

<input type="button" value="remove" onclick="remove()"/>

     <div id="p2">
        before hr 
       <hr/>

        after hr 
     </div>

  <script>
     function remove() {
        var p = document.getElementById('p2');
        p.parentNode.removeChild(p);
     }
  </script>

Upvotes: 0

Jack Bashford
Jack Bashford

Reputation: 44145

From the MDN web docs on <p>:

and notably will automatically close if another block-level element is parsed before the closing </p> tag.

And the W3C list of block elements states that <hr> is a block element.

So your code is evaluated like this:

<p id="p2">
  before hr
</p>
<hr />
<p id="p2">
  after hr
</p>

Which is why removing a single child isn't working. Since the ID isn't re-created, the only solution is to change the element type - a <div> works fine:

function remove() {
  var p2 = document.getElementById("p2");
  p2.parentNode.removeChild(p2);
}
<input type="button" value="remove" onclick="remove()" />

<div id="p2">
  before hr
  <hr/> after hr
</div>

Upvotes: 1

Quentin
Quentin

Reputation: 944217

Your HTML is invalid. Use a validator.

A <p> element may not contain an <hr> element, but the end tag for the <p> element is optional.

This means that the <p> element is implicitly ended by the <hr> and the </p> tag is discarded because it doesn't match an open <p>.

The resulting DOM looks like this:

 <p id="p2">before hr</p>
 <hr/>
 after hr 

Since the <hr> element and the text node following it are not inside the paragraph, they are not removed when the paragraph is removed.

Your reduced test case has been reduced so much that inferring the correct semantics for your content is impossible, but perhaps you need something like:

<div id="p2">
    <p>before hr</p>
    <hr>
    <p>after hr</p>
</div>

Upvotes: 1

Gianluca Musa
Gianluca Musa

Reputation: 805

you code is not correct, is not possible to put <hr> inside the <p>

<p id="p2">
        before hr 
        <hr/>
        after hr 
     </p>

in a good browser the browser correct your code

 <p id="p2">
            before hr
    </p>
   <hr/>
    <p> 

       after hr 
    </p>

one posibility use span or div

 <span id="p2">
            before hr 
            <hr/>
            after hr 
         </span>  

Upvotes: -1

Related Questions