web-dev-qa-db-ja.com

IFRAMEの読み込みが完了したときのJavaScriptコールバック?

IFRAMEの読み込みが完了したら、コールバックを実行する必要があります。 IFRAMEのコンテンツを制御できないため、そこからコールバックを実行できません。

このIFRAMEはプログラムによって作成され、そのデータをコールバックの変数として渡し、iframeを破棄する必要があります。

何か案は?

編集:

ここに私が持っているものがあります:

function xssRequest(url, callback)
{
    var iFrameObj = document.createElement('IFRAME');
    iFrameObj.src = url;            
    document.body.appendChild(iFrameObj);   

    $(iFrameObj).load(function() 
    {
        document.body.removeChild(iFrameObj);
        callback(iFrameObj.innerHTML);
    });
}

これは、iFrameがロードされる前にコールバックするため、コールバックにはデータが返されません。

143
FlySwat

最初に、関数名xssRequestを使用すると、クロスサイトリクエストを試みているように聞こえます-そうだとすると、iframeのコンテンツを読み取ることができなくなります。

一方、iframeのURLがドメイン上にある場合、本文にアクセスできますが、タイムアウトを使用してiframeを削除すると、コールバックが正常に機能することがわかりました。

// possibly excessive use of jQuery - but I've got a live working example in production
$('#myUniqueID').load(function () {
  if (typeof callback == 'function') {
    callback($('body', this.contentWindow.document).html());
  }
  setTimeout(function () {$('#frameId').remove();}, 50);
});
49
Remy Sharp

私はjQueryを使用していますが、驚いたことに、重いページをテストしてロードしたので、これがロードされているようで、iframeのロードが表示されるまで数秒間アラートが表示されませんでした:

$('#the_iframe').load(function(){
    alert('loaded!');
});

したがって、jQueryを使用したくない場合は、ソースコードを見て、この関数がiframe DOM要素で異なる動作をするかどうかを確認します。興味があるので、後で自分で調べてここに投稿します。また、私は最新のクロムでのみテストしました。

35
Neo

Iframeタグは親ドキュメントのコンテンツを囲まないため、iframeのinnerHTMLは空白です。 iframeのsrc属性によって参照されるページからコンテンツを取得するには、iframeのcontentDocumentプロパティにアクセスする必要があります。ただし、srcが別のドメインからのものである場合、例外がスローされます。これは、他の人のページで任意のJavaScriptを実行することを防ぐセキュリティ機能であり、クロスサイトスクリプティングの脆弱性を作成します。以下は、私が話していることを説明するサンプルコードです。

<script src="http://prototypejs.org/assets/2009/8/31/prototype.js" type="text/javascript"></script>

<h1>Parent</h1>

<script type="text/javascript">
function on_load(iframe) {
  try {
    // Displays the first 50 chars in the innerHTML of the
    // body of the page that the iframe is showing.
    // EDIT 2012-04-17: for wider support, fallback to contentWindow.document
    var doc = iframe.contentDocument || iframe.contentWindow.document;
    alert(doc.body.innerHTML.substring(0, 50));
  } catch (e) {
    // This can happen if the src of the iframe is
    // on another domain
    alert('exception: ' + e);
  }
}
</script>
<iframe id="child" src="iframe_content.html" onload="on_load(this)"></iframe>

さらに例を見るには、これをiframeのコンテンツとして使用してみてください。

<h1>Child</h1>

<a href="http://www.google.com/">Google</a>

<p>Use the preceeding link to change the src of the iframe
to see what happens when the src domain is different from
that of the parent page</p>
8
allyourcode

WordのドキュメントやPDFなどのドキュメントがiframeにストリーミングされている場合にこれを行う必要があり、非常にうまく機能するソリューションが見つかりました。重要なのは、iframeでonreadystatechangedイベントを処理することです。

フレームの名前が「myIframe」だとしましょう。まず、コードスタートアップのどこかで(iframeの後の任意の場所でインラインします)、次のようなものを追加してイベントハンドラーを登録します。

document.getElementById('myIframe').onreadystatechange = MyIframeReadyStateChanged;

Iframeでonreadystatechage属性を使用できなかったため、その理由を思い出せませんが、アプリはIE 7およびSafari 3で動作する必要があったため、それが要因となった可能性があります。

完全な状態を取得する方法の例を次に示します。

function MyIframeReadyStateChanged()
{
    if(document.getElementById('myIframe').readyState == 'complete')
    {
        // Do your complete stuff here.
    }
}
7
Ryan Cook

IフレームのコンテンツがIEに完全に読み込まれたときに、待機中のスピナーdivを非表示にしたかったので、Stackoverflow.Comに記載されているすべてのソリューションを文字通り試しましたが、何もうまくいきませんでした。

それから、iフレームのコンテンツが完全にロードされると、$(Window)loadイベントが発生するかもしれないという考えがありました。そして、まさにそれが起こった。それで、私はこの小さなスクリプトを書き、魔法のように働きました。

     $(window).load(function () {
     //alert("Done window ready ");
     var lblWait = document.getElementById("lblWait");
     if (lblWait != null ) {
         lblWait.style.visibility = "false";
         document.getElementById("divWait").style.display = "none";
     }
 });

お役に立てれば。

6

あなたと同じような問題がありました。私がしたことは、jQueryと呼ばれるものを使用することです。次に、javascriptコードで行うことは次のとおりです。

$(function(){ //this is regular jQuery code. It waits for the dom to load fully the first time you open the page.

    $("#myIframeId").load(function(){
       callback($("#myIframeId").html());
       $("#myIframeId").remove();

    });

});

Htmlを取得する前にiFrameを削除するようです。今、私はそれに関する問題を見ています:p

お役に立てれば :)。

2
Automatico

私のプロジェクトには、うまく機能する同様のコードがあります。私のコードをあなたの関数に適応させると、解決策は次のようになります:

function xssRequest(url, callback)
{
    var iFrameObj = document.createElement('IFRAME');
    iFrameObj.id = 'myUniqueID';
    document.body.appendChild(iFrameObj);       
    iFrameObj.src = url;                        

    $(iFrameObj).load(function() 
    {
        callback(window['myUniqueID'].document.body.innerHTML);
        document.body.removeChild(iFrameObj);
    });
}

(1つまたは両方の原因):1. body要素に対して使用する必要がある2.ページDOMからiframeを削除しているため

2
Pier Luigi

ロードイベントは正しいと思います。正しくないのは、iframeコンテンツdomからコンテンツを取得する方法です。

必要なのは、iframeオブジェクトのhtmlではなく、iframeにロードされたページのhtmlです。

あなたがしなければならないのは、iFrameObj.contentDocumentでコンテンツドキュメントにアクセスすることです。現在のページと同じドメインにある場合、iframe内にロードされたページのDOMを返します。

Iframeを削除する前にコンテンツを取得します。

私はFirefoxとオペラでテストしました。

その後、$(childDom).html()または$(childDom).find('some selector') ...でデータを取得できると思います

1
user142830

私は過去にもまったく同じ問題を抱えていましたが、それを修正する唯一の方法は、iframeページにコールバックを追加することでした。もちろん、iframeコンテンツを制御できる場合にのみ機能します。

0
roryf