/**
* Will wait for an iframe to be ready
* for DOM manipulation. Just listening for
* the load event will only work if the iframe
* is not already loaded. If so, it is necessary
* to observe the readyState. The issue here is
* that Chrome will initialize iframes with
* "about:blank" and set its readyState to complete.
* So it is furthermore necessary to check if it's
* the readyState of the target document property.
* Errors that may occur when trying to access the iframe
* (Same-Origin-Policy) will be catched and the error
* function will be called.
* @param {jquery} $i - The jQuery iframe element
* @param {function} successFn - The callback on success. Will
* receive the jQuery contents of the iframe as a parameter
* @param {function} errorFn - The callback on error
*/
var onIframeReady = function($i, successFn, errorFn) {
try {
const iCon = $i.first()[0].contentWindow,
bl = "about:blank",
compl = "complete";
const callCallback = () => {
try {
const $con = $i.contents();
if($con.length === 0) { // https://git.io/vV8yU
throw new Error("iframe inaccessible");
}
successFn($con);
} catch(e) { // accessing contents failed
errorFn();
}
};
const observeOnload = () => {
$i.on("load.jqueryMark", () => {
try {
const src = $i.attr("src").trim(),
href = iCon.location.href;
if(href !== bl || src === bl || src === "") {
$i.off("load.jqueryMark");
callCallback();
}
} catch(e) {
errorFn();
}
});
};
if(iCon.document.readyState === compl) {
const src = $i.attr("src").trim(),
href = iCon.location.href;
if(href === bl && src !== bl && src !== "") {
observeOnload();
} else {
callCallback();
}
} else {
observeOnload();
}
} catch(e) { // accessing contentWindow failed
errorFn();
}
};
字符串
使用示例
由两个文件(index.html和iframe.html)组成:索引.html:
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Parent</title>
</head>
<body>
<script src="https://code.jquery.com/jquery-1.12.2.min.js"></script>
<script>
$(function() {
/**
* Will wait for an iframe to be ready
* for DOM manipulation. Just listening for
* the load event will only work if the iframe
* is not already loaded. If so, it is necessary
* to observe the readyState. The issue here is
* that Chrome will initialize iframes with
* "about:blank" and set its readyState to complete.
* So it is furthermore necessary to check if it's
* the readyState of the target document property.
* Errors that may occur when trying to access the iframe
* (Same-Origin-Policy) will be catched and the error
* function will be called.
* @param {jquery} $i - The jQuery iframe element
* @param {function} successFn - The callback on success. Will
* receive the jQuery contents of the iframe as a parameter
* @param {function} errorFn - The callback on error
*/
var onIframeReady = function($i, successFn, errorFn) {
try {
const iCon = $i.first()[0].contentWindow,
bl = "about:blank",
compl = "complete";
const callCallback = () => {
try {
const $con = $i.contents();
if($con.length === 0) { // https://git.io/vV8yU
throw new Error("iframe inaccessible");
}
successFn($con);
} catch(e) { // accessing contents failed
errorFn();
}
};
const observeOnload = () => {
$i.on("load.jqueryMark", () => {
try {
const src = $i.attr("src").trim(),
href = iCon.location.href;
if(href !== bl || src === bl || src === "") {
$i.off("load.jqueryMark");
callCallback();
}
} catch(e) {
errorFn();
}
});
};
if(iCon.document.readyState === compl) {
const src = $i.attr("src").trim(),
href = iCon.location.href;
if(href === bl && src !== bl && src !== "") {
observeOnload();
} else {
callCallback();
}
} else {
observeOnload();
}
} catch(e) { // accessing contentWindow failed
errorFn();
}
};
var $iframe = $("iframe");
onIframeReady($iframe, function($contents) {
console.log("Ready to got");
console.log($contents.find("*"));
}, function() {
console.log("Can not access iframe");
});
});
</script>
<iframe src="iframe.html"></iframe>
</body>
</html>
var iframe = document.getElementById("someIframe");
var loadingStatus = true;
iframe.onload = function () {
loadingStatus = false;
//do whatever you want [in my case I wants to trigger postMessage]
};
if (loadingStatus)
//do whatever you want [in my case I wants to trigger postMessage]
// runs a function after an iframe node's content has loaded
// note, this almost certainly won't work for frames loaded from a different domain
// secondary note - this doesn't seem to work for chrome : (
// another note - doesn't seem to work for nodes created dynamically for some reason
function onReady(iframeNode, f) {
var windowDocument = iframeNode[0].contentWindow.document;
var iframeDocument = windowDocument?windowDocument : iframeNode[0].contentWindow.document;
if(iframeDocument.readyState === 'complete') {
f();
} else {
iframeNode.load(function() {
var i = setInterval(function() {
if(iframeDocument.readyState === 'complete') {
f();
clearInterval(i);
}
}, 10);
});
}
}
字符串 and I was using运用it like this:
onReady($("#theIframe"), function() {
try {
var context = modal[0].contentWindow;
var i = setInterval(function() {
if(context.Utils !== undefined && context.$) { // this mess is to attempt to get it to work in firefox
context.$(function() {
var modalHeight = context.someInnerJavascript();
clearInterval(i);
});
}
}, 10);
} catch(e) { // ignore
console.log(e);
}
});
// runs a function after an iframe node's content has loaded
// note, this almost certainly won't work for frames loaded from a different domain
onReady: function(iframeNode, f) {
var windowDocument = iframeNode[0].contentWindow.document;
var iframeDocument = windowDocument?windowDocument : iframeNode[0].contentWindow.document
if(iframeDocument.readyState === 'complete') {
f();
} else {
iframeNode.load(f);
}
}
8条答案
按热度按时间vmjh9lq91#
在我弄清楚这里发生了什么事之前,我一直在用头撞墙。
背景信息
.load()
(事件将永远不会触发).ready()
(reference),即使iframe尚未加载,也会立即调用回调postMessage
或调用load
上的容器函数$(window).load()
也会等待其他资产的加载,如图像和其他iframe。如果您只想等待特定的iframe,则这不是一个解决方案readyState
是否有一个已经触发的onload事件是没有意义的,因为Chrome会用一个“about:blank”的空页面初始化每个iframe。此页面的readyState
可能是complete
,但它不是您所期望的页面的readyState
(src
属性)。溶液
以下是必要的:
1.如果尚未加载iframe,则可以观察到
.load()
事件1.如果iframe已经加载,我们需要检查
readyState
1.如果
readyState
是complete
,我们通常可以假设iframe已经被加载。然而,由于Chrome的上述行为,我们还需要检查它是否是空页面的readyState
1.如果是这样,我们需要在一个时间间隔内观察
readyState
,以检查实际文档(与src属性相关)是否为complete
我已经用下面的函数解决了这个问题。它已在(传输至ES5)中成功测试
函数取自jquery.mark
字符串
使用示例
由两个文件(index.html和iframe.html)组成:索引.html:
型
iframe.html文件夹:
型
您也可以将
index.html
内的src
属性变更为,例如即“http://example.com/“。随便玩玩吧。1cklez4t2#
我会使用postMessage。iframe可以分配自己的onload事件并发布给父对象。如果有时间问题,请确保在创建iframe之前分配父级的postMessage处理程序。
要做到这一点,iframe必须知道父对象的URL,例如通过向iframe传递GET参数。
nxagd54h3#
如果iFrame已加载,此函数将立即运行回调函数,或者等到iFrame完全加载后再运行回调函数。只需将您希望在iFrame完成加载时运行的回调函数和元素传递给此函数:
字符串
这将解决最常见的问题,例如chrome使用about:blank初始化iframe,以及iFrame不支持DOMContentLoaded事件。请参阅此https://stackoverflow.com/a/69694808/15757382答案以获取解释。
bbmckpt74#
我也有同样的问题。在我的例子中,我只是检查
onload
函数是否被触发。字符串
7tofc5zh5#
我非常努力地想找到一个跨浏览器工作的解决方案。重要提示:我无法找到这样的解决方案。但这是我所得到的:
字符串
and I was using运用it like this:
型
请注意,即使这样,也不能解决我的问题。以下是此解决方案的一些问题:
因此,如果任何人可以改善这一点,这将是非常赞赏。
pdtvr36n6#
如果加载了框架,则可以使用ownerDocument获取Document数据
字符串
n3schb8v7#
只有当iframe中的内容被加载时,innerDoc才为true,并在if中触发代码。
字符串
example
uoifb46i8#
我想你应该尝试使用
onreadystatechange
事件。http://jsfiddle.net/fk8fc/3/
字符串
编辑:上下文不是我想的那样。你可以检查iframe文档的readyState,一切都应该正常。
OP:这是我根据上面描述的概念制作的打包函数:
型