¿Es posible agregar a internalHTML sin destruir los detectores de eventos de los descendientes?
En el siguiente código de ejemplo, adjunto un onclick
controlador de eventos al intervalo que contiene el texto "foo". El controlador es una función anónima que muestra un archivo alert()
.
Sin embargo, si lo asigno al nodo principal innerHTML
, este onclick
controlador de eventos se destruye; al hacer clic en "foo" no aparece el cuadro de alerta.
¿Se puede arreglar esto?
<html>
<head>
<script type="text/javascript">
function start () {
myspan = document.getElementById("myspan");
myspan.onclick = function() { alert ("hi"); };
mydiv = document.getElementById("mydiv");
mydiv.innerHTML += "bar";
}
</script>
</head>
<body onload="start()">
<div id="mydiv" style="border: solid red 2px">
<span id="myspan">foo</span>
</div>
</body>
</html>
El uso .insertAdjacentHTML()
conserva los detectores de eventos y es compatible con los principales navegadores . Es un reemplazo simple de una línea para .innerHTML
.
var html_to_insert = "<p>New paragraph</p>";
// with .innerHTML, destroys event listeners
document.getElementById('mydiv').innerHTML += html_to_insert;
// with .insertAdjacentHTML, preserves event listeners
document.getElementById('mydiv').insertAdjacentHTML('beforeend', html_to_insert);
El 'beforeend'
argumento especifica en qué parte del elemento se insertará el contenido HTML. Las opciones son 'beforebegin'
, 'afterbegin'
, 'beforeend'
y 'afterend'
. Sus ubicaciones correspondientes son:
<!-- beforebegin -->
<div id="mydiv">
<!-- afterbegin -->
<p>Existing content in #mydiv</p>
<!-- beforeend -->
</div>
<!-- afterend -->
Desafortunadamente, la asignación a innerHTML
causa la destrucción de todos los elementos secundarios, incluso si intenta agregarlos. Si desea conservar los nodos secundarios (y sus controladores de eventos), necesitará utilizar funciones DOM :
function start() {
var myspan = document.getElementById("myspan");
myspan.onclick = function() { alert ("hi"); };
var mydiv = document.getElementById("mydiv");
mydiv.appendChild(document.createTextNode("bar"));
}
Editar: la solución de Bob, de los comentarios. ¡Publica tu respuesta, Bob! Obtenga crédito por ello. :-)
function start() {
var myspan = document.getElementById("myspan");
myspan.onclick = function() { alert ("hi"); };
var mydiv = document.getElementById("mydiv");
var newcontent = document.createElement('div');
newcontent.innerHTML = "bar";
while (newcontent.firstChild) {
mydiv.appendChild(newcontent.firstChild);
}
}