2016-02-05 64 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(); 
相關問題