检测iframe中的DOMContentLoaded

时间:2013-06-06 11:20:43

标签: javascript events dom iframe domready

我很惊讶地发现以下似乎没有效果,因为DOMContentLoaded事件没有触发(this.els是元素的对象)。

this.els.stage_ifr.prop('src', 'templates/'+ee.globals.creating+'/item'+this.id);
this.els.stage_ifr[0].addEventListener('DOMContentLoaded', function() {
    alert('loaded!');
}, false);

页面加载到iframe中,但没有回调。但是,DOM级别onload可以正常工作。

this.els.stage_ifr[0].onload = function() { alert('loaded!'); }; //<-- fires

解决方法是在父页面中准备一个全局可访问的jQuery延迟对象,并通过从调用iframe的页面触发的DOM-ready事件解决它,而不是从父级调用DOM-ready。

Paraent页面:

dfd = new $.Deferred;
dfd.done(function() { alert("frame page's DOM is ready!"); });

框架页面:

$(function() { window.parent.dfd.resolve(); });

尽管如此,知道第一种方法是什么还是很好......

4 个答案:

答案 0 :(得分:17)

在回答this question的过程中,我发现了DOMContentLoaded事件监听器无法正常工作的原因。在我看来,你有两个问题。

首先,您正在尝试在iFrame上监听DOMContentLoaded事件。这不是一个iFrame事件。这是一个文件活动。因此,您必须进入iFrame才能获取contentWindow,然后从中获取文档。这导致了第二个问题。

其次,当首次创建iFrame时,它中有一个虚拟document,它与通过.src属性加载动态内容时最终会出现的文档不同。所以,即使你这样做了:

this.els.stage_ifr.contentWindow.document

要在iFrame中获取文档,它不一定是正确的文档,因此DOMContentLoaded事件不会触发它(我在Chrome中看到过这种行为)。


MDN说,可以在iFrame本身上监听DOMFrameContentLoaded事件,这与基础文档实际获得DOMContentLoaded的时间相对应。不幸的是,我无法在任何浏览器中使用此活动。所以,在这个时刻,我所知道的唯一解决方法是从iFrame本身触发load事件,它可以监听自己的DOMContentLoaded事件(如果需要,它可以调用父窗口) be)或只是听iFrame对象上的load事件,并知道在iFrame中的样式表和图像等资源也被加载之前它不会被激活。


无论如何,我想我会解释你的初始代码发生了什么,并提供另一个解决方案,即使这个问题是在一年多前发布的(虽然从未回答)。


<强>更新

我开发了一种跟踪DOMContentLoaded的方法,该方法用于加载与其父级相同来源的iFrame。您可以看到代码here

答案 1 :(得分:5)

尝试不同的选项后,我发现以下代码适用于我:

var iframe = document.getElementById("app-frame-id");
iframe.contentWindow.addEventListener("DOMContentLoaded", onFrameDOMContentLoaded, true);
function onFrameDOMContentLoaded () { 
     console.log("DOMContentLoaded");
};

答案 2 :(得分:1)

这可能更像是一个黑客,但帮助我解决了类似的问题。

我现在正在收听onmouseenter帧内容。

此事件在load之前触发(如果用户移动鼠标)。但在我的情况下,我需要用于初始化上下文菜单的事件,无论如何使用鼠标是一个先决条件。

当鼠标下的帧内容发生变化时,它甚至会触发。

答案 3 :(得分:1)

如果您的页面和iframe 位于同一域上,则必须先等待原始页面触发DOMContentLoaded,然后将DOMContentLoaded事件监听器附加到iframe的Window(不是Document)。

鉴于您的iframe如下,

<iframe id="iframe-id" name="iframe-name" src="..."></iframe>

下一个代码段将使您能够参与iframe的DOMContentLoaded事件:

document.addEventListener('DOMContentLoaded', function () {
    var iframeWindow = frames['iframe-name'];
    // var iframeWindow = document.querySelector('#iframe-id').contentWindow
    // var iframeWindow = document.getElementById('iframe-id').contentWindow

    iframeWindow.addEventListener('DOMContentLoaded', function () {
        console.log('iframe DOM is loaded!');
    });
});
相关问题