Iframeコンテンツが読み込まれたときの検出(クロスブラウザー)


90

iframeとそのコンテンツが読み込まれたが、運が悪いときを検出しようとしています。私のアプリケーションは、親ウィンドウのテキストフィールドに入力を取り、iframeを更新して「ライブプレビュー」を提供します

iframeの読み込みイベントがいつ発生するかを検出するために、次のコード(YUI)から始めました。

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

'プレビューペイン'はiframeのIDで、YUIを使用してイベントハンドラーをアタッチしています。ただし、(iframeの読み込み時に)コールバックで本文にアクセスしようとすると失敗します。イベントハンドラーの準備が完了する前にiframeが読み込まれるためです。このコードは、iframeを生成するphpスクリプトをスリープさせることによってiframeの読み込みを遅らせると機能します。

基本的に、iframeが読み込まれ、ドキュメントの準備ができたことを検出するために、ブラウザー間で正しいアプローチは何ですか?


1
YUIから始めるのは悪い考えです(他のJSライブラリも同様です)。どうして?そのライブラリが何をしているのか、あなたには分からないからです。「ロード」を完全にサポートできない場合は、明確で読みやすいjavascriptを使用して自分で行うことをお勧めします。
クリスチャン

2
ライブラリ@Christianのソースコードをよく読むことができます。これは通常、その実装を使用するかどうかに関係なく、自分でそれを行う方法に関する素晴らしいヒントを提供します。
AJP 2013年

@AJPあなたは私のポイントを誤解しました。確信が持てないことをしている場合は、コードを減らしてエラーの余地を少なくすることをお勧めします。
クリスチャン

2
見方次第です。当時、YUIのイベント処理が機能していることがわかっていたので、コードのその部分について心配する必要はありませんでした。また、私は自分のaddEventハンドラーを作成する方法も知っていました。この問題に関して、YUIよりもうまく機能したわけではありません。
David Snabel-Caunt 2013年

1
@Nico質問はYUIを参照し、$はYUIのDomラッパーのエイリアスです。
David Snabel-Caunt、2014

回答:


73

iframeが読み込まれ、ドキュメントの準備ができたことを検出する方法

フレーム内のスクリプトからiframeに自分自身を教えてくれるのが理想的です。たとえば、親関数を直接呼び出して、準備ができていることを伝えることができます。予期しない順序で発生する可能性があるため、クロスフレームコードの実行には常に注意が必要です。もう1つの方法は、「var isready = true;」を設定することです。独自のスコープ内にあり、 'contentWindow.isready'の親スクリプトスニフを持っています(そうでない場合はonloadハンドラーを追加します)。

何らかの理由でiframeドキュメントを連携させることが実用的でない場合は、従来のロードレースの問題があります。つまり、要素が互いに隣接している場合でも、

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

スクリプトの実行時にアイテムが読み込まれていないという保証はありません。

ロードレースから抜け出す方法は次のとおりです。

  1. IEでは、 'readyState'プロパティを使用して、何かが既にロードされているかどうかを確認できます。

  2. JavaScriptが有効になっている場合にのみアイテムを使用できる場合は、ソースを設定してページに追加する前に「onload」イベント関数を設定して、アイテムを動的に作成できます。この場合、コールバックが設定されるまでロードできません。

  3. それをマークアップに含める昔ながらの方法:

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

HTMLのインラインの 'onsomething'ハンドラーは、ほとんどの場合間違ったものであり、回避する必要がありますが、この場合、最も悪いオプションである場合があります。


ありがとう。私のソリューションは、readyState(存在する場合)、次にbody要素のinnerHTMLの長さをチェックして、読み込まれたかどうかを確認します。そうでない場合は、ロードイベントハンドラをアタッチします。[OK]を動作しているようです
デビッドSnabel-Caunt

8
-1-インラインイベントは「不良」ではありません。これは現在の流行です。実際、インラインイベントは、マジックイベントとは異なり、デバッグや理解が簡単です(一方で、接続、スタック、シームレスに使用するのが簡単です)。
クリスチャン

1
@Christianのインラインイベントも、非常に長いリストのすべての要素にイベントをアタッチする必要がある場合に最適なオプションです。サーバー側でリストを作成するために既にループしているので、インラインイベントもアタッチする方がはるかに効率的です。
ハクニック

16
@haknickリストで単一のイベントリスナーを使用し、イベントデリゲートを使用しませんか?これはより効率的です。
David Snabel-Caunt

4
iframeがクロスドメインの場合、これは機能しません。iframe内のスクリプトは親ウィンドウにアクセスできません。
Sudheer Someshwara 2013

48

このブログ投稿を参照してください。jQueryを使用しますが、使用していない場合でも役立つはずです。

基本的にこれをあなたに追加します document.ready()

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

興味深いですが、私が抱えている問題は、ロードイベントとタイミングです。その記事でアドバイスされているように、loadイベントをリッスンしています。
David Snabel-Caunt、2009

私はこれを試しましたconsole.log。iframeが読み込まれた後にログに記録されます。
shorif2000

12

Reactを使用する場合、同じオリジンのiframeロードイベントを検出することは、onLoadiframe要素にイベントリスナーを設定するのと同じくらい簡単です。

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


onLoadイベントは同じ生成元のiframeに対してのみトリガーできますか?
L_K 2018

2

Emberを使用している人にとっては、これは期待どおりに機能するはずです。

<iframe onLoad={{action 'actionName'}}  frameborder='0' src={{iframeSrc}} />
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.