web-dev-qa-db-ja.com

iframe.contentWindow == nullなのはなぜですか?

次のコードを使用して、iframeを動的に作成します。

var iframe_jquery = $("<iframe>")
    .addClass("foo")
    .appendTo(container); // container is a jQuery object containing a <div> which already exists

次に、そのcontentWindowにアクセスしたいが、nullです。

var iframe = iframe_jquery.get(0);
if (iframe){ // iFrame exists
    console.log(iframe.contentWindow); // Prints "null"
    var doc = iframe.contentWindow.document; // NullpointerException
}

だから、「iframeはまだ準備ができていないのではないか?」だから私は試しました:

iframe_jquery.ready(function(){
    var iframe = iframe_jquery.get(0);
    console.log(iframe.contentWindow); // Prints "null"
    var doc = iframe.contentWindow.document; // NullpointerException
});

同じ結果。

何が問題ですか?

43
Timo

先週iFrame(rtfエディターの作成)で遊んでいたときにこの問題が発生しましたが、まだ準備ができていません。

.ready()に入れるとうまくいくと思いましたが、.ready()はiFrameがコンテンツをロードしたときではなく、DOMの準備ができたときなので、コードをラップしました。 jQuery .load()を使用します。

だからこれを試してください:

$(function () {  
    $("#myiframe").load(function () {                        
        frames["myframe"].document.body.innerHTML = htmlValue;
    });
}); 

お役に立てれば

35
Losbear

問題は、<iframe>は、ページの実際のDOMに実際に追加されるまで「本物」ではありません。 これはデモンストレーションするフィドルです。

14
Pointy

ブラウザに応じて、documentまたは<iframe> 異なる場合があります。

これを処理する方法の例を次に示します。

if (iframe.contentDocument) // FF Chrome
  doc = iframe.contentDocument;
else if ( iframe.contentWindow ) // IE
  doc = iframe.contentWindow.document;
6
Gabe

ブックマークレット版

好奇心から、これをまとめると思った。 iframeとロードイベントは、異なるブラウザーではうまく再生されないことを忘れないでください(主に古いブラウザー、バラバラになっている、死んでいくはずのブラウザー) ... ...私の脳は、これがよりよくサポートされると判断しました(それがここでもそこでもないかどうか)

_$(function(){
  /// bind a listener for the bespoke iframeload event
  $(window).bind('iframeload', function(){
    /// access the contents of the iframe using jQuery notation
    iframe.show().contents().find('body').html('hello');
  });
  /// create your iframe
  var iframe = $('<iframe />')
        /// by forcing our iframe to evaluate javascript in the path, we know when it's ready
        .attr('src', 'javascript:(function(){try{p=window.parent;p.jQuery(p).trigger(\'iframeload\');}catch(ee){};})();')
        /// insert the iframe into the live DOM
        .appendTo('body');
});
_

このアプローチをとる理由は、通常iframe自体の内部からロードイベントをトリガーする方がはるかに優れているためです。ただし、これは適切なドキュメントをiframeにロードすることを意味するため、ダイナミックiframeの場合、これは少し面倒です。これは、ドキュメントをロードすることと、ロードしないことの混合です。

上記は、私がこれまでにテストしたすべてのもので機能します-はい

この投稿について私が言う1つのポジティブなことは、iframeのドキュメントにアクセスするために.contents()の使用を導入することです。これは少なくとも少し便利です...

2
Pebbl

また、iframeのonload属性を設定することにより、iframeの読み込みが完了したときに実行される関数を作成することもできます。

1
Vladivarius