是否有可能用JavaScript打开弹出窗口,然后检测用户何时关闭它?


75

标题中几乎所有问题。

是否可以(以及如何?)用JavaScript打开弹出窗口,然后检测用户何时关闭它?

我在项目中使用jquery,所以jquery解决方案会很好。干杯!


定义“弹出窗口”。我们在说某种页面上渲染的模式框吗?JavaScript警报?新的浏览器窗口?
DA。

1
一个新的浏览器窗口......对不起,我缺乏透明度
巴勃罗

Answers:


99

如果您可以控制弹出窗口的内容,请在unload此处处理窗口的事件,并通过opener属性通知原始窗口,首先检查打开器是否已关闭。请注意,这在Opera中并不总是有效。

window.onunload = function() {
    var win = window.opener;
    if (!win.closed) {
        win.someFunctionToCallWhenPopUpCloses();
    }
};

由于该unload事件将在用户离开弹出窗口中的页面时(而不只是关闭窗口时)触发,因此您应该检查弹出窗口在以下位置是否确实已关闭someFunctionToCallWhenPopUpCloses

var popUp = window.open("popup.html", "thePopUp", "");
function someFunctionToCallWhenPopUpCloses() {
    window.setTimeout(function() {
        if (popUp.closed) {
            alert("Pop-up definitely closed");
        }
    }, 1);
}

如果您无法控制弹出窗口的内容,或者您​​的目标浏览器之一不支持该unload事件,则可以在主窗口中使用某种轮询解决方案。调整间隔以适合。

var win = window.open("popup.html", "thePopUp", "");
var pollTimer = window.setInterval(function() {
    if (win.closed !== false) { // !== is required for compatibility with Opera
        window.clearInterval(pollTimer);
        someFunctionToCallWhenPopUpCloses();
    }
}, 200);

3
我建议使用轮询解决方案而不是unload事件,因为它与更多浏览器兼容(请参阅opera-bugs.jottit.com)。
乔纳森·希尔

@JonathonHill:同意。我在答案的前面提到了Opera的问题,但是我应该更清楚地指出这一点。感谢您的修改。顺便说一句,window.closed !== false在Opera中要求的原因是什么?
Tim Down

这是Opera中错误的解决方法。我是从Opera-bugs.jottit.com发现的。
乔纳森·希尔

@JonathonHill:是的,我阅读了该页面。我希望获得更多细节。不用担心,我会查找的。
Tim Down

1
无论如何,如果使用轮询选项,请务必确保不要忘记window.clearInterval()通话。如果不包括在内,原始页面将继续轮询...一遍又一遍...
codo-sapien

11

有一个非常简单的解决方案来解决您的问题。

首先创建一个新对象,它将打开一个弹出窗口,如下所示:

var winObj = window.open('http://www.google.com','google','width=800,height=600,status=0,toolbar=0');

为了知道何时关闭该弹出窗口,您只需要继续使用如下循环进行检查:

var loop = setInterval(function() {   
    if(winObj.closed) {  
        clearInterval(loop);  
        alert('closed');  
    }  
}, 1000); 

现在,您可以将警报替换为所需的任何JavaScript代码。

玩得开心!:)


7

尝试查看unloadbeforeunload窗口事件。监视这些应该使您有机会在通过以下方式关闭窗口时在DOM卸载时进行回调:

var newWin = window.open('/some/url');
newWin.onunload = function(){
  // DOM unloaded, so the window is likely closed.
}

谢谢ajm看起来很棒。无论如何,是否有机会获得弹出窗口的网址?
巴勃罗

这在跨浏览器中不起作用。您需要unload在弹出窗口中处理事件。
Tim Down'7

每个新请求都会触发卸载,而不仅仅是关闭窗口时。
乔什·斯托多拉

是的,YMMV已卸载。可能需要合并卸载和beforeunload才能覆盖IE。@Josh-每当从浏览器中卸载子窗口的Document而不依赖于请求时,应触发Unload;您看到什么行为?
2010年

例如,如果弹出窗口中有超链接,则单击它们将触发unload
乔什·斯托多拉

6

如果您可以使用jQuery UI对话框,则它实际上有一个close事件。


11
jQuery并非解决所有问题的方法:)。
2010年

11
对,对。我应该以“如果”一词作为“如果您可以使用jQuery UI对话框”中的单词开始回答,而不仅仅是假设这是可能的。嘿! 等一下...
eje211

3
而且,就JavaScript而言,jQuery从来不是真正的问题解决方案,而通常是解决方案的巨大,巨大,巨大的捷径,无论它是什么。您可以通过沿风景优美的路线学习更多信息,但是,在很多情况下,我和大多数人都喜欢(huge,HUGE,HUGE)jQuery快捷方式。
eje211

3

要打开新的窗口调用:

var wnd = window.open("file.html", "youruniqueid", "width=400, height=300");

如果您只想知道该窗口何时关闭,请使用onunload

wnd.onunload = function(){
    // do something
};

如果您希望用户在关闭前确认,请使用onbeforeunload

wnd.onbeforeunload = function(){
    return "are you sure?";
};

1
这在跨浏览器中不起作用。您需要unload在弹出文档中处理事件。
Tim Down'7

1
每个新请求都会触发卸载,而不仅仅是关闭窗口时。
乔什·斯托多拉

3

我们在我的一个工作项目中做到了这一点。

诀窍是要在您的父页面中有一个JS函数,您打算在关闭弹出窗口时调用它,然后在弹出窗口中挂载unload事件。

window.opener属性引用生成此弹出窗口的页面。

例如,如果我callingPageFunction在原始页面上编写了一个命名函数,则可以从弹出窗口中调用它,如下所示:

$(window).unload(function() {
    window.opener.callingPageFunction()
});

两个注意事项:

  1. 这应该包装在ready函数中。
  2. 我有一个匿名函数,因为您可能需要其他逻辑

1

我认为最好的方法是:

const popup = this.window.open(url.toString());
popup.addEventListener('unload', ()=> console.log('closed'))

0

是的,请处理弹出窗口的onbeforeUnload事件,然后使用以下命令在父窗口上调用函数:

window.opener.myFunction()
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.