Javascript弹出窗口文档永远不会“准备就绪”

3

我正在使用Javascript来打开一个空白窗口,填充它的最小内容并注入一个包含JQuery的脚本标签,但是窗口属性readyState永远无法超过加载状态,因此JQuery永远不会触发。这里是在jsFiddle上的演示。我无法弄清楚为什么弹出窗口无法更新其readyState。

var popup = window.open("", "popup", "height=500,width=700");
var doc = popup.document;
doc.write("<!doctype html><html><head></head><body></body></html>");
var script = doc.createElement("script");
script.type = "text/javascript";
script.src = "https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js";
script.onload = function() {
  console.log(doc.readyState);
  popup.$(document).ready(function() {
    console.log(doc.readyState);
  });
}
doc.getElementsByTagName("head")[0].appendChild(script);

这里是没有使用JQuery的类似代码--同样存在"loading"状态下readyState窗口属性无法超越的问题。

var popup = window.open("", "popup", "height=500,width=700");
var doc = popup.document;
doc.write("<!doctype html><html><head></head><body></body></html>");
console.log(doc.readyState);

我认为这是一个沙盒限制,因为弹出页面的URL与您的脚本不属于同一域。 - Florent
一个空白页面(使用“”)不会在同一个域上吗?我在Chrome中没有收到任何限制应用的错误。此外,在我的完整代码中,我继续调用弹出窗口的JavaScript调用,知道它已经准备好了,即使窗口并不这样认为。只是不够干净,不如我所希望的那样。 - scader
你为什么要使用古老的window.open而不是使用众多jQuery模态对话框之一? - danwellman
这段代码位于一个我无法控制的窗口的 iFrame 中。如果 iFrame 的尺寸太小,此功能可让用户在弹出窗口中打开内容并设置为更大的尺寸。 - scader
2个回答

6
如果您从未设置URL,则准备状态不会更改。它将是“initialized”或“loading”,具体取决于您的浏览器。您可以通过在弹出窗口的控制台窗口中像以下命令一样设置document.location来查看此更新:
console.log(document.readyState);
document.location = "http://yourdomain.com";
console.log(document.readyState);

如果您将位置发送到与您的域不同的域,则无法获得修改窗口对象的安全性。解决方法是使用iframe并设置源代码-如下所示:
var nw = window.open('', "MyWindowID", "fullscreen=no, toolbar=no, menubar=no,status=no,location=no");
var html = '<iframe id="document-{aid}" style="width:100%;height:100%;" src="http://www.google.com"></iframe>';
nw.document.write(html);
nw.focus();

请看:https://dev59.com/aknSa4cB1Zd3GeqPNmmq#1443839 请注意,尝试将弹出窗口包装在$(popup)中并挂钩ready事件。
这应该适合您:
var popup = window.open("", "popup", "height=500,width=700");
var doc = popup.document;
doc.write("<!doctype html><html><head></head><body></body></html>");
var script = doc.createElement("script");
script.type = "text/javascript";
script.src = "https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js";    
$(popup).ready(function(){
    console.log('loaded');
});

这有点令人困惑,因为如果您将日志更改为 console.log(doc.readyState),它仍然报告为“loading”。为什么JQuery认为文档已准备好,而readyState没有改变?查看JQuery脚本,它似乎是基于readyState运行的。 - scader
看起来在所有浏览器中,readyState 并不是干净的,而且 JQuery 实际上设置了 DOM 事件处理程序来处理文档就绪。我仍然很好奇为什么从父窗口的 jQuery 调用可以工作,但从弹出窗口本身的 JQuery 却不能,但无论如何这是一个有效的解决方案,所以我会标记它为已接受。 - scader
我已经更新了答案,并提供了一些更多的信息,你可能会发现有用。 - anAgent

1

由于没有popup的URL,它立即就准备好了。在window.open命令完成后,使用jQuery对其进行“准备”分配将变得无关紧要。它永远不会触发,因为已经太晚了。


这似乎是它的运行方式,但为什么窗口的“readyState”属性仍然设置为“loading”?(这就是为什么我在JQuery事件之外记录了readyState的原因。) - scader
实际上,仔细看一下,我认为popup在您指定的上下文中不存在。 - Joel Etherton
也许我在使用JQuery时让我的示例变得复杂了,但即使删除了使用JQuery的演示,readyState也从未改变。 - scader

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接