检查弹出窗口是否已关闭

15

我正在打开一个弹出窗口:

var popup = window.open('...', '...');

这段JavaScript代码被定义在一个控件中,然后从Web页面中使用该控件。我想要在弹出窗口关闭时重新加载打开此弹出窗口的页面。

基本上用户需要在弹出窗口中输入一些面额并提交。然后这些面额将存储在用户会话中。当用户点击提交时,我会关闭弹出窗口并同时刷新打开此弹出窗口的页面,以便重新获取用户在弹出窗口中进行的更新。

我正在尝试实现:

var popup = window.open('...','...');
if (popup) {
  popup.onClose = function () { popup.opener.location.reload(); }
}
我猜我做错了因为这似乎没有起作用。为了测试这个问题,我甚至尝试了这个方法,但是没有弹出警报。
if (popup) {
  popup.onclose = function() { 
    alert("1.InsideHandler");
    if (opener && !opener.closed) { 
      alert("2.Executed.");
      opener.location.reload(true); 
    } else { 
      alert("3.NotExecuted.");
    }
  }
}

你尝试过使用模态弹出窗口吗? - atrljoe
除非您将表单提交到iFrame,否则不要在模态窗口中提交表单。 - mplungjan
5个回答

8

以下是我的建议。

在弹出窗口中,您应该有:

<script type="text/javascript">

function reloadOpener() {
  if (top.opener && !top.opener.closed) {
    try {
      opener.location.reload(1); 
    }
    catch(e) {
    }
    window.close();
  }
}
window.onunload=function() {
  reloadOpener();
}
</script>

<form action="..." target="hiddenFrame">
</form>
<iframe style="width:10px; height:10px; display:none" name="hiddenFrame" src="about:blank"></iframe>

在服务器进程中,您可以返回以下内容。
<script>
   top.close();
</script>

旧建议

在弹出窗口中没有名为popup的变量。 请尝试:

var popup = window.open('...','...');
if (popup) {
  popup.onclose = function () { opener.location.reload(); }
}

或者使用测试:
popup.onclose = function () { if (opener && !opener.closed) opener.location.reload(); }

PS: onclose并不被所有浏览器支持。

PPS: location.reload需要一个布尔值,如果你不想从缓存中加载,请添加true,例如opener.location.reload(1);


当弹出窗口打开时,窗口会立即重新加载。 - S M Kamran
顺便提一下,它应该是 "onclose",小写的 C。并非所有浏览器都支持。 - mplungjan
我甚至尝试过这个,但没有弹出警告 >>>> popup.onclose = function() { alert("1.InsideHandler"); if (opener && !opener.closed) { alert("2.Executed."); opener.location.reload(true); } else { alert("3.NotExecuted."); } } - S M Kamran
这在 Fx 中不会失败,但不会在弹出窗口中执行脚本。它在 IE8 中会失败 http://jsfiddle.net/mplungjan/pxySQ/ - mplungjan
1
抱歉,我真的不知道为什么会给这个回答点踩。可能是因为我太累了,误点了一下。除非这个回答被编辑过,否则我无法撤销我的投票。对此我感到很抱歉。 - Felix Bernhard
显示剩余2条评论

3

解决同源弹出窗口问题

如果您的弹出窗口与打开者具有相同的源,您可以像这样将事件监听器附加到弹出窗口:

const popup = window.open('...', '...');

popup.window.addEventListener('load', () => {
    popup.window.addEventListener('unload', () => {
        console.log('> Popup Closed');
        // window.location.reload();
    });
});

请注意,卸载事件监听器需要在弹出窗口加载后添加。这是因为卸载事件也会在弹出窗口的页面加载时触发。

不同来源弹出窗口的解决方案

如果您的弹出窗口与打开者不属于同一来源,则在尝试添加监听器时,您将收到以下错误:Blocked a frame with origin from accessing a cross-origin frame.出于安全原因,您只能从打开者和打开的窗口访问有限的属性。 更多信息请点击此处

解决方案1

如果您可以访问弹出窗口中的来源,则可以在弹出窗口中创建卸载事件监听器,并调用window.opener.location.replace(OPENER_URL)。缺点是您需要打开者的URL。您可以将OPENER_URL作为查询字符串传递给弹出窗口,而不是硬编码。

请注意,在跨源场景中不允许使用window.opener.location.reload(),因此您必须使用.replace(OPENER_URL)

解决方案2

你可以在打开器中创建一个间隔,定期检查窗口是否打开或关闭,使用 window.closed 属性即可。
const popup = window.open('...', '...');

const interval = setInterval(() => {
    if (popup.closed) {
        clearInterval(interval);
        console.log('> Popup Closed');
        // window.location.reload();
    }
}, 500);

这可能是最灵活的解决方案。它也被PayPal API用于付款弹出窗口(使用closed属性的polyfill)


2

试试这个:

window.opener.location.reload(true);

或者

在关闭前进入弹出窗口

window.opener.location.href = window.opener.location.href;
window.close();

0

相反,您应该使用模态对话框,如下所示

var popup = window.showModalDialog("page.html", "", params);

这会在此行停止,直到对话框关闭。

然后,在您的 page.html 中的某个位置,您将编写一些 JavaScript 代码来设置 window.returnValue,这是将放置在弹出变量中的内容。

更新

Window.showModalDialog() 现在已经过时 (链接)


除非有一个 iframe 用于提交,否则在模态窗口中提交表单是有技巧的。 - mplungjan
他们有什么办法阻止将其放置在iframe中? - Ash Burlaczenko
要求使用无模式。 - S M Kamran

0

好的,你需要按照以下步骤进行操作。

创建一个名为“setWindowObjectInParent”的方法,然后在弹出窗口中调用它。 var popupwindow;

function setWindowObjectInParent(obj)
{
popupwindow = obj;
}

现在你有一个可以调用focus的对象。
因此,在弹出窗口中添加。
$(window).unload(function(){
window.opener.setWindowObjectInParent();
});
window.opener.setWindowObjectInParent(window);

当弹出窗口关闭时,将取消设置 obj,并在打开时设置对象。

因此,您可以检查弹出窗口是否已定义,然后调用 focus。


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