我正在尝试从JavaScript创建iframe并使用任意HTML填充它,如下所示:
var html = '<body>Foo</body>';
var iframe = document.createElement('iframe');
iframe.src = 'data:text/html;charset=utf-8,' + encodeURI(html);
我希望iframe
包含一个有效的窗口和文档。但事实并非如此:
&GT;的console.log(iframe.contentWindow);
空
亲自尝试:http://jsfiddle.net/TrevorBurnham/9k9Pe/
我在俯瞰什么?
答案 0 :(得分:199)
尽管你的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-domain限制并且完全通过iframe
句柄完成,您可以稍后访问和操作帧的内容。您需要确保的是,内容已经呈现,这将(根据浏览器类型)在发出.write命令期间/之后开始 - 但在{{1}时不是必须完成的调用。
100%兼容的回调方式可能是这种方法:
close()
然而,iframes有onload事件。这是一种访问内部html为DOM(js)的方法:
<html><body onload="parent.myCallbackFunc(this.window)"></body></html>
答案 1 :(得分:103)
在元素插入文档之前,在javascript中设置新创建的src
的{{1}}不会触发HTML解析器。然后更新HTML并调用HTML解析器并按预期处理该属性。
iframe
这也回答了你的问题,重要的是要注意这种方法与某些浏览器存在兼容性问题,请参阅@mschr的答案,了解跨浏览器解决方案。
答案 2 :(得分:11)
感谢你提出的一个很好的问题,这让我感到很沮丧。使用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>
标记和iframe.src
字符串的html内容。
需要将iframe元素添加到要解析的DOM树中。
document.body.appendChild(iframe);
除非您在浏览器上iframe.contentDocument
,否则您将无法检查disable-web-security
。
您将收到消息
DOMException:无法阅读&#39; contentDocument&#39;属性来自&#39; HTMLIFrameElement&#39;:阻止了一个有起源的框架&#34; http://localhost:7357&#34;从访问跨源框架。
答案 3 :(得分:8)
还可以选择创建内容为HTML字符串的iframe:the srcdoc attribute。旧浏览器不支持这种情况(其中主要是Internet Explorer, and possibly Safari?),但是这种行为有一个polyfill,您可以将其置于IE的条件注释中,或使用类似于has.js的内容有条件地懒加载它。
答案 4 :(得分:5)
我知道这是一个古老的问题,但我想我将提供一个使用srcdoc
属性的示例,因为现在它是widely supported,而且这个问题经常被人们看到。
使用srcdoc
属性,您可以提供嵌入式HTML。如果支持,它将覆盖src
属性。如果不支持,浏览器将退回到src
属性。
我还建议使用sandbox
属性对框架中的内容施加额外的限制。如果HTML不是您自己的,这尤其重要。
const iframe = document.createElement('iframe');
const html = '<body>Foo</body>';
iframe.srcdoc = html;
iframe.sandbox = '';
document.body.appendChild(iframe);
如果您需要支持较旧的浏览器,则可以检查是否支持srcdoc
并从其他答案中回退到其他方法之一。
function setIframeHTML(iframe, html) {
if (typeof iframe.srcdoc !== 'undefined') {
iframe.srcdoc = html;
} else {
iframe.sandbox = 'allow-same-origin';
iframe.contentWindow.document.open();
iframe.contentWindow.document.write(html);
iframe.contentWindow.document.close();
}
}
var iframe = document.createElement('iframe');
iframe.sandbox = '';
var html = '<body>Foo</body>';
document.body.appendChild(iframe);
setIframeHTML(iframe, html);
答案 5 :(得分:3)
URL方法仅适用于小型HTML片段。更可靠的方法是从Blob生成对象URL,并将其用作动态iframe的来源。
const html = '<html>...</html>';
const iframe = document.createElement('iframe');
const blob = new Blob([html], {type: 'text/html'});
iframe.src = window.URL.createObjectURL(blob);
document.body.appendChild(iframe);
答案 6 :(得分:0)
这样做
ShiftDateTime (cdate({BAQReportResult.LaborHed.ClockInTime}), "UTC,-60", "UTC,0")
getIframeWindow 在此处定义
...
var el = document.getElementById('targetFrame');
var frame_win = getIframeWindow(el);
console.log(frame_win);
...
答案 7 :(得分:-2)
(函数(){
var frame = document.createElement('iframe');
frame.src = 'https://1zr2h9xgfxqt.statuspage.io/embed/frame';
frame.style.position = 'fixed';
frame.style.border = 'none';
frame.style.boxShadow = '0 20px 32px -8px rgba(9,20,66,0.25)';
frame.style.zIndex = '9999';
frame.style.transition = 'left 1s ease, bottom 1s ease, right 1s ease';
var mobile;
if (mobile = screen.width < 450) {
frame.src += '?mobile=true';
frame.style.height = '20vh';
frame.style.width = '100vw';
frame.style.left = '-9999px';
frame.style.bottom = '-9999px';
frame.style.transition = 'bottom 1s ease';
} else {
frame.style.height = '115px';
frame.style.width = '320px';
frame.style.left = 'auto';
frame.style.right = '-9999px';
frame.style.bottom = '60px';
}
document.body.appendChild(frame);
var actions = {
showFrame: function() {
if (mobile) {
frame.style.left = '0';
frame.style.bottom = '0';
}
else {
frame.style.left = 'auto';
frame.style.right = '60px'
}
},
dismissFrame: function(){
frame.style.left = '-9999px';
}
}
window.addEventListener('message', function(event){
if (event.data.action && actions.hasOwnProperty(event.data.action)) {
actions[event.data.action](event.data);
}
}, false);
window.statusEmbedTest = actions.showFrame;
})();