Rilevamento del caricamento del contenuto Iframe (Cross browser)


90

Sto cercando di rilevare quando un iframe e il suo contenuto sono stati caricati ma non ho molta fortuna. La mia applicazione accetta alcuni input nei campi di testo nella finestra principale e aggiorna l'iframe per fornire un'anteprima in tempo reale

Ho iniziato con il seguente codice (YUI) per rilevare quando si verifica l'evento di caricamento dell'iframe.

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

"preview-pane" è l'ID del mio iframe e sto usando YUI per allegare il gestore di eventi. Tuttavia, il tentativo di accedere al corpo nel mio callback (al caricamento dell'iframe) non riesce, penso perché l'iframe viene caricato prima che il gestore di eventi sia pronto. Questo codice funziona se ritardo il caricamento dell'iframe facendo dormire lo script php che lo genera.

Fondamentalmente, sto chiedendo qual è l'approccio corretto tra i browser per rilevare quando l'iframe è stato caricato e il suo documento è pronto?


1
Iniziare con YUI è una cattiva idea (così come qualsiasi altra libreria JS). Perché? Perché non puoi proprio sapere quale magia stia facendo quella biblioteca. Se non supportano completamente il "caricamento", è meglio farlo da soli in un javascript chiaro e leggibile.
Christian

2
Puoi spesso leggere il codice sorgente della libreria @Christian. Trovo che questo di solito ti dia ottimi consigli su come farlo da solo indipendentemente dal fatto che tu usi la loro implementazione o meno.
AJP

@AJP Hai frainteso il mio punto. Se stai facendo qualcosa di cui non sei sicuro, è meglio avere meno codice in modo da avere meno spazio per gli errori.
Christian

2
Dipende da che punto di vista lo guardi. Sapevo che la gestione degli eventi di YUI funzionava in quel momento, quindi non dovevo preoccuparmi di quella parte del codice. Sapevo anche come scrivere il mio gestore addEvent, non che funzionasse meglio di YUI riguardo a questo problema.
David Snabel-Caunt

1
@Nico La domanda si riferisce a YUI e $ è un alias del wrapper Dom di YUI.
David Snabel-Caunt

Risposte:


73

rilevare quando l'iframe è stato caricato e il suo documento è pronto?

È l'ideale se puoi ottenere l'iframe per dirti da uno script all'interno del frame. Ad esempio, potrebbe chiamare direttamente una funzione genitore per dirgli che è pronta. È sempre necessaria attenzione con l'esecuzione di codice cross-frame poiché le cose possono accadere in un ordine che non ti aspetti. Un'altra alternativa è impostare "var isready = true;" nel proprio ambito e fare in modo che lo script principale annusi "contentWindow.isready" (e in caso contrario aggiungi il gestore onload).

Se per qualche motivo non è pratico far cooperare il documento iframe, hai il tradizionale problema della corsa al caricamento, ovvero che anche se gli elementi sono uno accanto all'altro:

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

non vi è alcuna garanzia che l'elemento non sia già stato caricato al momento dell'esecuzione dello script.

Le vie d'uscita dalle gare di carico sono:

  1. su IE, puoi usare la proprietà 'readyState' per vedere se qualcosa è già caricato;

  2. se è accettabile avere l'elemento disponibile solo con JavaScript abilitato, è possibile crearlo dinamicamente, impostando la funzione evento 'onload' prima di impostare l'origine e aggiungerlo alla pagina. In questo caso non può essere caricato prima di aver impostato la richiamata;

  3. il modo vecchio stile di includerlo nel markup:

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

I gestori "onsomething" inline in HTML sono quasi sempre la cosa sbagliata e da evitare, ma in questo caso a volte è l'opzione meno cattiva.


Grazie. La mia soluzione controlla readyState (se esiste), quindi la lunghezza innerHTML degli elementi del corpo per vedere se è stata caricata. In caso contrario, collega il gestore dell'evento di caricamento. Sembra funzionare bene
David Snabel-Caunt

8
-1 - gli eventi inline non sono "cattivi", questa è solo la moda attuale. In effetti, gli eventi inline sono più facili da eseguire il debug e da comprendere, a differenza delle loro controparti magiche (che, d'altra parte, sono più facili da collegare, impilare e utilizzare senza problemi).
Christian

1
@Christian, gli eventi in linea sono anche l'opzione migliore quando devi allegare un evento a ogni elemento di un elenco molto lungo. Poiché stai già eseguendo un ciclo per creare l'elenco sul lato server, è molto più efficiente allegare anche l'evento inline.
haknick

16
@haknick Non vorresti utilizzare un singolo listener di eventi nell'elenco e utilizzare un delegato di eventi? Questo sarebbe più efficiente.
David Snabel-Caunt

4
Questo non funzionerebbe se l'iframe fosse interdominio. Lo script all'interno dell'iframe non può accedere alla finestra principale.
Sudheer Someshwara

48

Vedi questo post del blog. Usa jQuery, ma dovrebbe aiutarti anche se non lo stai usando.

Fondamentalmente lo aggiungi al tuo file document.ready()

$('iframe').load(function() {
    RunAfterIFrameLoaded();
});

Interessante, ma il problema che ho è con gli eventi di caricamento e la tempistica. Sto ascoltando l'evento di caricamento come consigliato da quell'articolo.
David Snabel-Caunt

l'ho provato con console.log. viene registrato dopo che l'iframe è stato caricato.
shorif2000

12

Per coloro che utilizzano React, rilevare un evento di caricamento iframe della stessa origine è semplice come impostare il onLoadlistener di eventi sull'elemento iframe.

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


L' onLoadevento può essere attivato solo per iframe della stessa origine?
L_K

2

Per chiunque utilizzi Ember, dovrebbe funzionare come previsto:

<iframe onLoad={{action 'actionName'}}  frameborder='0' src={{iframeSrc}} />
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.