porthole.js - 如何关闭我使用window.open()打开的选项卡,但是从新选项卡中关闭

时间:2015-10-21 15:17:29

标签: javascript html5 porthole.js

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

生成一个标签

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

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

我尝试了以下内容:

在app#1中

window.tab = window.open('http://localhost:5007', '_blank');
在app#2中

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

不幸的是我得到了安全性异常: 错误:阻止了包含原点" http://localhost:5007"从访问跨源框架。

如何解决此错误?无论如何我可以使用这个库来克服这个问题吗? https://github.com/ternarylabs/porthole

2 个答案:

答案 0 :(得分: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,当希望打开或关闭当前窗口时,或者你的情况是打开窗口。

一个实际的例子是this堆栈溢出问题。 Ñ

我希望它有所帮助!

修改

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

window.close()

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

HTML

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

的Javascript / jQuery的:

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

编辑#2

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

引自How can I close a browser window without receiving the “Do you want to close this window” prompt?

  

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

     

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

     

我建议你不要浪费精力去争取这个,并采用浏览器如此有用的方法 - 在看似崩溃他们的页面之前询问用户。

换句话说,除非您的网页脚本控制了打开的窗口,否则您应该/不能关闭所述窗口。这是因为运行$(document).ready(function(){ $("#close-window").click(function(){ alert("ok"); window.close(); }); }); 的脚本无法控制打开的窗口。

编辑#3

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

使用网站与使用 iframes 时存在显着差异,其中iframe是Widgets,网站(包括迷你网站)都有URL。在portholejs demo here上可以看到,在安全性和沙盒方面也有很多考虑因素。这种差异也是不允许您以最初的方式使用不同网站的原因。

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

祝你好运!

答案 1 :(得分:1)

好的,我能够通过使用porthole.js理论化的方式实现这一目标。 我相信这是唯一一种不使用黑客来实现这一目标的跨浏览器方式。

该解决方案包含2个应用程序(您必须在两个应用程序中添加代码才能实现此目的)。

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

在我的情况下,我需要app#1来生成包含app#2的need选项卡。然后我需要app#2才能在单击app#2内的按钮时关闭自己。

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

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

然后通过window.opener.tab.close()

从应用#2中访问该引用

但是,对于我的情况,应用程序需要在差异域上,并且执行此方法会导致浏览器安全性异常。因此,我需要做的是在app#1内的iframe中托管应用#2(在某些特定路线上,比如/ iframe),这样就浏览器窗口而言,它们就在同一个域中,现在第二个标签应该能够使用window.opener.tab.close()关闭自己。

然而,问题仍然存在,因为我需要触发器作为按钮INSIDE app#2(也就是iframe中的按钮),并且由于托管应用和iframe应用程序再次不在同一个域中,似乎就像我会回到原点......或许不是。

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

应用#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,一个自我关闭标签。