7

我迫切需要一些帮助。

我创建了一个 <script> ,它与我在别处编写的另一个更复杂的 <script> 非常相似,并重现了该问题。

这是它的作用:

  • 创建一个 <iframe> 并插入到页面上的 <div> 中
  • 创建一个文档并将其附加到该 <iframe>,其中包含一个定义一些函数的 <script>(包括一个回调函数和一个使用 AJAX 加载外部 <script> 的函数)
  • 后一个外部脚本只是对回调函数的调用,它调用一个创建文档并将其附加到它所在的 <iframe> 的函数;这应该有效地覆盖 <script>

涉及的三个文件是:

这一切都适用于 Firefox、Safari 和 Chrome。它在 Internet Explorer 和 Opera 中出现故障。发生的情况是 main.js 中的 render() 函数执行,所有三个警报都被触发,但 <iframe> 中的文档没有被覆盖。我不知道正在创建或写入什么文件,或者根本就没有。

如果我在 render() 函数的开头添加调试代码(如 console.log(document)),工作浏览器似乎可以处理现有的 <iframe> 文档并列出下面包含的属性。Internet Explorer 似乎也能找到某种文档。我只是不知道为什么它不让我覆盖它。

会不会是范围问题?也许我不正确地使用了 document.write()、document.open() 或 document.close() 方法,而 Firefox 和其他一些浏览器只是让我侥幸逃脱?

一个可能的线索:如果我取出 render() 函数的胆量(即,将它们放在 main.js 中的 load() 之后),这可以正常工作。这向我表明,这不是我使用 document.open() 等的方式,而是在执行 callback() 函数时,文档对象不可用或超出范围,或类似的东西。

这让我完全被难住了,这是一个非常重要的项目,截止日期即将到来。如果它能让我摆脱困境,我不会超越黑客或解决方法。任何帮助或见解将不胜感激!

console.log() 的文档属性列表:

属性节点:2
CDATA_SECTION_NODE:4
COMMENT_NODE:8
DOCUMENT_FRAGMENT_NODE:11
DOCUMENT_NODE:9
DOCUMENT_POSITION_CONTAINED_BY:16
DOCUMENT_POSITION_CONTAINS:8
DOCUMENT_POSITION_DISCONNECTED:1
DOCUMENT_POSITION_FOLLOWING:4
DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC:32
DOCUMENT_POSITION_PRECEDING:2
DOCUMENT_TYPE_NODE:10
ELEMENT_NODE:1
实体节点:6
ENTITY_REFERENCE_NODE:5
NOTATION_NODE:12
PROCESSING_INSTRUCTION_NODE:7
文本节点:3
网址:“http://localhost/projects/test/ajax_loader/document_write/index.html”
活动元素:HTMLBodyElement
addEventListener: 函数 addEventListener() {
采用节点:函数采用节点(){
链接颜色:“”
全部:HTMLCollection
锚点:HTMLCollection
appendChild: 函数 appendChild() {
小程序:HTMLCollection
属性:空
baseURI:“http://localhost/projects/test/ajax_loader/document_write/index.html”
背景颜色:“”
正文:HTMLBodyElement
捕获事件:函数捕获事件(){
字符集:“UTF-8”
字符集:“UTF-8”
子节点:节点列表
清除:函数清除(){
克隆节点:函数克隆节点(){
关闭:函数关闭(){
compareDocumentPosition: 函数 compareDocumentPosition() {
compatMode:“BackCompat”
cookie:“__gads=ID=62bb88ab20ac9451:T=1256683145:S=ALNI_Mbso-nFjAvRzYhCSwhiuaDh84G8CA”
创建属性:函数创建属性(){
createAttributeNS: 函数 createAttributeNS() {
createCDATASection: 函数 createCDATASection() {
createComment: 函数 createComment() {
createDocumentFragment: 函数 createDocumentFragment() {
创建元素:函数创建元素(){
createElementNS: 函数 createElementNS() {
createEntityReference: 函数 createEntityReference() {
创建事件:函数创建事件(){
createExpression: 函数 createExpression() {
createNSResolver: 函数 createNSResolver() {
createNodeIterator: 函数 createNodeIterator() {
createProcessingInstruction: 函数 createProcessingInstruction() {
创建范围:函数创建范围(){
createTextNode: 函数 createTextNode() {
createTreeWalker: 函数 createTreeWalker() {
默认字符集:“iso-8859-1”
默认视图:DOMWindow
设计模式:“关闭”
目录:“”
调度事件:函数调度事件(){
文档类型:空
文档元素:HTMLHtmlElement
documentURI:“http://localhost/projects/test/ajax_loader/document_write/index.html”
域:“本地主机”
elementFromPoint: 函数 elementFromPoint() {
嵌入:HTMLCollection
评估:函数评估(){
执行命令:函数执行命令(){
fg颜色:“”
第一个孩子:HTMLHtmlElement
表单:HTMLCollection
getCSSCanvasContext: 函数 getCSSCanvasContext() {
getElementById: 函数 getElementById() {
getElementsByClassName: 函数 getElementsByClassName() {
getElementsByName: 函数 getElementsByName() {
getElementsByTagName:函数 getElementsByTagName() {
getElementsByTagNameNS: 函数 getElementsByTagNameNS() {
getOverrideStyle: 函数 getOverrideStyle() {
获取选择:函数获取选择(){
hasAttributes: 函数 hasAttributes() {
hasChildNodes: 函数 hasChildNodes() {
hasFocus: 函数 hasFocus() {
身高:150
图片:HTMLCollection
实现:DOMImplementation
进口节点:函数进口节点(){
输入编码:“UTF-8”
插入前:函数插入前(){
isDefaultNamespace: 函数 isDefaultNamespace() {
isEqualNode: 函数 isEqualNode() {
isSameNode: 函数 isSameNode() {
isSupported: 函数 isSupported() {
jQuery1258269389622:2
lastChild: HTMLHtmlElement
最后修改: ””
链接颜色:“”
链接:HTMLCollection
本地名称:空
地点:地点
查找名称空间URI:函数查找名称空间URI(){
查找前缀:函数查找前缀(){
命名空间URI:空
下一个兄弟姐妹:空
节点名称:“#document”
节点类型:9
节点值:空
规范化:函数规范化(){
打开:函数打开(){
所有者文档:空
父元素:空
父节点:空
插件:HTMLCollection
首选样式表集:空
前缀:空
上一个兄弟姐妹:空
queryCommandEnabled: 函数 queryCommandEnabled() {
queryCommandIndeterm: 函数 queryCommandIndeterm() {
查询命令状态:函数查询命令状态(){
查询命令支持:函数查询命令支持(){
查询命令值:函数查询命令值(){
查询选择器:函数查询选择器(){
querySelectorAll: 函数 querySelectorAll() {
就绪状态:“完成”
推荐人:“http://localhost/projects/test/ajax_loader/document_write/index.html”
释放事件:函数释放事件(){
removeChild: 函数 removeChild() {
removeEventListener: 函数 removeEventListener() {
替换孩子:函数替换孩子(){
脚本:HTMLCollection
选定样式表集:空
样式表:样式表列表
文本内容:空
标题:“页面”
vlink颜色:“”
宽度:300
写:函数写(){
writeln: 函数 writeln() {
xml编码:空
xml独立:假
xml版本:空
4

6 回答 6

11

如果我去掉 render() 函数的胆量(即,将它们放在 main.js 中的 load() 之后),这可以正常工作。

在 IE8 中不适合我。如果我完全失去了 AJAX 调用而只调用render()main.js,我会得到相同的结果。事实上,即使我将整个 main.js 替换为:

document.write('hello!');

无论是否打开文档,你好永远不会出现!

render如果我在 main.js中调用任何超时(甚至为 0) ,它就可以工作。另一方面,父文档的超时似乎没有做任何事情。

这种极端怪异的原因是 jQuery 使用临时插入的<script>标签来执行 jsonp.js 中返回的代码。如果您只是调用eval返回值而不是让 jQuery 执行它,它就可以正常工作。

我发现缩小 hello 示例的相关问题由 index.html 演示:

<body>
<iframe name="foo"></iframe>
<script>
    var idoc= frames['foo'].document;
    idoc.open();
    idoc.write('<body><script src="main.js"><\/script>');
    idoc.close();
</script>

main.js 包含:

document.write('foo');

没有 foo 写。(另一方面,内联脚本很好。)

如果idoc.close省略了,它会起作用。如果添加了idoc.write('bar')附加内容,则之前仅在 IEbar中编写过。foo如果我同时添加barclose调用,IE 崩溃了。

总而言之,从本身编写的文档内部使用存在严重问题!如果可能的话,尽量避免它。可能是从父文档填充 iframe 的有用方法,但您不应该在子文档中真正需要它,您可以在其中使用自己的 DOM 方法。document.writedocument.writedocument.open

于 2009-11-16T01:12:04.560 回答
4

正如大多数人已经提到的那样,IE 在尝试做一些简单的事情时会遇到严重的问题,例如:

var doc = window.frames['your_frame'].document;
doc.open();
doc.write('<body><script src="external_resource.js"><\/script>');
doc.close();

经过详尽的搜索,我发现这篇文章建议使用 javascript: URI 方案将内容插入 iframe 文档。我已经在当前版本的 FF、Chrome 和 Safari 以及 IE 7/8/9/10 中亲自测试过这个解决方案。

借鉴他的示例,以下示例将代替我上面的示例,并且可用于实现您所追求的目标:

var iframe = window.frames['your_frame'];
var content = '<body><script src="external_resource.js"><\/script>';
iframe.contentWindow.contents = content;
iframe.src = 'javascript:window["contents"]';

我听说旧版本的 Safari 不能很好地处理 javascript: URI 方案,但我找不到确认方法,因为使用 Safari 的每个人似乎都在定期升级。我也不知道这是否会遇到 IE 中 URI 的字符限制问题(因为它比其他所有浏览器都小),但对于那些遇到类似问题的人来说,值得研究一下。

于 2013-08-15T22:25:00.737 回答
2

根本问题是在 IE 中你不能做

iframe_document.open();
iframe_document.write('<script src="foo.js"><\/script>');
iframe_document.close();

在 iframe 上调用 document.close() 后,IE 似乎会在那里停止所有 javascript 执行。js 线程在 foo.js 的 http 请求未完成时运行 document.close(),因此文件已加载但从未执行。

我还没有找到任何方法让父页面知道在 iframe 中执行的脚本已完全完成。一种解决方法是让 foo.js 负责调用 document.close() 本身——这不是很愉快,但如果你不介意更改被调用的脚本,它就可以了。

注意:你不能 document.write('document.close()') 直接进入 iframe:会导致 IE 死机。但是 setTimeout(function(){document.close()}, 0) 似乎免疫 -有时加载脚本中的 document.close() 也是如此。啊。

于 2009-11-24T21:32:33.920 回答
1

您应该使用以下属性加载 iframe 的内容"src":不支持 iframe 的浏览器使用 iframe 的主体来显示替代消息。相反,您是在 iframe 中注入一个完整的内联 html 文档,而某些浏览器将不喜欢它。更多信息在这里

如果你想从主文档向 iframe 发送消息,John Resig 的博客上有一个很好的教程。

于 2009-11-15T10:00:35.777 回答
0

会像这样简单:

function render(data) {
    document.body.innerHTML = data;
}

解决你的问题?适用于 IE8/Win7。

于 2009-11-16T04:25:20.513 回答
0

这很奇怪,Michael Kleber 弄错了:所有警报都出现得很好,所以问题不在于脚本没有执行。它确实执行。

观察 main.js 的以下变化:

$(document).ready(function() {

  // note that render() has to be moved into the window scope
  window.render = function(data) {
    document.open();
    alert('opened');
    document.write(data);
    alert('written');
    document.close();
    alert('closed');
  }

  function load() {
    $.ajax({
      url: 'jsonp.js',
      dataType: 'script'
    });
  }

  window.callback = function(data) {
    // does not work
    render(data);

    // works
    window.data = data;
    var t = setTimeout("render(data)", 0);
  }

  load();

});
于 2010-03-19T18:41:19.263 回答