Почему iframe.contentWindow == null?
Я использую следующий код для динамического создания iframe.
var iframe_jquery = $("<iframe>")
.addClass("foo")
.appendTo(container); // container is a jQuery object containing a <div> which already exists
Затем я хочу получить доступ к его контенту contentWindow, но он null:
var iframe = iframe_jquery.get(0);
if (iframe){ // iFrame exists
console.log(iframe.contentWindow); // Prints "null"
var doc = iframe.contentWindow.document; // NullpointerException
}
Поэтому я подумал: "Может быть, iframe еще не готов?" Поэтому я попробовал:
iframe_jquery.ready(function(){
var iframe = iframe_jquery.get(0);
console.log(iframe.contentWindow); // Prints "null"
var doc = iframe.contentWindow.document; // NullpointerException
});
Тот же результат.
Что не так?
Ответы
Ответ 1
У меня была эта проблема на прошлой неделе во время игры с iFrames (создание редактора rtf), и да, он еще не готов.
Я думал, что если бы я поместил его в .ready()
, это сработало бы, но .ready()
будет, когда DOM будет готов, а не когда iFrame загрузит его содержимое, поэтому я закончил перенос моего кода с помощью jQuery .load()
.
Итак, попробуйте следующее:
$(function () {
$("#myiframe").load(function () {
frames["myframe"].document.body.innerHTML = htmlValue;
});
});
Надеюсь, что это поможет
Ответ 2
Проблема в том, что ваш <iframe>
не будет "реальным", пока он действительно не добавится к фактической DOM для страницы. Вот скрипка, чтобы продемонстрировать..
Ответ 3
В зависимости от браузера доступ к document
или <iframe>
может отличаться.
Вот пример того, как с ним обращаться:
if (iframe.contentDocument) // FF Chrome
doc = iframe.contentDocument;
else if ( iframe.contentWindow ) // IE
doc = iframe.contentWindow.document;
Ответ 4
Версия прокладок
Просто из любопытства я подумал, что соединить это. Помня, что события iframes и load не хорошо сочетаются друг с другом в разных браузерах (в основном старше, разваливаются, должны быть мертвые браузеры)... плюс не совсем уверен, как jQuery обошел эту проблему... мой мозг решил, что это было бы лучше поддержано (независимо от того, есть оно или нет ни здесь, ни там):
$(function(){
/// bind a listener for the bespoke iframeload event
$(window).bind('iframeload', function(){
/// access the contents of the iframe using jQuery notation
iframe.show().contents().find('body').html('hello');
});
/// create your iframe
var iframe = $('<iframe />')
/// by forcing our iframe to evaluate javascript in the path, we know when it ready
.attr('src', 'javascript:(function(){try{p=window.parent;p.jQuery(p).trigger(\'iframeload\');}catch(ee){};})();')
/// insert the iframe into the live DOM
.appendTo('body');
});
Причиной такого подхода является то, что обычно лучше запускать событие загрузки из самого iframe. Но это означает наличие надлежащего документа, загруженного в iframe, поэтому для динамических фреймов это немного утомительно. Это своего рода смесь между документом, загруженным, а не.
Вышеизложенное работает над всем, что я тестировал до сих пор, и да, вы правы - это немного смехотворные, не относящиеся к будущему и поддерживающие другие вещи, имеющие отрицательные коннотации;)
Одна положительная вещь, которую я скажу об этом сообщении, - это использование .contents()
для доступа к документу iframe, который хотя бы немного полезен...
Ответ 5
У меня была аналогичная ситуация, когда contentWindow
был пустым (около 50% времени сразу после загрузки документа), но я хотел установить iframe src через element.contentWindow.location.replace
.
Чтобы решить эту проблему, я сделал цикл, ожидающий, что contentWindow
не будет иметь нуль... например:
function setIframeLocation(element, value) {
if (element.contentWindow !== null) {
element.contentWindow.location.replace(value);
}
else {
setTimeout(setIframeLocation.bind(this, element, value), 100);
}
}
setIframeLocation(element, 'http://google.com');
Ответ 6
Вы также можете создать функцию, которая будет выполняться, когда iframe завершит загрузку, установив атрибут onload.