2016-02-05 169 views
3

首先,我看到这个问题问几次,但没有答案似乎令人满意。我正在寻找的是能够随时调用脚本并确定是否加载了iframe,并且不要将脚本限制为需要将其添加到onrame属性中的iframe标记本身。圣杯判断本地iframe是否已加载

这里有一些背景知识:我一直在研究一个不显眼的脚本来试图确定dom中的本地iframe是否已经加载,这是因为我们的客户之一在其网站上的iframe中包含了窗体,并且其中许多窗体在Lightbox中 - 随时动态地将iframe插入到dom中。我可以附加到灯箱的公开事件,但它是否可以在加载之前“捕捉”iframe。

让我再解释一下。

在我的测试中,我确定onload事件只会触发一次 - 并且只有在iframe实际加载之前绑定。例如:这个页面应该只警告“添加到iframe标签”,并且之后附加的侦听器不会触发 - 对我来说这是有道理的。 (我为简单的例子使用iframe onload属性)。

https://jsfiddle.net/g1bkd3u1/2/

<script> 
    function loaded() { 
     alert ("added to iframe tag"); 
     $("#test").load(function(){ 
      alert("added after load finished"); 
     }); 
    }; 
</script> 
<iframe onload="loaded()" id="test" src="https://en.wikipedia.org/wiki/HTML_element#Frames"></iframe> 

我的下一个方法是检查这似乎在几乎全天候工作在我的测试中,除了铬它报告“完成” iframe的文件准备状态 - 我所期待的“拒绝访问”用于跨域请求。我可以交叉域名错误,因为我可以忽略iframe,因为我只对本地iframe感兴趣 - firefox报告“unintialized”,我很好,因为我知道我可以附加一个onload事件。

请在Chrome中打开: https://jsfiddle.net/g1bkd3u1/

<iframe id="test" src="https://en.wikipedia.org/wiki/HTML_element#Frames"></iframe> 
<script> 
    alert($("#test").contents()[0].readyState); 
</script> 

我发现,如果我只等待100ms的 - 那么IFRAME似乎报告如预期(跨域安全例外 - 这就是我想要的 - 但我不想等待任意长度)。

https://jsfiddle.net/g1bkd3u1/4/

<iframe id="test" src="https://en.wikipedia.org/wiki/HTML_element#Frames"></iframe> 
<script> 
    setTimeout(function() { 
     try { 
      alert($("#test").contents()[0].readyState); 
     } catch (ignore) { 
      alert("cross domain request"); 
     } 
    }, 100); 
</script> 

我目前的解决方法/解决方案是增加onload事件处理程序,然后分离从DOM的iframe,然后将它放回在同一个地方的DOM - 现在onload事件会触发。这里有一个例子,等待3秒(希望有足够的时间加载iframe)来显示分离和重新连接导致iframe onload事件触发。

https://jsfiddle.net/g1bkd3u1/5/

<iframe id="test" src="https://en.wikipedia.org/wiki/HTML_element#Frames"></iframe> 
<script> 
    setTimeout(function(){ 
     var placeholder = $("<span>"); 
     $("#test").load(function(){ 
      alert("I know the frame has loaded now"); 
     }).after(placeholder).detach().insertAfter(placeholder); 
     placeholder.detach(); 
    }, 3000); 
</script> 

虽然这个作品它让我想知道如果有检查iframe的负载(悄悄)更好更优雅的技术?

谢谢你的时间。

回答

2

今天我遇到了一个错误,那就是我删除并重新插入iframe,在网站上破坏了一个wysiwyg编辑器。所以我创建了一个小的jQuery插件来检查iframe是否准备就绪。它不是生产准备好的,我没有测试过它,但它应该提供一个更好的替代方法来分离和重新附加一个iframe - 如果需要,它会使用轮询,但应该在iframe准备就绪时删除setInterval。

它可用于像:

$("iframe").iready(function() { ... }); 

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

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

示例等待,直到窗口已经加载到一个iframe动态地添加到DOM,它然后警告其文档的readyState的 - 这在铬显示“完整”,不正确。应该在调用iready函数之后调用并尝试输出文档的readyState证明跨域异常 - 这还没有经过彻底测试,但适用于我所需要的。

0

我遇到了类似的问题,因为我有一个iframe,并且需要在完成加载后修改其文档。

IF您知道或可以控制加载文件的iFrame中的内容,那么你可以简单地检查/补充一点,你可以检查是否存在以再更新的iframe文档的元素。 至少您知道您要使用的元素将被加载到文档中。

在我的情况下,我调用了一个函数,它自己检查我已知元素的存在性,这个元素在我需要更新的元素已经被加载之后总会被发现 - 如果没有找到它,本身再次通过setTimeout()。

function updateIframeContents() { 
    if ($("#theIframe").contents().find('.SaveButton').length > 0) { 
     // iframe DOM Manipulation 
    } else { 
     setTimeout(updateIframeContents, 250); 
    } 
} 

updateIframeContents();