用于确定本地 iframe 是否已加载的圣杯
Holy grail for determining whether or not local iframe has loaded
首先,我看到这个问题被问了几次,但没有一个答案令人满意。我正在寻找的是能够随时调用脚本并确定 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 事件处理程序,然后将 iframe 与 dom 分离,然后将其插入回 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 负载(不显眼(?
谢谢你的时间。
今天我实际上遇到了一个错误,我删除和重新插入 iframe 会破坏网站上的所见即所得编辑器。因此,我创建了一个小型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 - 在 chrome 中错误地显示"完成"。应该在之后调用 iready 函数,并且尝试输出文档的 readyState 证明跨域异常 - 同样,这还没有经过彻底测试,但适用于我需要的东西。
我遇到了类似的问题,因为我有一个 iframe,一旦完成加载就需要修改它的文档。
如果您知道或可以控制iFrame中加载的文档的内容,那么您可以简单地检查/添加一个可以检查是否存在的元素,以便更新iframe文档。至少那时您知道要使用的元素已加载到文档中。
就我而言,我调用了一个函数,该函数本身检查了我的已知元素是否存在,该元素在我需要更新的元素已经加载后总是会找到 - 如果没有找到,它通过 setTimeout(( 再次调用自己。
function updateIframeContents() {
if ($("#theIframe").contents().find('.SaveButton').length > 0) {
// iframe DOM Manipulation
} else {
setTimeout(updateIframeContents, 250);
}
}
updateIframeContents();
- 如何使用url加载程序在webpack中导入多个图像
- 如何在生成下载文件时显示加载动画
- 有没有任何方法可以将控制器从文件加载到ui路由器$stateProvider中
- 无法在通过jQuery的ajax加载的页面中执行javascript
- Emberjs应用程序加载在除Index之外的所有路由上
- 在chrome.tabs.onCreated之后加载HTML页面
- 单击F5时如何停止页面加载
- HTML5音频加载和播放获胜'我不能在iPad上工作
- 跟踪在页面加载时应用内联样式的JavaScript
- 在使用Polymer'加载所有json文件后执行方法;s的核心ajax
- jQuery Lazy加载动画滚动
- Html页面上的多个Base64图像和平滑加载
- 如何创建带有插槽的vue js组件预加载程序
- Webpack/Rect:遵循egghead.io教程,但出现错误:您可能需要一个合适的加载程序来处理此文件类型
- 如何使该数据在所有元素中加载
- Chrome扩展没有't在重新加载之前考虑期权价值
- 使用javascript在Flash中加载外部图像
- Ajax文件加载和<输入>文件加载
- 用于确定本地 iframe 是否已加载的圣杯
- 圣杯加载问题