Reputation: 3
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
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
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
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
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