使用window.open打开的窗口如何检测onload事件?

58
 window.popup = window.open($(this).attr('href'), 'Ad', 'left=20,top=20,width=500,height=500,toolbar=1,resizable=0');
 $(window.popup).onload = function()
        {
                alert("Popup has loaded a page");
        };

我已经在多个浏览器中尝试了这段代码(包括IE,Firefox和Chrome),但都没有起作用。有什么方法可以检测页面何时在窗口中加载完成(就像在iframe的onload事件中那样)?


2
我猜你已经在你的<BODY>中有了onLoad了吧? - VoodooChild
假设我无法控制在弹出窗口中打开的页面。 - Christopher Tarquini
你在那里试图用 $(...).onload 做什么?为什么不直接用 window.popup.onload - Crescent Fresh
^ 这可能是它出问题的原因... 编辑:是的,这解决了问题,但不适用于跨域。 - Christopher Tarquini
8个回答

59
var myPopup = window.open(...);
myPopup.addEventListener('load', myFunction, false);

如果你关心IE的兼容性,可以使用以下代码替换第二行:

myPopup[myPopup.addEventListener ? 'addEventListener' : 'attachEvent'](
  (myPopup.attachEvent ? 'on' : '') + 'load', myFunction, false
);

正如你所看到的,支持IE相当繁琐,应尽可能避免。如果你需要支持IE以满足观众需求,那么请务必这样做。


1
我能以跨域的方式实现这个吗? - Christopher Tarquini
3
很遗憾,出于安全原因,浏览器禁用了不同域之间的JavaScript对象交互。 - Delan Azabani
2
然后只需要使用三元条件语句即可。我会添加它。 - Delan Azabani
1
我花了数小时寻找解决方案,这是唯一对我有效的方法。需要注意的一点是,Firefox似乎在完全加载页面之前就打开了打印对话框。这将导致打印空白页面。我通过检测浏览器,然后在需要时使用onload事件来解决了这个问题。这可能不是最好的方法,但对我而言有效。以下是我的代码: - user359519
1
var w = window.open(targetUrl, "_blank"); w[w.addEventListener ? 'addEventListener' : 'attachEvent']( (w.attachEvent ? 'on' : '') + 'load', doPrint(w), false ); - user359519
显示剩余3条评论

26

如果弹出窗口的文档来自不同的域名,那么这是不可能的。

2015年4月更新:我对此有误解:如果您拥有这两个域名,您可以使用window.postMessagemessage事件在几乎所有相关浏览器中实现

如果没有这种情况,除非弹出窗口加载的文档提供一些帮助,否则您仍然无法跨浏览器使其正常工作。您需要能够检测弹出窗口加载后发生的更改,这可以是JavaScript在弹出窗口页面处理其自己的load事件时设置的变量,或者如果您对其有一定的控制权,则可以添加一个函数调用到打开者中。


1
一种简单的方法是在setTimeout()调用中监视另一个页面中JS函数的可用性。 - Jerod Venema
根据这篇文章https://dev59.com/Q18f5IYBdhLWcg3wD-8v,这是可能的,但你必须拥有两个域名。 - James

6

如在检测使用window.open打开的窗口的onload事件中所述,以下解决方案是理想的:

/* Internet Explorer will throw an error on one of the two statements, Firefox on the other one of the two. */
(function(ow) {
    ow.addEventListener("load", function() { alert("loaded"); }, false);
    ow.attachEvent("onload", function() { alert("loaded"); }, false);
})(window.open(prompt("Where are you going today?", location.href), "snapDown"));

其他评论和答案存在一些错误的误解,如下所述。

以下脚本演示了定义 onload 的反复无常性。将该脚本应用于“快速加载”的位置以打开窗口,例如具有 file: 方案的位置,然后将其与“慢”位置进行比较以查看问题:可能会看到任何一个onload消息或者根本没有 (通过重新加载已加载的页面,可以看到所有3个变体)。还假定正在加载的页面本身没有定义会加重问题的 onload 事件。

显然,onload 定义不在“弹出式文档标记”内:

var popup = window.open(location.href, "snapDown");
popup.onload = function() { alert("message one"); };
alert("message 1 maybe too soon\n" + popup.onload);
popup.onload = function() { alert("message two"); };
alert("message 2 maybe too late\n" + popup.onload);

你可以做以下事情:

  • 打开一个有“外部”网址的窗口
  • 在窗口的地址栏中输入一个javascript: URI - 该代码将与“外部”网址的域具有相同的特权
    如果在地址栏中输入没有效果(可能是2012年左右发布的某些浏览器的情况),则可能需要将javascript: URI 添加到书签中。

因此,几乎可以修改任何页面的来源:

if(confirm("wipe out links & anchors?\n" + document.body.innerHTML))
    void(document.body.innerHTML=document.body.innerHTML.replace(/<a /g,"< a "))

好的,几乎吧:

jar:file:///usr/lib/firefox/omni.ja!/chrome/toolkit/content/global/aboutSupport.xhtml,Mozilla Firefox的故障排除页面和其他Jar归档文件是例外。

另一个例子是,为了定期禁用Google对目标点击的篡改,使用以下URI更改其rwt函数:

javascript: void(rwt = function(unusurpURL) { return unusurpURL; })

(可选择将以上内容作为书签命名为“Spay Google”(“中和Google”?)

在任何点击Google搜索结果前,点击此书签,因此任何这些结果的书签都是干净的,并且不会受到Google对它们进行混杂畸变的影响。

使用 Mozilla/5.0 (X11; Ubuntu; Linux i686; rv:11.0) Gecko/20100101 Firefox/11.0 UA 字符串进行测试。

应该注意,在Firefox中,addEventListener 只有一个非标准的第四个布尔参数,如果设置为 true,则允许实例化来自外部页面的不受信任的内容触发器。

参考文献:
element.addEventListener | Document Object Model (DOM) | MDN:
Interaction between privileged and non-privileged pages | Code snippets | MDN:


9
这个回答中有很多句子,它们先表述了一件事,然后跟着另一句话来纠正之前的内容。这会让理解变得困难。虽然信息量丰富,但难以捉摸。如果表达更清晰,你将获得更多点赞。 - MushinNoShin
此外,如果这个问题已经被另一个问题回答了,或许将其标记为那个问题的副本并在评论中引导提问者到那个问题会更有价值。 - MushinNoShin
所引用的答案是对这个问题发布的答案的直接“分享”链接 - 最好的做法是...完成!... - ekim
2
点赞本身并不是一个问题 - 混淆?希望没有直接矛盾的地方 - “误解的实施” 是指先前有关 x-site 脚本和起源策略的评论和回答,希望这个回答不会引起这种情况! - 通过运行功能代码示例的经验证据,散文希望更简洁、更精确地得到验证和确认 - ow!(O pen W indow 或者应该是 function(ouch),这是对第一个示例中未处理错误条件的双关语!)散文非常尖锐,如果写它很痛苦,那么阅读它...! - ekim
4
你的写作风格很难阅读。在尝试理解这个答案的意思时,我的大脑感到疼痛。简洁是好事。 - Pete Martin
自调用函数真的有必要吗? - user5886944

4
这对我有用,下面是完整示例:
HTML:
<a href="/my-popup.php" class="import">Click for my popup on same domain</a>

Javascript:

(function(){
    var doc = document;

    jQuery('.import').click(function(e){
        e.preventDefault();
        window.popup = window.open(jQuery(this).attr('href'), 'importwindow', 'width=500, height=200, top=100, left=200, toolbar=1');

        window.popup.onload = function() {
            window.popup.onbeforeunload = function(){
                doc.location.reload(true); //will refresh page after popup close
            }
        }
    });
})();

4
如果域名不同,这种方法将无效。 - Ben Muircroft

1

onload 事件处理程序必须在弹出窗口的 HTML <body> 标记内部。


这是我唯一能够触发它的方式,尝试了几乎所有可能的方式 - 谢谢。最后 $(popup).find('body').attr('onload', 'window.print();'); 生效了。 - Breeno

1

首先,当您的第一个初始窗口被加载时,它会被缓存。因此,从第一个窗口创建一个新的窗口时,新窗口的内容不是从服务器加载的,而是从缓存加载的。因此,创建新的窗口时不会发生onload事件。

但是,在这种情况下,会触发onpageshow事件。它始终在onload事件之后触发,即使页面从缓存中加载也会触发。此外,现在所有主要浏览器都支持它。

 window.popup = window.open($(this).attr('href'), 'Ad', 'left=20,top=20,width=500,height=500,toolbar=1,resizable=0');
 $(window.popup).onpageshow = function() {
     alert("Popup has loaded a page");
 };

w3school网站更详细地阐述了这一点:

onpageshow事件类似于 onload 事件,不同的是它在页面第一次加载后发生。此外, onpageshow 事件每次加载页面时都会发生,而 onload 事件在从缓存加载页面时不会发生。


0

-2

简单的解决方案:

new_window = window.open(...);
new_window.document.write('<body onload="console.log(1);console.log(2);></body>');

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