我有一个项目,需要使用JavaScript创建<iframe>元素并将其附加到DOM。之后,我需要在<iframe>中插入一些内容。这是一个将嵌入第三方网站的小部件。
<iframe>
我不想设置<iframe>的“ src”属性,因为我不想加载页面。相反,它用于隔离/沙盒我插入其中的内容,这样我就不会遇到CSS或JavaScript与父页面冲突的情况。我正在使用JSONP从服务器加载一些HTML内容并将其插入此<iframe>中。
我的工作正常,但有一个严重的例外-如果在父页面中设置了document.domain属性(可能在部署此小部件的某些环境中),Internet Explorer(可能是所有版本),在尝试访问已创建的此<iframe>的文档对象时,在6、7和8中确认)给我一个“访问被拒绝”错误。在我测试过的任何其他浏览器(所有主要的现代浏览器)中都没有发生。
这很有道理,因为我知道Internet Explorer要求您将将彼此通信的所有窗口/框架的document.domain设置为相同的值。但是,我不知道有什么方法可以在无法访问的文档上设置此值。
有谁知道执行此操作的方法-以某种方式设置此动态创建的的document.domain属性吗?还是我不是从正确的角度看待它-是否有另一种方法可以实现我想要的目标而又不会遇到这个问题?无论如何,我确实需要使用,因为隔离/沙盒化窗口对于此小部件的功能至关重要。
这是我的测试代码:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <title>Document.domain Test</title> <script type="text/javascript"> document.domain = 'onespot.com'; // set the page's document.domain </script> </head> <body> <p>This is a paragraph above the <iframe>.</p> <div id="placeholder"></div> <p>This is a paragraph below the <iframe>.</p> <script type="text/javascript"> var iframe = document.createElement('iframe'), doc; // create <iframe> element document.getElementById('placeholder').appendChild(iframe); // append <iframe> element to the placeholder element setTimeout(function() { // set a timeout to give browsers a chance to recognize the <iframe> doc = iframe.contentWindow || iframe.contentDocument; // get a handle on the <iframe> document alert(doc); if (doc.document) { // HEREIN LIES THE PROBLEM doc = doc.document; } doc.body.innerHTML = '<h1>Hello!</h1>'; // add an element }, 10); </script> </body> </html>
如您所见,如果您在IE中加载此页面,则在我调用alert()时,我确实在的window对象上有一个句柄;我只是无法更深入地了解其文档对象。
如果在父页面中设置了document.domain属性,则Internet Explorer会提示我“访问被拒绝”
document.domain
Internet Explorer
叹。是的,这是IE问题(错误?很难说,因为没有针对这种不愉快现象的记录标准)。创建无src的iframe时,它会document.domain从父文档的那里收到,location.host而不是从document.domain。那时,由于无法更改,您已经迷失了很多。
location.host
可怕的解决方法是将srcjavascript 设置为URL:
iframe.src= "javascript:'<html><body><p>Hello<\/p><script>do things;<\/script>'";
但是由于某种原因,此类文档无法document.domain在IE中的脚本中设置自己的文档(很好的旧“未指定错误”),因此您不能使用它来重新获得父级(*)之间的桥梁。您可以使用它来编写整个文档的HTML,假设该部件在实例化后无需与其父文档进行对话。
(*)
但是,iframe JavaScript URL在Safari中不起作用,因此您仍然需要某种浏览器嗅探才能选择要使用的方法。
iframe JavaScript URL
*:由于其他原因,您可以在IE中document.domain从第二个文档(由第一个文档编写)中设置。所以这有效:
*
if (isIE) iframe.src= "javascript:'<script>window.onload=function(){document.write(\\'<script>document.domain=\\\""+document.domain+"\\\";<\\\\/script>\\');document.close();};<\/script>'";
在这一点上,我的恐惧程度太高了,我已经出局了。我会像David所说的那样做外部HTML。