Определить 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, вместо прослушивания DOM-ready от родительского объекта.
Страничка Паранта:
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
в нем, который НЕ тот же документ, который будет в конечном итоге там, когда динамический контент загружается через .src
приписывать. Итак, даже если вы сделали:
this.els.stage_ifr.contentWindow.document
чтобы получить документ в iFrame, он не обязательно будет правильным документом и, следовательно, DOMContentLoaded
событие не сработает (я видел такое поведение в Chrome).
MDN говорит, что можно слушать DOMFrameContentLoaded
событие на самом iFrame, и это будет соответствовать тому, когда базовый документ действительно получает DOMContentLoaded
, К сожалению, я не могу заставить это событие работать ни в одном браузере. Итак, в данный момент единственный обходной путь, о котором я знаю, - это инициировать событие загрузки изнутри самого iFrame, где он может прослушивать свой собственный DOMContentLoaded
событие (оно может вызвать родительское окно, если это необходимо) или просто прослушать load
событие на объекте iFrame и знать, что он не будет срабатывать, пока не будут загружены такие ресурсы, как таблицы стилей и изображения в iFrame.
В любом случае, я подумал, что объясню кое-что из того, что происходит с вашим исходным кодом, и предложу другое решение, даже если этот вопрос был опубликован более года назад (хотя так и не получил ответа).
Обновить:
Я разработал метод отслеживания DOMContentLoaded
для iFrame, загруженного с тем же источником, что и его родитель. Вы можете увидеть код здесь.
Попробовав разные варианты, я обнаружил, что у меня работает следующий код:
var iframe = document.getElementById("app-frame-id");
iframe.contentWindow.addEventListener("DOMContentLoaded", onFrameDOMContentLoaded, true);
function onFrameDOMContentLoaded () {
console.log("DOMContentLoaded");
};
Если ваша страница и 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!');
});
});
Это может быть больше взломать, но помог мне решить аналогичную проблему.
Я слушаю onmouseenter
содержимого кадра сейчас.
Это событие срабатывает впереди load
(если пользователь перемещает мышь). Но, как и в моем случае, мне нужно событие для инициализации контекстного меню, так или иначе, использование мыши было предварительным условием.
Он даже срабатывает, когда содержимое фрейма изменяется под мышью.