I’m trying to add an event listener to some elements which I generate in the loop. I must use div.lastChild – although in this example it’s pretty stupid. But that’s just demonstration:
<div id="someArea">
</div>
<script type="text/javascript">
var func = function() {
alert('Callback works');
}
var func1 = function() {
alert('Test');
}
var func2 = function() {
alert('Test2');
}
var div = document.getElementById("someArea");
var callbacks = [func, func1, func2];
for(var i = 0; i <= 2; i++) {
div.innerHTML += '<input type="button" value="' + i + '" />';
(function(i) {
console.log(div.lastChild);
div.lastChild.addEventListener('click', callbacks[i], false);
}(i));
}
</script>
The event works only for the last button. What am I missing here?
Why it’s not working.
When you do this…
…in every iteration of the loop you’re destroying the old DOM nodes inside
div(and therefore their handlers), and recreating new nodes (but no handlers). The destruction includes theinputelements that were added in previous iterations.That’s why only the last one works, since after that point, you’ve assigned the handler to the last element, but the other ones are brand new and untouched.
A solution.
Instead of treating the DOM as though it was a string of HTML markup, consider using DOM methods for element creation…
Notice that I removed the immediately invoked function. For your code, it was unnecessary since
iis being evaluated in the loop instead of later in the handler.The DOM is not HTML, but
.innerHTMLmakes you think it is.It’s important to understand
innerHTML. When working with the DOM, there is no HTML markup. So when you get the.innerHTML, the DOM is being analyzed, and a new HTML string is created.When you assign to
.innerHTML, you’re destroying all the current content, and replacing it with new nodes created from the HTML string.So when you do…
…you’re first creating the new HTML string from the current content, then concatenating the new HTML content to the string, then destroying the old nodes and creating new ones from the new string.
This is terribly inefficient, and as you’ve already seen, it destroys any data associated with the original elements, including handlers.