首先,我看到这个问题被问过几次,但没有答案似乎令人满意。我正在寻找的是能够随时调用脚本并确定iframe是否已加载 - 并且不限制脚本要求在onload属性中添加到iframe标记本身。
这里有一些背景知识:我一直在研究一个不显眼的脚本,试图确定dom中的本地iframe是否已加载,这是因为我们的一个客户在其网站上的iframe中包含表单,其中许多都打开了灯箱 - 随时动态地将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的文档就绪状态,这似乎在我的几乎所有测试中都有效,除了报告“完整”的chrome之外 - 我希望跨域请求“拒绝访问”。我没有跨域错误,因为我可以忽略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>
我发现如果我只等待100毫秒 - 那么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加载(不引人注目)?
感谢您的时间。
答案 0 :(得分:2)
今天我遇到了一个错误,我删除并重新插入iframe正在网站上破坏了一个所见即所得的编辑器。所以我创建了一个小jQuery插件的开始,以检查iframe准备情况。它不是生产就绪的,我没有对它进行过多的测试,但是它应该提供一个更好的替代方法来分离和重新附加iframe - 它确实在需要时使用轮询,但是当iframe准备就绪时应该删除setInterval。 / p>
可以像:
一样使用$("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>
该示例等待窗口加载后动态地向DOM添加iframe,然后警告其文档的readyState - 在chrome中显示&#34;完成&#34;,错误。 iready函数应该在之后被调用,并且尝试输出文档的readyState证明了跨域异常 - 再次对此进行了彻底的测试但是可以满足我的需要。
答案 1 :(得分:0)
我遇到了一个类似的问题,因为我有一个iframe,需要修改它的&#39;文件一旦完成加载。
IF 您知道或可以控制iFrame中已加载文档的内容,那么您只需检查/添加一个可以检查其存在的元素,然后再更新iframe文献。 至少你知道你想要使用的元素被加载到文档中。
在我的情况下,我调用了一个函数,它本身检查了我已知元素的存在,在我需要更新的元素已经被加载之后总是会找到它 - 在没有找到它的情况下,它自称再次通过setTimeout()。
function updateIframeContents() {
if ($("#theIframe").contents().find('.SaveButton').length > 0) {
// iframe DOM Manipulation
} else {
setTimeout(updateIframeContents, 250);
}
}
updateIframeContents();