检测 Iframe 内容何时加载(跨浏览器)
Posted
技术标签:
【中文标题】检测 Iframe 内容何时加载(跨浏览器)【英文标题】:Detecting when Iframe content has loaded (Cross browser) 【发布时间】:2010-10-19 13:58:46 【问题描述】:我正在尝试检测 iframe 及其内容何时加载但运气不佳。我的应用程序在父窗口的文本字段中输入一些内容并更新 iframe 以提供“实时预览”
我开始使用以下代码 (YUI) 来检测 iframe 加载事件何时发生。
$E.on('preview-pane', 'load', function()
previewBody = $('preview-pane').contentWindow.document.getElementsByTagName('body')[0];
'preview-pane' 是我的 iframe 的 ID,我正在使用 YUI 来附加事件处理程序。但是,尝试在我的回调中访问正文(在 iframe 加载时)失败,我认为是因为 iframe 在事件处理程序准备好之前加载。如果我通过使生成它的 php 脚本休眠来延迟 iframe 加载,则此代码有效。
基本上,我问的是跨浏览器检测 iframe 何时加载且其文档何时准备就绪的正确方法是什么?
【问题讨论】:
从 YUI 开始是个坏主意(以及任何其他 JS 库)。为什么?因为你不知道图书馆在做什么魔法。如果他们不能完全支持“加载”,你最好用清晰易读的javascript自己做。 您可以经常阅读库@Christian 的源代码。我发现无论您是否使用它们的实现,这通常都会为您提供如何自己做的很好的提示。 @AJP 你误解了我的意思。如果你正在做一些你不确定的事情,最好少写一些代码,这样出错的空间就会更小。 取决于你如何看待它。我知道当时 YUI 的事件处理是有效的,所以我不必担心那部分代码。我也知道如何编写自己的 addEvent 处理程序,但在这个问题上它的效果并不比 YUI 好。 @Nico 问题指的是 YUI,$ 是 YUI 的 Dom 包装器的别名。 【参考方案1】:检测 iframe 何时加载且其文档准备就绪?
如果您可以让 iframe 从框架内的脚本告诉您自己,那就太理想了。例如,它可以直接调用父函数来告诉它它已经准备好了。跨框架代码执行始终需要小心,因为事情可能会以您意想不到的顺序发生。另一种选择是在自己的范围内设置“var isready= true;”,并让父脚本嗅探“contentWindow.isready”(如果没有,则添加 onload 处理程序)。
如果由于某种原因让 iframe 文档协作不切实际,您就会遇到传统的负载竞争问题,即即使元素彼此相邻:
<img id="x" ... />
<script type="text/javascript">
document.getElementById('x').onload= function()
...
;
</script>
无法保证该项目在脚本执行时尚未加载。
解决负载竞争的方法是:
在 IE 上,您可以使用“readyState”属性来查看是否已加载;
如果可以接受仅启用 JavaScript 的项目,您可以动态创建它,在设置源和附加到页面之前设置“onload”事件函数。在这种情况下,在设置回调之前无法加载;
将其包含在标记中的老式方法:
<img onload="callback(this)" ... />
html 中的内联“onsomething”处理程序几乎总是错误的,应该避免,但在这种情况下,有时它是最不坏的选择。
【讨论】:
谢谢。我的解决方案检查 readyState(如果存在),然后检查 body 元素的 innerHTML 长度以查看它是否已加载。如果不是,则附加加载事件处理程序。似乎工作正常 -1 - 内联事件并不“坏”,这只是当前的时尚。事实上,内联事件更容易调试和理解,不像它们的魔法对应物(另一方面,更容易无缝地附加、堆叠和使用)。 @Christian,当您需要将事件附加到很长列表的每个元素时,内联事件也是最佳选择。由于您已经在服务器端循环构建列表,因此附加内联事件效率更高。 @haknick 您不想在列表中使用单个事件侦听器并使用事件委托吗? 这样会更有效率。 如果 iframe 是跨域的,这将不起作用。 iframe 内的脚本无法访问父窗口。【参考方案2】:请参阅 this 博客文章。它使用 jQuery,但即使您不使用它,它也会对您有所帮助。
基本上你把它添加到你的document.ready()
$('iframe').load(function()
RunAfterIFrameLoaded();
);
【讨论】:
有趣,但我遇到的问题是加载事件和时间。我正在按照那篇文章的建议监听 load 事件。 我已经用console.log
尝试过这个。它在 iframe 加载后被记录。【参考方案3】:
对于那些使用 React 的人来说,检测同源 iframe 加载事件就像在 iframe 元素上设置 onLoad
事件监听器一样简单。
<iframe src='path-to-iframe-source' onLoad=this.loadListener frameBorder=0 />
【讨论】:
onLoad
事件是否只能触发同源iframe?【参考方案4】:
对于使用 Ember 的任何人,这应该可以按预期工作:
<iframe onLoad=action 'actionName' frameborder='0' src=iframeSrc />
【讨论】:
【参考方案5】:-
此代码检测何时加载了 iframe 内容不使用 jquery:
信用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);
-
此代码与 jquery 一起工作:
信用: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);
【讨论】:
【参考方案6】:jQuery(document).ready(function ()
jQuery('iframe').load(function()
console.log(jQuery(this))
);
)
【讨论】:
以上是关于检测 Iframe 内容何时加载(跨浏览器)的主要内容,如果未能解决你的问题,请参考以下文章