Erkennen, wann Iframe-Inhalte geladen wurden (Cross-Browser)

90

Ich versuche festzustellen, wann ein Iframe und sein Inhalt geladen wurden, habe aber nicht viel Glück. Meine Anwendung nimmt einige Eingaben in Textfelder im übergeordneten Fenster vor und aktualisiert den Iframe, um eine Live-Vorschau bereitzustellen.

Ich habe mit dem folgenden Code (YUI) begonnen, um festzustellen, wann das iframe-Ladeereignis auftritt.

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

'Vorschau-Bereich' ist die ID meines Iframes und ich verwende YUI, um den Ereignishandler anzuhängen. Der Versuch, in meinem Rückruf auf den Body zuzugreifen (beim Laden des Iframes), schlägt jedoch fehl, da der Iframe geladen wird, bevor der Ereignishandler bereit ist. Dieser Code funktioniert, wenn ich das Laden des Iframes verzögere, indem ich das PHP-Skript, das ihn generiert, in den Ruhezustand versetze.

Grundsätzlich frage ich, was der richtige Ansatz für alle Browser ist, um festzustellen, wann der Iframe geladen wurde und sein Dokument bereit ist.

David Snabel-Caunt
quelle
1
Mit YUI zu beginnen ist eine schlechte Idee (wie auch jede andere JS-Bibliothek). Warum? Weil Sie einfach nicht wissen können, welche Magie diese Bibliothek tut. Wenn sie das "Laden" nicht vollständig unterstützen können, tun Sie dies besser selbst in klarem und lesbarem Javascript.
Christian
2
Sie können häufig den Quellcode der Bibliothek @Christian lesen. Ich finde, dies gibt Ihnen normalerweise großartige Tipps, wie Sie es selbst tun können, unabhängig davon, ob Sie dann deren Implementierung verwenden oder nicht.
AJP
@AJP Du hast meinen Standpunkt falsch verstanden. Wenn Sie etwas tun, dessen Sie sich nicht sicher sind, ist es besser, weniger Code zu haben, damit weniger Fehler auftreten können.
Christian
2
Kommt darauf an, wie du es betrachtest. Ich wusste, dass die Ereignisbehandlung von YUI zu dieser Zeit funktionierte, sodass ich mich nicht um diesen Teil des Codes kümmern musste. Ich wusste auch, wie man meinen eigenen addEvent-Handler schreibt, nicht, dass er in Bezug auf dieses Problem besser funktioniert als YUI.
David Snabel-Caunt
1
@Nico Die Frage bezieht sich auf YUI und $ ist ein Alias ​​für den Dom-Wrapper von YUI.
David Snabel-Caunt

Antworten:

73

um festzustellen, wann der Iframe geladen wurde und sein Dokument bereit ist?

Es ist ideal, wenn Sie den Iframe dazu bringen können, sich anhand eines Skripts im Frame zu informieren. Zum Beispiel könnte es eine übergeordnete Funktion direkt aufrufen, um ihr mitzuteilen, dass sie bereit ist. Bei der Ausführung von Cross-Frame-Code ist immer Vorsicht geboten, da Dinge in einer Reihenfolge passieren können, die Sie nicht erwarten. Eine andere Alternative besteht darin, 'var isready = true' zu setzen. in seinem eigenen Bereich, und lassen Sie das übergeordnete Skript nach 'contentWindow.isready' schnüffeln (und fügen Sie den Onload-Handler hinzu, wenn nicht).

Wenn es aus irgendeinem Grund nicht praktikabel ist, das iframe-Dokument zusammenzuarbeiten, haben Sie das traditionelle Problem des Laderennens, nämlich selbst wenn die Elemente direkt nebeneinander liegen:

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

Es gibt keine Garantie dafür, dass das Element zum Zeitpunkt der Ausführung des Skripts noch nicht geladen ist.

Die Auswege aus Lastrennen sind:

  1. Im IE können Sie die Eigenschaft 'readyState' verwenden, um festzustellen, ob bereits etwas geladen ist.

  2. Wenn es akzeptabel ist, das Element nur mit aktiviertem JavaScript verfügbar zu haben, können Sie es dynamisch erstellen, indem Sie die Ereignisfunktion "Onload" festlegen, bevor Sie die Quelle festlegen und an die Seite anhängen. In diesem Fall kann es nicht geladen werden, bevor der Rückruf eingestellt wurde.

  3. die alte Art, es in das Markup aufzunehmen:

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

Inline-Onsomething-Handler in HTML sind fast immer das Falsche und sollten vermieden werden. In diesem Fall ist dies jedoch manchmal die am wenigsten schlechte Option.

Bobince
quelle
Vielen Dank. Meine Lösung überprüft den readyState (falls vorhanden) und dann die innerHTML-Länge der Body-Elemente, um festzustellen, ob sie geladen wurden. Wenn nicht, hängt der Ladeereignishandler an. Scheint in
Ordnung zu sein
8
-1 - Inline-Events sind nicht "schlecht", das ist nur die aktuelle Modeerscheinung. Inline-Ereignisse sind im Gegensatz zu ihren magischen Gegenstücken (die andererseits einfacher anzuhängen, zu stapeln und nahtlos zu verwenden sind) einfacher zu debuggen und zu verstehen.
Christian
1
@Christian, Inline-Ereignisse sind auch die beste Option, wenn Sie jedem Element einer sehr langen Liste ein Ereignis hinzufügen müssen. Da Sie bereits eine Schleife erstellen, um die Liste auf der Serverseite zu erstellen, ist es viel effizienter, das Inline-Ereignis anzuhängen.
Haknick
16
@haknick Möchten Sie nicht einen einzelnen Ereignis-Listener in der Liste und einen Ereignis-Delegaten verwenden? Dies wäre effizienter.
David Snabel-Caunt
4
Dies würde nicht funktionieren, wenn der Iframe domänenübergreifend ist. Das Skript in iframe kann nicht auf das übergeordnete Fenster zugreifen.
Sudheer Someshwara
49

Siehe diesen Blog-Beitrag. Es verwendet jQuery, sollte Ihnen aber auch dann helfen, wenn Sie es nicht verwenden.

Grundsätzlich fügen Sie dies zu Ihrem document.ready()

$('iframe').load(function() {
    RunAfterIFrameLoaded();
});
kgiannakakis
quelle
Interessant, aber das Problem, das ich habe, ist mit den Ladeereignissen und dem Timing. Ich warte auf das Ladeereignis, wie in diesem Artikel empfohlen.
David Snabel-Caunt
Ich habe es mit versucht console.log. Es wird protokolliert, nachdem der Iframe geladen wurde.
Shorif2000
12

Für diejenigen, die React verwenden, ist das Erkennen eines Iframe-Ladeereignisses mit demselben Ursprung so einfach wie das Festlegen des onLoadEreignis-Listeners für das Iframe-Element.

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

Farzad YZ
quelle
Kann ein onLoadEreignis nur für einen Iframe mit demselben Ursprung ausgelöst werden?
L_K
2

Für alle, die Ember verwenden, sollte dies wie erwartet funktionieren:

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