Reputation: 57217
I've noticed a funny behavior and was wondering if anybody could shed some light on the reason.
It breaks down like this:
div
and a button
using Javascript's `appendChild'.onclick
handler to the button, works fineinnerHTML
of the div
to add some more contentonclick
stops working altogetherHere's a sample script:
var D = document.createElement("DIV"), B = document.createElement("BUTTON");
B.innerHTML = "Is it true?";
document.body.appendChild(D);
D.appendChild(B);
B.onclick = function() { alert("Elvis Lives!"); }
At this point, it works fine. Then, add this line:...
D.innerHTML += "What about Tupac?";
...and the button breaks. So, I'm just using appendChild
for all elements now.
But -
Upvotes: 2
Views: 564
Reputation: 177885
Not an answer, just a test page - looks very strange - I can confirm your findings
<script>
window.onload=function() {
var D = document.createElement("DIV"), B = document.createElement("BUTTON");
D.id = "div1"
B.innerHTML = "Is it true?";
B.onclick = function() { alert("Elvis Lives!"); }
D.appendChild(B);
document.body.appendChild(D);
}
</script>
<a href="" onclick="document.getElementById('div1').innerHTML += 'What about Tupac?'; return false">Click</a><br>
<a href="" onclick="alert(document.getElementsByTagName('button')[0].onclick); return false">Test</a>
update: Lessons learned - be consistent.
This works as expected
<script>
window.onload=function() {
var D = document.createElement("DIV");
D.id = "div1"
D.innerHTML = '<button onclick="alert(\'Elvis Lives!\')">Elvis</button>'
document.body.appendChild(D);
}
</script>
<a href="" onclick="document.getElementById('div1').innerHTML += 'What about Tupac?'; return false">Click</a><br>
Upvotes: 1
Reputation: 141879
innerHTML
is a shortcut for creating DOM elements. When you append something to the outer div using innerHTML
, this is what happens:
D.innerHTML += "What about Tupac?";
which is the same as,
D.innerHTML = D.innerHTML + "What about Tupac?";
which is the same as,
D.innerHTML = "<button>Is it true?</button>" + "What about Tupac?";
which finally becomes this,
D.innerHTML = "<button>Is it true?</button>What about Tupac?";
Now in the last step, we completely replaced the existing contents of the div, with a new string which contains HTML. As far as the DOM is concerned, it doesn't care whether a user typed the HTML by hand, or it came from calling innerHTML
on a DOM node. All it cares about is, is that it has a string of HTML, which must be converted to a DOM. A new button element is created at this time, which is why the onclick
stops working - it's not the same element anymore.
Upvotes: 3
Reputation: 11238
(this is a lot of educated guessing) I think when you modify D
's innerHTML
, the dom within D
is destroyed and created from the new value. So when the new contents are constructed, you are getting a brand new button
, which is not the same node as B
. since you set the onclick
handler via js and not by an attribute on the original element, the new button
does not have that function reference. however B
still works as can be demonstrated by calling
B.click();
after you append to innerHTML
.
to prevent the thrashing of the dom within D
, you can do this instead of using innerHTML
:
D.appendChild(document.createTextNode("What about Tupac?"));
Upvotes: 4