首页 文章

jQuery .ready在动态插入的iframe中

提问于
浏览
177

我们正在使用jQuery thickbox在有人点击图片时动态显示iframe . 在这个iframe中,我们使用galleria一个javascript库来显示多张图片 .

问题似乎是iframe中的 $(document).ready 似乎太快被解雇了,iframe内容甚至还没有被加载,所以galleria代码没有在DOM元素上正确应用 . $(document).ready 似乎使用iframe父级就绪状态来判断iframe是否准备就绪 .

如果我们在单独的函数中提取由文档就绪调用的函数,并在超过100毫秒后调用它 . 它有效,但我们不能利用慢速计算机 生产环境 机会 .

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

我的问题:我们应该绑定哪个jQuery事件,以便在动态iframe准备就绪时能够执行我们的代码而不仅仅是父代码?

9 回答

  • 27

    在IFrame中,我通常通过在块的最末端放一个小脚来解决这个问题:

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

    这项工作大部分时间都适合我 . 有时,最简单,最天真的解决方案是最合适的 .

  • 283

    找到问题的解决方案 .

    当您点击打开iframe的厚盒链接时,会插入ID为TB_iframeContent的iframe .

    我只需要绑定到父文档中iframe的load事件,而不是依赖于iframe代码中的 $(document).ready 事件:

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

    此代码位于iframe中,但绑定到父文档中的控件事件 . 它适用于FireFox和IE .

  • 0

    我正在使用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";
    
  • 1

    试试这个,

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

    您需要做的就是创建JavaScript函数testframe_loaded() .

  • 1

    使用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页面中的代码 . 所有代码都驻留在父框架/窗口中并从中执行 .

  • 4

    按照约克博士和大卫默多克的想法,我实施了一个更完整的版本 . 它在父级和iframe上都是 requires jQuery,iframe在你的控件中 .

    iframe code:

    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");
            });
        });
    }
    

    parent test code:

    $(function(){
        $("iframe").on("iframeloading iframeready iframeloaded iframebeforeunload iframeunloaded", function(e){
            console.log(e.type);
        });
    });
    
  • 1

    我回答了类似的问题(见Javascript callback when IFRAME is finished loading?) . 您可以使用以下代码获取对iframe加载事件的控制权:

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

    在处理iframe时,我发现使用load事件而不是文档就绪事件已经足够好了 .

  • 8

    基本上其他人已经发布但IMHO有点清洁:

    $('<iframe/>', {
        src: 'https://example.com/',
        load: function() {
            alert("loaded")
        }
    }).appendTo('body');
    
  • 14

    这是我与客户遇到的确切问题 . 我创建了一个小jquery插件,似乎适用于iframe准备 . 它使用轮询来检查iframe文档readyState与内部文档URL结合iframe源以确保iframe实际上是“就绪” .

    “onload”的问题是你需要访问添加到DOM的实际iframe,如果你没有,那么你需要尝试捕获iframe加载,如果它被缓存,那么你可能不会 . 我需要的是一个可以随时调用的脚本,并确定iframe是否“准备好” .

    这是问题:

    Holy grail for determining whether or not local iframe has loaded

    这是我最终提出的jsfiddle .

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

    在上面的jsfiddle中,我正在等待onload将一个iframe附加到dom,然后检查iframe的内部文档的就绪状态 - 这应该是跨域的,因为它指向维基百科 - 但Chrome似乎报告“完整” . 然后在iframe实际就绪时调用插件的iready方法 . 回调试图再次检查内部文档的就绪状态 - 这次报告跨域请求(这是正确的) - 无论如何它似乎适用于我需要的东西并希望它可以帮助其他人 .

    <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>
    

相关问题