2013-06-06 16 views
9

Sono stato sorpreso di scoprire che quanto segue non sembra funzionare, nella misura in cui l'evento DOMContentLoaded non viene attivato (this.els è un oggetto di elementi).Rileva DOMContentLoaded in iframe

this.els.stage_ifr.prop('src', 'templates/'+ee.globals.creating+'/item'+this.id); 
this.els.stage_ifr[0].addEventListener('DOMContentLoaded', function() { 
    alert('loaded!'); 
}, false); 

La pagina viene caricata nell'ifrile, ma senza richiamata. Il livello DOM zero onload, tuttavia, funziona.

this.els.stage_ifr[0].onload = function() { alert('loaded!'); }; //<-- fires 

Una soluzione è quella di preparare un oggetto jQuery differita globalmente accessibile nella pagina superiore e risolvere tramite un evento DOM-ready sparato dalla pagina chiamata in iframe, piuttosto che ascoltare per DOM-ready dalla genitore. Pagina

Paraent: pagina

dfd = new $.Deferred; 
dfd.done(function() { alert("frame page's DOM is ready!"); }); 

Telaio:

$(function() { window.parent.dfd.resolve(); }); 

Tuttavia, sarebbe bene sapere cosa succede con il primo approccio ...

+1

Eccezionalmente viene fornito un collegamento a MSDN: [elemento iframe] (http://msdn.microsoft.com/en-us/library/ms535258%28v=vs.85%29.aspx). Come puoi leggere su quella pagina, 'DOMContentLoaded' non può essere collegato a un 'iframe'. – Teemu

+0

Interessante - Avrei dovuto pensare che fosse perfettamente soddisfacente se il frame è dello stesso dominio. Se questo è davvero un caso chiuso, sentitevi liberi di postarlo come risposta e accetterò. – Utkanos

+0

Puoi provare a collegare 'DOMContentLoaded' (un metodo di' document' only) a 'stage_ifr [0] .contentDocument', non sono sicuro, se esistesse nel momento in cui ne avrai bisogno ... – Teemu

risposta

12

Nel processo di rispondere this question , Ho scoperto il motivo per cui il listener di eventi DOMContentLoaded non funziona. Mi sembra che tu abbia due problemi.

Per prima cosa, stai cercando di ascoltare l'evento DOMContentLoaded sull'iFrame stesso. Questo non è un evento iFrame. È un evento del documento. Quindi devi raggiungere l'iFrame per ottenere il contentWindow e quindi ottenere il documento da quello. Questo porta al secondo problema.

In secondo luogo, quando un iFrame viene creato per la prima volta, contiene un dummy document che NON è lo stesso documento che sarà eventualmente presente quando il contenuto dinamico viene caricato tramite l'attributo .src. Quindi, anche se avete fatto:

this.els.stage_ifr.contentWindow.document 

per ottenere il documento nel iFrame, non sarà necessariamente il documento a destra e, quindi, l'evento DOMContentLoaded non si attiverà su di esso (che ho visto questo comportamento in Chrome).


MDN dice che si può intercettare l'evento DOMFrameContentLoaded sulla iFrame stesso e questo corrisponderà con cui il documento sottostante diventa realtà DOMContentLoaded. Sfortunatamente, non riesco a far funzionare questo evento in nessun browser. Quindi, in questo momento, l'unico aggeggio che conosco è quello di attivare l'evento load dall'interno dello stesso iFrame dove può ascoltare il proprio evento DOMContentLoaded (può chiamare alla finestra padre se necessario) o basta ascoltare l'evento load sull'oggetto iFrame e sapere che non si attiva finché non vengono caricate anche risorse come fogli di stile e immagini nell'iFrame.


In ogni caso, ho pensato di spiegare qualcosa di quello che stava accadendo con il codice iniziale e offrire un'altra soluzione, anche se questa domanda è stata pubblicata più di un anno fa (anche se mai risposto).


Aggiornamento:

ho sviluppato un metodo di tracciamento DOMContentLoaded per un iFrame caricato con la stessa origine come il suo genitore. Puoi vedere il codice here.

+0

Mi stavo già chiedendo perché 'readyState' è sempre' completato' in Chrome. Ora so che è perché Chrome imposta un documento vuoto e crea il vero documento iframe (correlato all'attributo src) dopo di ciò. Un cattivo comportamento, se Chrome gestisse questo come un altro browser, potremmo semplicemente usare 'readyState'. – dude

+0

http://stackoverflow.com/a/36155560/3894981 – dude

+0

'DOMFrameContentLoaded' non è solo un [evento specifico di Mozilla] (https://developer.mozilla.org/en-US/docs/Web/Events#Mozilla -specific_events) ma anche un "evento specifico del componente aggiuntivo", che è "mai esposto ai contenuti web e può essere utilizzato solo in contesto di contenuto cromato". –

5

Dopo aver provato diverse opzioni che ho trovato il seguente codice funziona per me:

var iframe = document.getElementById("app-frame-id"); 
iframe.contentWindow.addEventListener("DOMContentLoaded", onFrameDOMContentLoaded, true); 
function onFrameDOMContentLoaded() { 
    console.log("DOMContentLoaded"); 
}; 
+1

Questo non funziona quando si modifica la fonte dell'iframe –

+0

Sembra funzionare per me. Ma potresti descrivere cosa esattamente fa e perché non stai assegnando questo evento alla proprietà document di 'contentWindow'? – dude

1

Questo potrebbe essere più di un hack, ma mi ha aiutato a risolvere un problema simile.

Sto ascoltando per onmouseenter del contenuto della cornice ora.

Questo evento si attiva prima di load (se l'utente sposta il mouse). Ma come nel mio caso ho bisogno dell'evento per l'inizializzazione di un menu di scelta rapida, usare comunque il mouse era una condizione preliminare.

Si attiva anche quando il contenuto della cornice cambia sotto il mouse.

+0

Approccio interessante. Grazie per il testa a testa. – Utkanos