2011-03-07 13 views
17

He estado jugando con la adición de elementos iframe ocultos a una página, y quiero manipular el DOM de estos una vez cargados. Me di cuenta de que no puedo comenzar a manipular el DOM inmediatamente después de agregar el iframe a una página, ya que aún no se ha cargado. Esto no se puede hacer con el evento DOMContentLoaded ya que se dispara contra el documento que no existe en el iframe hasta que se lo agrega a la página, por lo que debemos usar el evento load.iframe comportamiento de onload vs addEventListener ('load')

Aquí hay un código de prueba:

var iframe = document.createElement('iframe'); 
iframe.onload = function() { console.log('loaded!'); }; 
document.getElementsByTagName('body')[0].appendChild(iframe); 

esto funciona como se espera, sin embargo, cuando lo cambio a addEventListener que ni siquiera se añaden a la DOM:

var iframe = document.createElement('iframe'); 
iframe.addEventListener('load', function() { console.log('loaded!'); }); 
document.getElementsByTagName('body')[0].appendChild(iframe); 

no he t probado attachEvent en IE.

¿Alguien arrojó algo de luz sobre esto?

Respuesta

19

addEventListener() función necesita 3 argumentos! Echar un vistazo a https://developer.mozilla.org/en/DOM/element.addEventListener

La tercera argumento está marcado como opcional, pero luego escriben:

Tenga en cuenta que este parámetro no es opcional en todas las versiones del navegador.

No estoy seguro de cuándo y dónde se requiere, pero mis pruebas en FF4 inició una excepción cuando se llama al addEventListener con 2 argumentos:

excepción no detectada: [Excepción ..."No suficientes argumentos" nsresult: "0x80570001 (NS_ERROR_XPC_NOT_ENOUGH_ARGS)" ubicación: "marco JS :: http://localhost/index.php :: :: línea 10" de datos: no]

Por cierto, su código funciona bien en Chrome [la cadena loaded! está registrada en la consola].

Al igual que FF, IE9 necesita el tercer argumento en el modo de estándares (con <!DOCTYPE html>). IE9 es el primer IE que admite el modelo de eventos del W3C. Entonces en las versiones anteriores tenemos que probar attachEvent. No tengo IEs anteriores, pero funcionó en IE7/8 Standards Mode e incluso en el modo Quirks en IE9. Aquí está el código que utilicé:

<!DOCTYPE html> 
<html> 
<head><title></title></head> 
<body> 
<script> 
    window.onload=function(){ 
     var iframe = document.createElement('iframe'); 
     var func = function() { console.log('loaded!');}; 
     if(iframe.addEventListener) 
      iframe.addEventListener('load', func, true); 
     else if(iframe.attachEvent) 
      iframe.attachEvent('onload',func); 
     document.body.appendChild(iframe); 
    } 
</script> 
</body> 
</html> 
+0

Creo que tu punto sobre el 3er parámetro era exactamente el problema, no estaba obteniendo el error que hiciste, pero probablemente fue suprimido de alguna manera. No recuerdo, pero claramente no lo probé en Chrome (me parece tonto ...). Agradable, gracias. – roryf

0

¿Funciona el primer ejemplo? No estoy seguro exactamente lo que está buscando, pero esto debe iluminar cuando los eventos funcionan: jQuery fuente document.ready

$(document).ready equivalent without jQuery

addEventListener no funciona en IE, así que si eso es donde se está probando, a continuación, el 2nd fallaría antes de que el iframe se anexe.

También podría agregar una devolución de llamada desde la página, aunque (por ejemplo, usando jQuery para no reinventar la rueda) sospecho que $(iframe).ready() {..} le daría un comportamiento consistente.

+0

No puedo usar el evento 'ready' ya que esto requiere un documento que aún no existe, a menos que me falta algo. – roryf

+0

Sugiero usar la misma lógica que jquery document.ready en el elemento iframe, p. Ej. al igual que este plugin parece hacer: http://www.thunderguy.com/semicolon/2007/08/14/elementready-jquery-plugin/, pero aún no está claro si hay algún problema con el primer fragmento de código. ¿Estás tratando de conectarlo? antes de que se carguen las imágenes? Alternativamente, suponiendo que controle el código en el iframe, puede usar document.ready allí para devolver la llamada a una función utilizando parent. –

+0

El primer fragmento de código funciona correctamente (como se dijo), sin embargo, la propiedad 'onload' no es estándar (AFAIK) y me pregunté por qué la forma compatible con los estándares (ignorando IE) no funcionaba. El propio iframe no apunta a otra página, quiero cargarlo en blanco y llenar el DOM. – roryf

1

Esto es trabajo para mí:

html:

iframe source code: <br /> 
<textarea id="output" rows="20" cols="60">loading ...</textarea> 

Javascript (en documentReady):

var iframe = document.createElement('iframe'); 
iframe.id = iframe.name = "testframe"; 
iframe.src = "http://fiddle.jshell.net"; 
iframe.width = 400; 
iframe.height = 100; 
iframe.style.display = "none"; 

if (iframe.addEventListener) 
    iframe.addEventListener("load", loaded, false); 
else 
    iframe.attachEvent("onload", loaded); 

function loaded() { 
    var html; 
    if (iframe.contentDocument) 
     html = iframe.contentDocument.getElementsByTagName("HTML")[0].innerHTML; 
    else 
     html = window.frames[iframe.name].document.getElementsByTagName("html")[0].innerHTML; 

    document.getElementById("output").value = html; 
} 

document.getElementsByTagName("body")[0].appendChild(iframe); 

Ver la demo en: http://jsfiddle.net/WcKEz/

Funciona con addEventListener, pero incluye la alternativa para attachEvent. Acceso al DOM del IFRAME por supuesto solo en el mismo dominio.