Manipulating innerHTML removes events
Others have written about this before, but I thought I'd mention it again, just so you don't miss it. Aleksandar Vaci? found it while playing with tables and their cells. I found it when Robert and I played with nested lists. It works the same across browers. Let me show a quick example:
You have a paragraph tag that contains a span that you want to make clickable.
<p id="para">
<span id="clickspan">This is clickable.</span>
But this is not.
</p>
To make it clickable you don't do any fancy stuff, you just add it with onclick:
var span = document.getElementsById("clickspan");
span.onclick = function() {
alert("You clicked the span!");
}
All fine. You click the span and it just works. But then you remember something. You want to add some text to the end of the paragraph, and you decide to do this with javascript. You add the following line to the end of the script:
var p = document.getElementById("para");
p.innerHTML += " Some extra text";
You try clicking the span again, and it doesn work. You scratch your hair, you bite your nails, you scream of desperation and anger. It still doesn't work. It seems manipulating an element by using innerHTML removes all events from that element, and all children. Here's a live example. I thought you should know.
Comments
By: Nate Klaiber (#1)
Just kidding. Do you have the same results if you were to try appending via the DOM instead of innerHTML?
By: Emil Stenström (#2)
By: Freddy (#3)
The only thing slightly noteworthy is that this also applies when using the + unary operator ("+="). And given that it is required to call GetValue() and return the sum, which is in turn written back as a whole, it is not very surprising.
By: Emil Stenström (#4)
As you said, the confusing part here is that adding to and replacing innerHTML is the same.
Thanks for commenting.
By: Freddy (#5)
By: Emil Stenström (#6)
By: Johan Lind (#7)
Is this an IE only thing?
By: Kalle Persson (#8)
Johan Lind:
Look at the source of the example page, the JavaScript isn't supposed to do anything when you click the span, because of the innerHTML change.
By: Jose Carrero (#9)
By: Ara Pehlivanian (#10)
By: Robert Nyman (#11)
Thanks for explaining that! It threw us off for a while, so we just needed to think in alternate terms. In this case it was an AJAX call that could return any kind of HTML code, so using proper DOM methods wasn't a viable option.
By: Emil Stenström (#12)
By: Anders Ringqvist (#13)
I let Christian Heilmann speak:
http://icant.co.uk/sandbox/eventdelegation/
By: Emil Stenström (#14)
By: zcorpan (#15)
HTMLElement.prototype.appendHTML = function(s) {
var div = document.createElement('div');
div.innerHTML = s;
while (div.firstChild)
this.appendChild(div.firstChild);
}
This does what you thought "innerHTML +=" did (except that script blocks inserted this way will be executed).
By: wongkachun (#16)
I try to use div instead of span on the above coding.
The result is that the event of div is kept while span's is "killed".
kachun
By: wongkachun (#17)
In conclusion, the innerHTML, DOM and html methods are used in following codes to show the event differences:
events of innerHtml and DOM dynamic html
function changeinnerhtml(_id)
{
var obj = document.getElementById(_id);
obj.onclick = function(){alert(_id + ' is clicked!')};
var objparent = document.getElementById('para1');
objparent.innerHTML += ' YAHOO click me!';
}
function changedom(_id)
{
var obj = document.getElementById(_id);
obj.onclick = function(){alert(_id + ' is clicked!')};
var objparent = document.getElementById('para1');
var objnew = document.createElement('a');
objnew.setAttribute("href","http://google.com.hk");
objnew.appendChild(document.createTextNode("GOOGLE click me!"));
obj.appendChild(objnew);
}
Compare about event handlers of innerHTML, DOM and static html
innerHTML here
DOM here
hard coded html here
(1)When you click "innerHTML here", no alert because parent tag (< p >) changed by innerHTML destroys the event.
(2)When you click "DOM here", alert prompts dom tree is built within parent tag (< p >).
(3)When you click "hard coded html here", alert should prompt because no structure changing within parent tag (< p >).
changeinnerhtml('span1');
changedom('span2');
Regards,
wongkachun