0

我需要使用window.open('...', '_blank');

然后,当用户单击按钮(按钮位于新选项卡中)时,我需要该选项卡自行关闭。

我可以控制这两个应用程序的代码库和服务器。

我尝试了以下方法:

在应用程序#1 中:

window.tab = window.open('http://localhost:5007', '_blank');

在应用程序#2 中:

function clickedButton() {
    window.opener.tab.close();
}

不幸的是,我得到了安全异常:错误:阻止了具有源“ http://localhost:5007 ”的框架访问跨域框架。

我怎样才能绕过这个错误?无论如何我可以使用这个库来克服这个问题吗?https://github.com/ternarylabs/porthole

4

2 回答 2

1

好的,我能够通过使用 porthole.js 以我理论化的方式完成此任务。我相信这是在不使用 hack 的情况下实现这一目标的唯一跨浏览器方式。

该解决方案由 2 个应用程序组成(您必须向这两个应用程序添加代码才能正常工作)。

app #1: http://localhost:4000
app #2: http://localhost:5000

就我而言,我需要 app#1 来生成包含 app#2 的需求选项卡。然后我需要 app#2 能够在单击 app#2 内的按钮时自行关闭。

如果这些应用程序位于同一域(包括同一端口)上,则通过保存对 app#1 中选项卡的引用,这将相对容易:

window.tab = window.open('...', '_blank');

然后通过 app#2 访问该引用window.opener.tab.close()

但是,就我而言,应用程序需要位于不同的域上,并且执行此方法会导致浏览器安全异常。因此,相反,我需要做的是在 app#1 内的 iframe 中托管 app#2(在某些特定路线上,例如 /iframe),这样就浏览器窗口而言,它们位于同一个域中,现在第二个选项卡应该能够使用window.opener.tab.close().

但是,问题仍然存在,因为我需要触发器是应用程序#2 内的按钮(也就是 iframe 内的按钮),并且由于托管应用程序和 iframe 应用程序再次不在同一个域中,所以我似乎会回到第一方......或者也许不是。

在这种情况下,porthole.js 节省了时间。您必须将 porthole.js 加载到两个应用程序中(这就是您需要访问两个代码库的原因)。这是代码:

在 app#1 ( http://localhost:4000/iframe )

// create a proxy window to send to and receive messages from the iFrame
var windowProxy;
window.onload = function() {
    windowProxy = new Porthole.WindowProxy(
        'http://localhost:5000', 'embedded-iframe');

    windowProxy.addEventListener(function(event) { 
       //handle click event from iframe and close the tab 
       if(event == 'event:close-window') {
           window.opener && window.opener.tab && window.opener.tab.close();
       }
    });
}

在应用程序#2 中:(http://localhost:5000

    var windowProxy;
    window.onload = function() {
        windowProxy = new Porthole.WindowProxy(
            'http://localhost:4000/#/iframe');

        $('button').on('click', function() {
            windowProxy.post('event:close-window');
        });
    }

还有 wa-lah,一个自动关闭的标签。

于 2015-10-22T14:06:03.393 回答
1

我只是在这里引用文档,任何需要参考的人都可以点击W3CMDN

function openWin() {
    myWindow = window.open("", "myWindow", "width=200, height=100");   // Opens a new window
}

function closeWin() {
    myWindow.close();   // Closes the new window
}

分解它,openclose函数使用的参数非常有用,例如URL, 当希望打开或关闭当前窗口时,或者在您的情况下是打开的窗口。

一个实际的例子是这个堆栈溢出问题。ñ

我希望它有帮助!

编辑

要回答 OP 对问题的编辑:如果是在打开的窗口上触发事件,您可以在新窗口上有一个事件处理程序,它将window.close()像这样触发:

$('#anElementId').click(function() { window.opener.$('body').trigger('theCloseEvent', anyPassedData); })

但是,如果您确实可以控制新选项卡,因为它指向一个您可以控制其代码库的 URL,那么只需在该处触发一个事件,您可以在窗口加载后触发该事件,或者一旦你点击一个按钮......就像这样:

HTML

<button id="close-window">Close me</button>

Javascript/jQuery:

$(document).ready(function(){
    $("#close-window").click(function(){
        alert("ok");
        window.close();
    });
});

编辑#2

为了进一步扩展 OP 的编辑,我想在此处包含一个在尝试触发打开的窗口自行关闭时很容易遇到的问题。

引自如何关闭浏览器窗口而不收到“您要关闭此窗口”提示?

不允许脚本关闭用户打开的窗口。这被认为是一种安全风险。虽然它没有任何标准,但所有浏览器供应商都遵循这一点(Mozilla 文档)。如果在某些浏览器中发生这种情况,这是一个安全漏洞(理想情况下)会很快得到修补。

这个问题的答案中的任何黑客都不再有效,如果有人想出另一个肮脏的黑客,最终它也会停止工作。

我建议您不要为此浪费精力,而是采用浏览器为您提供的非常有用的方法——在您看似崩溃他们的页面之前询问用户。

换句话说,除非您的网页脚本可以控制打开的窗口,否则您应该/不能关闭所述窗口。那是因为运行的脚本window.close不受打开的窗口的控制。

编辑#3

我知道这么多编辑!但我在我的日常生活之间回答这个问题,所以请耐心等待。要回答 porthole.js 的问题,应该更有可能用它做一些事情,但是您需要意识到您正在使用 iframe。

使用网站与使用iframe存在显着差异,其中 iframe 是小部件,网站(包括迷你网站)被赋予 URL。在安全性和沙盒方面也有很多考虑因素,可以在此处的 portholejs 演示中看到。这种差异也不允许您以最初想要的方式使用不同的网站。

我的建议是评估您在实施方面的选择:网站到网站与网站到小部件。

祝你好运!

于 2015-10-21T15:26:12.080 回答