动态创建具有给定HTML的iframe

时间:2012-05-02 17:21:50

标签: javascript iframe

我正在尝试从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/

我在俯瞰什么?

8 个答案:

答案 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解析器并按预期处理该属性。

http://jsfiddle.net/9k9Pe/2/

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;

})();