Detectar cuándo se ha cargado el contenido de Iframe (navegador cruzado)

90

Estoy tratando de detectar cuándo se ha cargado un iframe y su contenido, pero no tengo mucha suerte. Mi aplicación toma alguna entrada en campos de texto en la ventana principal y actualiza el iframe para proporcionar una 'vista previa en vivo'

Comencé con el siguiente código (YUI) para detectar cuándo ocurre el evento de carga del iframe.

$E.on('preview-pane', 'load', function(){
    previewBody = $('preview-pane').contentWindow.document.getElementsByTagName('body')[0];
}

'preview-pane' es el ID de mi iframe y estoy usando YUI para adjuntar el controlador de eventos. Sin embargo, intentar acceder al cuerpo en mi devolución de llamada (al cargar el iframe) falla, creo que porque el iframe se carga antes de que el controlador de eventos esté listo. Este código funciona si retardo la carga del iframe haciendo que el script php que lo genera duerma.

Básicamente, pregunto cuál es el enfoque correcto en los navegadores para detectar cuándo se ha cargado el iframe y su documento está listo.

David Snabel-Caunt
fuente
1
Comenzar con YUI es una mala idea (al igual que cualquier otra biblioteca JS). ¿Por qué? Porque simplemente no puedes saber qué magia está haciendo esa biblioteca. Si no pueden soportar la "carga" por completo, será mejor que lo haga usted mismo en un javascript claro y legible.
Christian
2
A menudo puede leer el código fuente de la biblioteca @Christian. Creo que esto generalmente le brinda excelentes consejos sobre cómo hacerlo usted mismo, independientemente de si luego usa su implementación o no.
AJP
@AJP No entendiste mi punto. Si está haciendo algo de lo que no está seguro, es mejor tener menos código para que haya menos espacio para errores.
Christian
2
Depende de cómo lo mires. Sabía que el manejo de eventos de YUI funcionaba en ese momento, así que no tuve que preocuparme por esa parte del código. También sabía cómo escribir mi propio controlador addEvent, aunque no funcionaba mejor que YUI con respecto a este problema.
David Snabel-Caunt
1
@Nico La pregunta se refiere a YUI y $ es un alias del envoltorio Dom de YUI.
David Snabel-Caunt

Respuestas:

73

para detectar cuando el iframe se ha cargado y su documento está listo?

Es ideal si puede hacer que el iframe se lo diga a sí mismo desde un script dentro del marco. Por ejemplo, podría llamar a una función principal directamente para indicarle que está lista. Siempre se requiere cuidado con la ejecución de código entre marcos, ya que pueden suceder cosas en un orden inesperado. Otra alternativa es establecer 'var isready = true;' en su propio alcance, y haga que el script principal rastree 'contentWindow.isready' (y agregue el controlador de carga si no es así).

Si por alguna razón no es práctico que el documento iframe coopere, tienes el problema tradicional de carrera de carga, es decir, incluso si los elementos están uno al lado del otro:

<img id="x" ... />
<script type="text/javascript">
    document.getElementById('x').onload= function() {
        ...
    };
</script>

no hay garantía de que el elemento no se haya cargado antes de que se ejecute el script.

Las formas de salir de las carreras de carga son:

  1. en IE, puede usar la propiedad 'readyState' para ver si algo ya está cargado;

  2. Si tener el elemento disponible solo con JavaScript habilitado es aceptable, puede crearlo dinámicamente, configurando la función de evento 'onload' antes de configurar la fuente y agregarla a la página. En este caso, no se puede cargar antes de que se establezca la devolución de llamada;

  3. la forma de la vieja escuela de incluirlo en el marcado:

    <img onload="callback(this)" ... />

Los manejadores "onsomething" en línea en HTML son casi siempre incorrectos y deben evitarse, pero en este caso, a veces es la opción menos mala.

bobince
fuente
Gracias. Mi solución verifica readyState (si existe), luego los elementos del cuerpo innerHTML length para ver si se ha cargado. De lo contrario, adjunta el controlador de eventos de carga. Parece que funciona bien
David Snabel-Caunt
8
-1 - Los eventos en línea no son "malos", eso es solo la moda actual. De hecho, los eventos en línea son más fáciles de depurar y comprender, a diferencia de sus contrapartes mágicas (que, por otro lado, son más fáciles de adjuntar, apilar y usar sin problemas).
Christian
1
@Christian, los eventos en línea también son la mejor opción cuando necesita adjuntar un evento a cada elemento de una lista muy larga. Dado que ya está haciendo un bucle para crear la lista en el lado del servidor, es mucho más eficiente adjuntar también el evento en línea.
haknick
16
@haknick ¿No le gustaría usar un solo detector de eventos en la lista y usar un delegado de eventos? Esto sería más eficiente.
David Snabel-Caunt
4
Esto no funcionaría si el iframe es de dominio cruzado. El script dentro del iframe no puede acceder a la ventana principal.
Sudheer Someshwara
48

Vea esta publicación de blog. Utiliza jQuery, pero debería ayudarte incluso si no lo estás utilizando.

Básicamente, agrega esto a su document.ready()

$('iframe').load(function() {
    RunAfterIFrameLoaded();
});
kgiannakakis
fuente
Interesante, pero el problema que tengo es con los eventos de carga y el tiempo. Estoy escuchando el evento de carga según lo recomendado por ese artículo.
David Snabel-Caunt
He intentado esto con console.log. se registra después de que se haya cargado el iframe.
shorif2000
12

Para aquellos que usan React, detectar un evento de carga de iframe del mismo origen es tan simple como configurar el onLoaddetector de eventos en el elemento iframe.

<iframe src={'path-to-iframe-source'} onLoad={this.loadListener} frameBorder={0} />

Farzad YZ
fuente
¿Puede el onLoadevento solo activarse para iframe del mismo origen?
L_K
2

Para cualquiera que use Ember, esto debería funcionar como se esperaba:

<iframe onLoad={{action 'actionName'}}  frameborder='0' src={{iframeSrc}} />
Max Wallace
fuente