Обнаружение DOMContentLoaded в iframe

Я был удивлен, обнаружив, что следующее не работает, поскольку событие 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 на родительской странице и разрешить его с помощью события DOM-ready, запущенного со страницы, вызванной в iframe, а не слушаю дом-готов от родителя.

Paraent страницы:

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

страница:

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

тем не менее было бы неплохо узнать, что происходит с первым подходом...

3 ответов


в ответе этот вопрос, я обнаружил причину своего DOMContentLoaded прослушиватель событий не работает. Мне кажется, у вас две проблемы.

во-первых, вы пытаетесь слушать на DOMContentLoaded событие на самом iFrame. Это не событие iFrame. Это событие документа. Таким образом, вы должны добраться до iFrame, чтобы получить contentWindow, а затем получить документ из этого. Это приводит ко второму вопросу.

во-вторых, когда iframe сначала создается, у него есть манекен document в нем это не тот же документ, который в конечном итоге будет там, когда динамическое содержимое загружается через . Так что, даже если вы сделали:

this.els.stage_ifr.contentWindow.document

чтобы получить документ в iFrame, он не обязательно будет правильным документом и, следовательно,DOMContentLoaded событие не будет работать на нем (я видел это поведение в Chrome).


MDN говорит, что можно слушать DOMFrameContentLoaded событие на самом iFrame и это будет соответствовать, когда базовый документ фактически получает DOMContentLoaded. К сожалению, я не могу заставить это событие работать в любом браузере. Итак, на данный момент единственная работа, которую я знаю,-это либо вызвать событие load из самого iFrame, где он может слушать свой собственный DOMContentLoaded событие (при необходимости оно может вызвать родительское окно) или просто прослушать load событие на объекте iFrame и знать, что он не будет срабатывать до ресурсов, таких как таблицы стилей и изображений в кадра будут также загружены.


в любом случае, я думал, что объясню некоторые из того, что происходит с вашим исходным кодом, и предложу другое решение, хотя этот вопрос был опубликован более года назад (хотя никогда не отвечал).


обновление:

Я разработал метод отслеживания DOMContentLoaded для iFrame, загруженного с тем же источником, что и его родитель. Вы можете увидеть код здесь.


попробовав разные варианты, я обнаружил, что для меня работает следующий код:

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

Это может быть больше взлома, но помогло мне решить аналогичную проблему.

Я слушаю onmouseenter контент кадр.

это событие срабатывает перед load (если пользователь перемещает мышь). Но, как и в моем случае, мне нужно событие для инициализации контекстного меню, использование мыши было предварительным условием.

Он даже срабатывает, когда содержимое кадра изменяется под мышью.