Wykrywanie załadowania zawartości iframe (wiele przeglądarek)

91

Próbuję wykryć, kiedy element iframe i jego zawartość zostały załadowane, ale nie mam szczęścia. Moja aplikacja pobiera dane w polach tekstowych w oknie nadrzędnym i aktualizuje ramkę iframe, aby zapewnić „podgląd na żywo”

Zacząłem od następującego kodu (YUI), aby wykryć, kiedy wystąpi zdarzenie ładowania iframe.

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

„okienko podglądu” to identyfikator mojego elementu iframe i używam YUI do dołączania obsługi zdarzeń. Jednak próba uzyskania dostępu do treści w moim wywołaniu zwrotnym (po załadowaniu elementu iframe) kończy się niepowodzeniem, ponieważ element iframe ładuje się, zanim program obsługi zdarzeń jest gotowy. Ten kod działa, jeśli opóźnię ładowanie iframe, powodując uśpienie skryptu PHP, który go generuje.

Zasadniczo pytam, jakie jest prawidłowe podejście w różnych przeglądarkach do wykrywania, kiedy element iframe został załadowany, a jego dokument jest gotowy?

David Snabel-Caunt
źródło
1
Rozpoczęcie pracy z YUI to zły pomysł (podobnie jak każda inna biblioteka JS). Czemu? Ponieważ po prostu nie możesz wiedzieć, jaką magię robi ta biblioteka. Jeśli nie mogą w pełni obsługiwać funkcji „wczytaj”, lepiej zrób to samodzielnie w jasnym i czytelnym języku JavaScript.
Christian
2
Często możesz przeczytać kod źródłowy biblioteki @Christian. Uważam, że zazwyczaj daje to świetne wskazówki, jak to zrobić samodzielnie, niezależnie od tego, czy korzystasz z ich implementacji, czy nie.
AJP
@AJP Źle zrozumiałeś mój punkt widzenia. Jeśli robisz coś, czego nie jesteś pewien, lepiej mieć mniej kodu, aby było mniej miejsca na błędy.
Christian
2
Zależy, jak na to spojrzysz. Wiedziałem, że obsługa zdarzeń YUI działała w tamtym czasie, więc nie musiałem się martwić o tę część kodu. Wiedziałem też, jak napisać własny program obsługi addEvent, co nie znaczy, że działał lepiej niż YUI w odniesieniu do tego problemu.
David Snabel-Caunt
1
@Nico Pytanie odnosi się do YUI, a $ jest aliasem do opakowania YUI Dom.
David Snabel-Caunt

Odpowiedzi:

73

wykryć, kiedy element iframe został załadowany, a jego dokument jest gotowy?

Idealnie byłoby, gdyby element iframe mógł sam się rozpoznać na podstawie skryptu wewnątrz ramki. Na przykład może bezpośrednio wywołać funkcję nadrzędną, aby powiedzieć, że jest gotowa. Zawsze należy zachować ostrożność przy wykonywaniu kodu między ramkami, ponieważ może się zdarzyć w kolejności, której się nie spodziewasz. Inną alternatywą jest ustawienie „var isready = true;” we własnym zakresie i mieć skrypt nadrzędny wyszukujący „contentWindow.isready” (i jeśli nie, dodaj procedurę obsługi ładowania).

Jeśli z jakiegoś powodu niepraktyczne jest współdziałanie dokumentu iframe, masz tradycyjny problem z wyścigiem ładowania, a mianowicie, że nawet jeśli elementy są tuż obok siebie:

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

nie ma gwarancji, że element nie zostanie załadowany do czasu wykonania skryptu.

Sposoby wyjścia z wyścigów na ładowanie to:

  1. w IE możesz użyć właściwości „readyState”, aby sprawdzić, czy coś jest już załadowane;

  2. jeśli dopuszczalny jest element dostępny tylko z włączoną obsługą JavaScript, można go utworzyć dynamicznie, ustawiając funkcję zdarzenia „onload” przed ustawieniem źródła i dołączeniem do strony. W tym przypadku nie można go załadować przed ustawieniem wywołania zwrotnego;

  3. oldschoolowy sposób umieszczania go w znacznikach:

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

Wbudowane funkcje obsługi „onsomething” w HTML prawie zawsze są niewłaściwe i należy ich unikać, ale w tym przypadku czasami jest to najmniej zła opcja.

bobince
źródło
Dzięki. Moje rozwiązanie sprawdza readyState (jeśli istnieje), a następnie długość elementów ciała innerHTML, aby sprawdzić, czy zostało załadowane. Jeśli nie, dołącza procedurę obsługi zdarzeń ładowania. Wydaje się, że działa dobrze
David Snabel-Caunt
8
-1 - zdarzenia inline nie są „złe”, to tylko obecna moda. W rzeczywistości zdarzenia inline są łatwiejsze do debugowania i zrozumienia, w przeciwieństwie do ich magicznych odpowiedników (które z drugiej strony są łatwiejsze do bezproblemowego dołączania, układania i używania).
Christian
1
@Christian, zdarzenia inline są również najlepszą opcją, gdy chcesz dołączyć wydarzenie do każdego elementu bardzo długiej listy. Ponieważ już tworzysz listę po stronie serwera w pętli, dołączenie zdarzenia inline-event jest znacznie wydajniejsze.
haknick
16
@haknick Czy nie chciałbyś użyć jednego detektora zdarzenia na liście i użyć pełnomocnika zdarzenia? To byłoby bardziej efektywne.
David Snabel-Caunt
4
To nie zadziała, jeśli element iframe jest międzydomenowy. Skrypt wewnątrz iframe nie może uzyskać dostępu do okna nadrzędnego.
Sudheer Someshwara 8-13
48

Zobacz ten wpis na blogu. Używa jQuery, ale powinno ci pomóc, nawet jeśli go nie używasz.

Zasadniczo dodajesz to do swojego document.ready()

$('iframe').load(function() {
    RunAfterIFrameLoaded();
});
kgiannakakis
źródło
Ciekawe, ale problem jaki mam jest ze zdarzeniami obciążenia i czasem. Nasłuchuję zdarzenia ładowania zgodnie z zaleceniami w tym artykule.
David Snabel-Caunt
próbowałem tego z console.log. jest rejestrowany po załadowaniu elementu iframe.
shorif2000
12

Dla tych, którzy używają Reacta, wykrycie zdarzenia ładowania onLoadelementu iframe z tego samego źródła jest tak proste, jak ustawienie detektora zdarzeń w elemencie iframe.

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

Farzad YZ
źródło
Czy onLoadzdarzenie może zostać wywołane tylko w przypadku elementu iframe tego samego pochodzenia?
L_K
2

Dla każdego, kto używa Ember, powinno to działać zgodnie z oczekiwaniami:

<iframe onLoad={{action 'actionName'}}  frameborder='0' src={{iframeSrc}} />
Max Wallace
źródło