188

誰かが画像をクリックしたときに iframe を動的に表示するためにjQuery シックボックスを使用しています。この iframe では、galleriaの JavaScript ライブラリを使用して複数の画像を表示しています。

問題は$(document).ready、iframe での起動が早すぎるように見え、iframe コンテンツがまだ読み込まれていないため、DOM 要素にガレリア コー​​ドが適切に適用されていないことです。 $(document).readyiframe の親の準備完了状態を使用して、iframe の準備ができているかどうかを判断しているようです。

document ready によって呼び出された関数を別の関数で抽出し、100 ミリ秒のタイムアウト後に呼び出すとします。動作しますが、遅いコンピューターでは本番環境でチャンスを逃すことはできません。

$(document).ready(function() { setTimeout(ApplyGalleria, 100); });

私の質問: 動的 iframe の準備ができており、それが親であるだけでなく、コードを実行できるようにするには、どの jQuery イベントにバインドする必要がありますか?

4

10 に答える 10

294

同様の質問に答えました ( IFRAME のロードが終了したときの Javascript コールバックを参照してください)。次のコードを使用して、iframe ロード イベントを制御できます。

function callIframe(url, callback) {
    $(document.body).append('<IFRAME id="myId" ...>');
    $('iframe#myId').attr('src', url);

    $('iframe#myId').load(function() {
        callback(this);
    });
}

iframe を扱う際に、ドキュメントの準備完了イベントの代わりに load イベントを使用するのに十分であることがわかりました。

于 2008-10-15T15:41:30.593 に答える
31

jQuery 1.3.2を使用すると、次のことがうまくいきました:

$('iframe').ready(function() {
  $('body', $('iframe').contents()).html('Hello World!');
});

リビジョン:!実際、上記のコードは Firefox で動作するように見えることがありますが、Opera では動作するようには見えません。

代わりに、目的のためにポーリング ソリューションを実装しました。簡略化すると、次のようになります。

$(function() {
  function manipIframe() {
    el = $('body', $('iframe').contents());
    if (el.length != 1) {
      setTimeout(manipIframe, 100);
      return;
    }
    el.html('Hello World!');
  }
  manipIframe();
});

これには、呼び出された iframe ページのコードは必要ありません。すべてのコードが存在し、親フレーム/ウィンドウから実行されます。

于 2009-04-09T17:37:46.587 に答える
15

IFrame では、通常、ブロックの最後に小さなスクリプトを配置して、この問題を解決します。

<body>
The content of your IFrame
<script type="text/javascript">
//<![CDATA[
   fireOnReadyEvent();
   parent.IFrameLoaded();
//]]>
</script>
</body>

これは私にとってほとんどの場合機能します。最も単純で単純な解決策が最も適切な場合もあります。

于 2008-10-15T15:54:38.727 に答える
9

DrJokepu と David Murdoch のアイデアに従って、より完全なバージョンを実装しました。親とiframe の両方に jQueryが必要であり、iframe をコントロールする必要があります。

iframe コード:

var iframe = window.frameElement;

if (iframe){
    iframe.contentDocument = document;//normalization: some browsers don't set the contentDocument, only the contentWindow

    var parent = window.parent;
    $(parent.document).ready(function(){//wait for parent to make sure it has jQuery ready
        var parent$ = parent.jQuery;

        parent$(iframe).trigger("iframeloading");

        $(function(){
            parent$(iframe).trigger("iframeready");
        });

        $(window).load(function(){//kind of unnecessary, but here for completion
            parent$(iframe).trigger("iframeloaded");
        });

        $(window).unload(function(e){//not possible to prevent default
            parent$(iframe).trigger("iframeunloaded");
        });

        $(window).on("beforeunload",function(){
            parent$(iframe).trigger("iframebeforeunload");
        });
    });
}

親テスト コード:

$(function(){
    $("iframe").on("iframeloading iframeready iframeloaded iframebeforeunload iframeunloaded", function(e){
        console.log(e.type);
    });
});
于 2013-04-30T01:49:51.910 に答える
4

問題の解決策を見つけました。

iframe を開くシックボックス リンクをクリックすると、TB_iframeContent の ID を持つ iframe が挿入されます。

iframe コードのイベントに依存する代わりに$(document).ready、親ドキュメントの iframe の load イベントにバインドする必要があります。

$('#TB_iframeContent', top.document).load(ApplyGalleria);

このコードは iframe にありますが、親ドキュメントのコントロールのイベントにバインドします。FireFox と IE で動作します。

于 2008-10-15T17:00:18.937 に答える
1

jQuery ajaxを使用してPDFをブラウザキャッシュにロードしています。次に、ブラウザーのキャッシュに既にあるデータを使用して埋め込み要素を作成します。iframe でも動くと思います。


var url = "http://example.com/my.pdf";
// show spinner
$.mobile.showPageLoadingMsg('b', note, false);
$.ajax({
    url: url,
    cache: true,
    mimeType: 'application/pdf',
    success: function () {
        // display cached data
        $(scroller).append('<embed type="application/pdf" src="' + url + '" />');
        // hide spinner
        $.mobile.hidePageLoadingMsg();
    }
});

http ヘッダーも正しく設定する必要があります。


HttpContext.Response.Expires = 1;
HttpContext.Response.Cache.SetNoServerCaching();
HttpContext.Response.Cache.SetAllowResponseInBrowserHistory(false);
HttpContext.Response.CacheControl = "Private";
于 2012-08-16T14:32:45.223 に答える
1

これを試して、

<iframe id="testframe" src="about:blank" onload="if (testframe.location.href != 'about:blank') testframe_loaded()"></iframe>

あとは、JavaScript 関数 testframe_loaded() を作成するだけです。

于 2009-10-12T17:04:03.720 に答える
1

これは、私がクライアントと遭遇した正確な問題でした。iframe 対応で動作するように見える小さな jquery プラグインを作成しました。ポーリングを使用して、iframe ソースと組み合わせた内部ドキュメント URL と組み合わせた iframe ドキュメントの readyState をチェックして、iframe が実際に「準備完了」であることを確認します。

「onload」の問題は、DOM に追加されている実際の iframe にアクセスする必要があることです。アクセスしない場合は、iframe の読み込みをキャッチする必要がありますが、キャッシュされている場合はそうでない可能性があります。私が必要としていたのは、いつでも呼び出すことができ、iframe が「準備完了」かどうかを判断できるスクリプトでした。

質問は次のとおりです。

ローカル iframe が読み込まれたかどうかを判断するための聖杯

そして、これが私が最終的に思いついたjsfiddleです。

https://jsfiddle.net/q0smjkh5/10/

上記の jsfiddle では、onload が iframe を dom に追加するのを待ってから、iframe の内部ドキュメントの準備完了状態 (ウィキペディアを指しているためクロスドメインである必要があります) をチェックしていますが、Chrome は「完了」と報告しているようです。プラグインの iready メソッドは、iframe が実際に準備ができたときに呼び出されます。コールバックは、内部ドキュメントの準備完了状態を再度チェックしようとします - 今回はクロスドメインリクエストを報告します (これは正しいです) - とにかく、私が必要としているものにはうまくいくようで、他の人に役立つことを願っています.

<script>
  (function($, document, undefined) {
    $.fn["iready"] = function(callback) {
      var ifr = this.filter("iframe"),
          arg = arguments,
          src = this,
          clc = null, // collection
          lng = 50,   // length of time to wait between intervals
          ivl = -1,   // interval id
          chk = function(ifr) {
            try {
              var cnt = ifr.contents(),
                  doc = cnt[0],
                  src = ifr.attr("src"),
                  url = doc.URL;
              switch (doc.readyState) {
                case "complete":
                  if (!src || src === "about:blank") {
                    // we don't care about empty iframes
                    ifr.data("ready", "true");
                  } else if (!url || url === "about:blank") {
                    // empty document still needs loaded
                    ifr.data("ready", undefined);
                  } else {
                    // not an empty iframe and not an empty src
                    // should be loaded
                    ifr.data("ready", true);
                  }

                  break;
                case "interactive":
                  ifr.data("ready", "true");
                  break;
                case "loading":
                default:
                  // still loading
                  break;   
              }
            } catch (ignore) {
              // as far as we're concerned the iframe is ready
              // since we won't be able to access it cross domain
              ifr.data("ready", "true");
            }

            return ifr.data("ready") === "true";
          };

      if (ifr.length) {
        ifr.each(function() {
          if (!$(this).data("ready")) {
            // add to collection
            clc = (clc) ? clc.add($(this)) : $(this);
          }
        });
        if (clc) {
          ivl = setInterval(function() {
            var rd = true;
            clc.each(function() {
              if (!$(this).data("ready")) {
                if (!chk($(this))) {
                  rd = false;
                }
              }
            });

            if (rd) {
              clearInterval(ivl);
              clc = null;
              callback.apply(src, arg);
            }
          }, lng);
        } else {
          clc = null;
          callback.apply(src, arg);
        }
      } else {
        clc = null;
        callback.apply(this, arguments);
      }
      return this;
    };
  }(jQuery, document));
</script>
于 2016-02-10T14:17:45.190 に答える