问题描述
我有一个项目,我需要创建一个< iframe>元素使用JavaScript并将其附加到DOM。之后,我需要将一些内容插入< iframe>。这是一个嵌入在第三方网站的小部件。我不设置< iframe>的src属性因为我不想加载页面;相反,它用于将我插入的内容隔离/沙箱,以便我不会遇到与父页面的CSS或JavaScript冲突。我正在使用JSONP从服务器加载一些HTML内容并将其插入到这个< iframe>。
我有一个很正常的工作,一个严重的例外 - if document.domain属性设置在父页面中(它可能在部署此部件的特定环境中),Internet Explorer(可能是所有版本,但我已经在6,7和8中确认)给了我一个当我尝试访问这个< iframe>的文档对象时,访问被拒绝错误我创建了在我测试过的任何其他浏览器(所有主要的现代版本)中都不会发生。
这有一定的意义,因为我知道Internet Explorer需要您将设置将相互通信为相同值的所有Windows /框架的document.domain。但是,我不知道有什么办法将这个值设置在无法访问的文档上。
有人意识到有办法做到这一点 - 不知何故设置此动态创建的< iframe>?的document.domain属性或者我没有从正确的角度看它 - 有没有另一种方式来实现我要去的,而不会遇到这个问题?我确实需要使用< iframe>在任何情况下,由于隔离/沙箱窗口对于此小部件的功能至关重要。
这是我的测试代码:
<!DOCTYPE html PUBLIC - // W3C // DTD XHTML 1.0 Strict // ENhttp://www.w3.org/TR/xhtml1/DTD /xhtml1-strict.dtd\">
< html xmlns =http://www.w3.org/1999/xhtmlxml:lang =enlang =en>
< head>
< meta http-equiv =Content-Typecontent =text / html; charset = utf-8/>
< title> Document.domain测试< / title>
< script type =text / javascript>
document.domain ='onespot.com'; //设置页面的document.domain
< / script>
< / head>
< body>
< p>这是& lt; iframe& gt< / p>之上的一个段落。
< div id =placeholder>< / div>
< p>这是& lt; iframe& gt< / p>下面的段落。
< script type =text / javascript>
var iframe = document.createElement('iframe'),doc; // create< iframe>元素
document.getElementById('placeholder')。appendChild(iframe); // append< iframe>元素到占位符元素
setTimeout(function(){//设置一个超时,让浏览器有机会识别< iframe>
doc = iframe.contentWindow || iframe.contentDocument; // get < iframe>文档上的一个句柄
alert(doc);
if(doc.document){// HEREIN LIES THE PROBLEM
doc = doc.document;
}
doc.body.innerHTML ='< h1> Hello!< / h1>'; //添加元素
},10);
< / script>
< / body>
< / html>
我已经主持:
正如你将看到的,如果你在IE中加载这个页面,在我调用alert()的时候,我确实有一个句柄在< iframe> ;我不能深入到其文档对象中。
非常感谢任何帮助或建议!我会感激谁能帮助我找到一个解决方案。
叹了口气。是的,这是一个IE问题(错误,很难说,因为这种不愉快没有文件标准)。当您创建一个srcless iframe时,它从父文档的 location.host
而不是中收到
。在这一点上,你几乎失去了,因为你不能改变它。 document.domain
C $ C> document.domain的
一个可怕的解决方法是设置 src
to a javascript:URL(urgh!):
iframe.src =javascript:'< html>< body>< p> Hello< \ / p>< script> do things;< \ / script>';
但由于某种原因,这样的文档无法设置自己的文档。从IE脚本中的.domain
(好的旧的未指定错误),所以你不能使用它来重新获得父(*)之间的桥。您可以使用它来编写整个文档HTML,假设该窗口小部件在实例化之后不需要与其父文档通信。
但是,iframe JavaScript网址在Safari中不起作用,所以您仍然需要某种浏览器嗅探才能选择使用哪种方法。
*:对于其他一些原因,你可以在IE中设置 document.domain
从第二个文档,由第一个文档写入。所以这样做:
if(isIE)
iframe.src =javascript:'< script>窗口。的onload =函数(){文件撰写(\\'<脚本> document.domain的= \\\ + document.domain的+ \\\;< \\ \\ /脚本> \\ '); document.close();};< \ /脚本>';
在这一点上,对我来说,丑恶程度太高了,我出去了。我会像David所说的这样的外部HTML。
I have project in which I need to create an <iframe> element using JavaScript and append it to the DOM. After that, I need to insert some content into the <iframe>. It's a widget that will be embedded in third-party websites.
I don't set the "src" attribute of the <iframe> since I don't want to load a page; rather, it is used to isolate/sandbox the content that I insert into it so that I don't run into CSS or JavaScript conflicts with the parent page. I'm using JSONP to load some HTML content from a server and insert it in this <iframe>.
I have this working fine, with one serious exception - if the document.domain property is set in the parent page (which it may be in certain environments in which this widget is deployed), Internet Explorer (probably all versions, but I've confirmed in 6, 7, and 8) gives me an "Access is denied" error when I try to access the document object of this <iframe> I've created. It doesn't happen in any other browsers I've tested in (all major modern ones).
This makes some sense, since I'm aware that Internet Explorer requires you to set the document.domain of all windows/frames that will communicate with each other to the same value. However, I'm not aware of any way to set this value on a document that I can't access.
Is anyone aware of a way to do this - somehow set the document.domain property of this dynamically created <iframe>? Or am I not looking at it from the right angle - is there another way to achieve what I'm going for without running into this problem? I do need to use an <iframe> in any case, as the isolated/sandboxed window is crucial to the functionality of this widget.
Here's my test code:
<!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>
I've hosted it at:
http://troy.onespot.com/static/access_denied.html
As you'll see if you load this page in IE, at the point that I call alert(), I do have a handle on the window object of the <iframe>; I just can't get any deeper, into its document object.
Thanks very much for any help or suggestions! I'll be indebted to whomever can help me find a solution to this.
Sigh. Yeah, it's an IE issue (bug? difficult to say as there is no documented standard for this kind of unpleasantness). When you create a srcless iframe it receives a document.domain
from the parent document's location.host
instead of its document.domain
. At that point you've pretty much lost as you can't change it.
A horrendous workaround is to set src
to a javascript: URL (urgh!):
iframe.src= "javascript:'<html><body><p>Hello<\/p><script>do things;<\/script>'";
But for some reason, such a document is unable to set its own document.domain
from script in IE (good old "unspecified error"), so you can't use that to regain a bridge between the parent(*). You could use it to write the whole document HTML, assuming the widget doesn't need to talk to its parent document once it's instantiated.
However iframe JavaScript URLs don't work in Safari, so you'd still need some kind of browser-sniffing to choose which method to use.
*: For some other reason, you can, in IE, set document.domain
from a second document, document.written by the first document. So this works:
if (isIE)
iframe.src= "javascript:'<script>window.onload=function(){document.write(\\'<script>document.domain=\\\""+document.domain+"\\\";<\\\\/script>\\');document.close();};<\/script>'";
At this point the hideousness level is too high for me, I'm out. I'd do the external HTML like David said.
这篇关于“访问被拒绝”尝试访问以编程方式创建的< iframe>的文档对象时出现JavaScript错误(仅IE)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!