检测 Iframe 内容何时加载(跨浏览器)

我试图检测 iframe 及其内容何时已加载,但运气不佳。我的应用程序在父窗口的文本字段中接受一些输入,并更新 iframe 以提供一个“实时预览”

我从以下代码(YUI)开始,以检测 iframe 加载事件何时发生。

$E.on('preview-pane', 'load', function(){
previewBody = $('preview-pane').contentWindow.document.getElementsByTagName('body')[0];
}

“预览窗格”是我的 iframe 的 ID,我使用 YUI 附加事件处理程序。然而,尝试访问我的回调函数体(在 iframe 加载时)失败了,我认为这是因为 iframe 在事件处理程序准备好之前就加载了。如果我通过让生成 iframe 的 php 脚本处于睡眠状态来延迟加载 iframe,那么这段代码就可以工作。

基本上,我是在询问跨浏览器检测 iframe 何时加载并且其文档准备就绪的正确方法是什么?

202432 次浏览

See this blog post. It uses jQuery, but it should help you even if you are not using it.

Basically you add this to your document.ready()

$('iframe').load(function() {
RunAfterIFrameLoaded();
});

to detect when the iframe has loaded and its document is ready?

It's ideal if you can get the iframe to tell you itself from a script inside the frame. For example it could call a parent function directly to tell it it's ready. Care is always required with cross-frame code execution as things can happen in an order you don't expect. Another alternative is to set ‘var isready= true;’ in its own scope, and have the parent script sniff for ‘contentWindow.isready’ (and add the onload handler if not).

If for some reason it's not practical to have the iframe document co-operate, you've got the traditional load-race problem, namely that even if the elements are right next to each other:

<img id="x" ... />
<script type="text/javascript">
document.getElementById('x').onload= function() {
...
};
</script>

there is no guarantee that the item won't already have loaded by the time the script executes.

The ways out of load-races are:

  1. on IE, you can use the ‘readyState’ property to see if something's already loaded;

  2. if having the item available only with JavaScript enabled is acceptable, you can create it dynamically, setting the ‘onload’ event function before setting source and appending to the page. In this case it cannot be loaded before the callback is set;

  3. the old-school way of including it in the markup:

    <img onload="callback(this)" ... />

Inline ‘onsomething’ handlers in HTML are almost always the wrong thing and to be avoided, but in this case sometimes it's the least bad option.

For those using React, detecting a same-origin iframe load event is as simple as setting onLoad event listener on iframe element.

<iframe src={'path-to-iframe-source'} onLoad={this.loadListener} frameBorder={0} />

For anyone using Ember, this should work as expected:

<iframe onLoad=\{\{action 'actionName'}}  frameborder='0' src=\{\{iframeSrc}} />
jQuery(document).ready(function () {
jQuery('iframe').load(function() {
console.log(jQuery(this))
});
})
  1. This code detects when iframe content has loaded Without jquery:

Credit Biranchi's answer

    // wait for the doc to load (wait for the class 'iframe...' to load) before sending the script
checkIframeLoaded()
    

function checkIframeLoaded() {
// console.log(" function checked")
// Get a handle to the iframe element
var iframe = document.getElementsByClassName("docs-texteventtarget-iframe")[0];
console.log("iframe", iframe)
// check if the iframe is loaded or not (= undefined = null)
if (iframe == null) {
// If we are here, it is not loaded. Set things up so we check the status again in 1000 milliseconds
window.setTimeout(checkIframeLoaded, 1000);
} else {
var iframeDoc = iframe.contentDocument || iframe.contentWindow.document;
// Check if loading is completed
if (iframeDoc.readyState == 'complete') {
    

// The loading is complete, call the function we want executed once the iframe is loaded
iframeDoc.addEventListener("keydown", dispatchkeyboard, false);
} else {
// even if the iframe is loaded the "readystate may not be completed yet" so we need to recall the function.
window.setTimeout(checkIframeLoaded, 1000);
}
}
}
    

  

  1. This code works with jquery:

Credit: gilles bousquet's answer

    // use jquery to detect when iframe is loaded but doesn't work offline
// (this code needs jQuery because it use the "$" below). if you use it; add this require in the ===usercript=== section
//  @require    http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js


var editingIFrame = $('iframe.docs-texteventtarget-iframe')[0];
if (editingIFrame) {
console.log("inside doc.getele")
editingIFrame.contentDocument.addEventListener("keydown", dispatchkeyboard, false);
}