Создание iframe с заданным HTML динамически
Я пытаюсь создать iframe из JavaScript и заполнить его произвольным HTML, например:
var html = '<body>Foo</body>';
var iframe = document.createElement('iframe');
iframe.src = 'data:text/html;charset=utf-8,' + encodeURI(html);
Я бы ожидал, что iframe
будет содержать допустимое окно и документ. Однако это не так:
> console.log(iframe.contentWindow);
нуль
Попробуйте сами: http://jsfiddle.net/TrevorBurnham/9k9Pe/
Что я пропускаю?
Ответы
Ответ 1
Установка src
только что созданного iframe
в javascript не вызывает парсер HTML до тех пор, пока элемент не будет вставлен в документ. Затем HTML обновляется, и парсер HTML будет вызываться и обрабатывать атрибут, как ожидалось.
http://jsfiddle.net/9k9Pe/2/
var iframe = document.createElement('iframe');
var html = '<body>Foo</body>';
iframe.src = 'data:text/html;charset=utf-8,' + encodeURI(html);
document.body.appendChild(iframe);
console.log('iframe.contentWindow =', iframe.contentWindow);
Также этот ответ на ваш вопрос важно отметить, что этот подход имеет проблемы с совместимостью с некоторыми браузерами, см. ответ @mschr для кросс-браузерного решения.
Ответ 2
Пока ваш src = encodeURI
должен работать, я пошел бы по-другому:
var iframe = document.createElement('iframe');
var html = '<body>Foo</body>';
document.body.appendChild(iframe);
iframe.contentWindow.document.open();
iframe.contentWindow.document.write(html);
iframe.contentWindow.document.close();
Поскольку у этого нет никаких ограничений по x-доменам и полностью выполняется с помощью дескриптора iframe
, вы можете позже получить доступ к содержимому фрейма и управлять им. Все, что вам нужно сделать, это то, что содержимое было отображено, которое будет (в зависимости от типа браузера) запускаться во время/после того, как будет выведена команда .write, но не выполняется, когда вызывается close()
.
100% совместимым способом выполнения обратного вызова может быть такой подход:
<html><body onload="parent.myCallbackFunc(this.window)"></body></html>
Iframes имеет событие onload. Ниже приведен подход к доступу к внутреннему html как DOM (js):
iframe.onload = function() {
var div=iframe.contentWindow.document.getElementById('mydiv');
};
Ответ 3
Спасибо за ваш замечательный вопрос, это несколько раз застало меня. При использовании источника dataURI HTML я обнаруживаю, что мне нужно определить полный HTML-документ.
См. ниже модифицированный пример.
var html = '<html><head></head><body>Foo</body></html>';
var iframe = document.createElement('iframe');
iframe.src = 'data:text/html;charset=utf-8,' + encodeURI(html);
обратите внимание на содержимое html, заключенное в теги <html>
и строку iframe.src
.
Элемент iframe необходимо добавить в дерево DOM, которое нужно проанализировать.
document.body.appendChild(iframe);
Вы не сможете проверить iframe.contentDocument
, если вы не используете disable-web-security
в своем браузере.
Вы получите сообщение
DOMException: Не удалось прочитать свойство contentDocument из "HTMLIFrameElement": заблокирован кадр с источником "http://localhost:7357" от доступа к кадру скрещивания.
Ответ 4
Существует альтернатива для создания iframe, содержимое которого представляет собой строку HTML: атрибут srcdoc. Это не поддерживается в старых браузерах (главный из них: Internet Explorer и, возможно, Safari?), Но для этого поведения есть полифилл, который можно добавить в условные комментарии для IE, или используйте что-то вроде has.js для условно-ленивой загрузки.
Ответ 5
Сделай это
...
var el = document.getElementById('targetFrame');
var frame_win = getIframeWindow(el);
console.log(frame_win);
...
getIframeWindow определяется здесь
function getIframeWindow(iframe_object) {
var doc;
if (iframe_object.contentWindow) {
return iframe_object.contentWindow;
}
if (iframe_object.window) {
return iframe_object.window;
}
if (!doc && iframe_object.contentDocument) {
doc = iframe_object.contentDocument;
}
if (!doc && iframe_object.document) {
doc = iframe_object.document;
}
if (doc && doc.defaultView) {
return doc.defaultView;
}
if (doc && doc.parentWindow) {
return doc.parentWindow;
}
return undefined;
}
Ответ 6
https://get.cryptobrowser.site/promo/ad/6/9438734/"style =" width: 728px; height: 90px "frameborder =" no ">