0

I need to spawn a tab using window.open('...', '_blank');

Then, I need that tab to CLOSE ITSELF, when the user click a button (button is in the new tab).

I have control over the codebase and server of both applications.

I tried the following:

in app#1:

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

in app#2:

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

Unfortunately I get security exception: Error: Blocked a frame with origin "http://localhost:5007" from accessing a cross-origin frame.

How can I get around this error? Is there anyway I can use this library to overcome this? https://github.com/ternarylabs/porthole

parliament
  • 21,544
  • 38
  • 148
  • 238
  • you can invoke javascript when the window loads to do window.close() on button click – AGE Oct 21 '15 at 15:20
  • I'm pretty sure windows opened with `window.open()` can be closed with `window.close()`. – Tim Lewis Oct 21 '15 at 15:21
  • 1
    Possible duplicate of [How to close current tab in a browser window?](http://stackoverflow.com/questions/2076299/how-to-close-current-tab-in-a-browser-window) – Asons Oct 21 '15 at 15:21
  • Not a duplicate, I'm asking a different question. See edit – parliament Oct 21 '15 at 16:06
  • @parliament read my edit#2 in order to understand why your latest edit does not work and why a fix/hack that completely solves the issue does not exist. – AGE Oct 21 '15 at 17:00
  • @AGE I was able to accomplish what I wanted using porthole.js. I posted an answer how. Thanks for the help though – parliament Oct 22 '15 at 14:10

2 Answers2

1

I am simply going to quote documentation here, just for anyone who needs a reference click W3C and MDN.

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

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

To break it down, the open and close functions use parameters than can be very useful, such as the URL, when desiring to open or close the current window, or in your case the opened window.

A practical example would be this stack overflow question. N

I hope it helps!

EDIT

To answer the OP's edit to the question: If it is a matter of triggering an event on a window which was opened, you can on the new window have an event handler which will trigger window.close() like so:

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

However, if you truly do have control over the new tab, because it leads to a URL whose code base you are in control of, then it is only a matter of triggering an event there that you can trigger either once the window loads, or once you click a button... like so:

HTML

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

Javascript/jQuery:

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

EDIT #2

To further extend the OP's edit, I want to include here an issue that can easily be encountered when attempting to trigger the opened window to close itself.

Quoted from How can I close a browser window without receiving the “Do you want to close this window” prompt?:

Scripts are not allowed to close a window that a user opened. This is considered a security risk. Though it isn't in any standard, all browser vendors follow this (Mozilla docs). If this happens in some browsers, it's a security bug that (ideally) gets patched very quickly.

None of the hacks in the answers on this question work any longer, and if someone would come up with another dirty hack, eventually it will stop working as well.

I suggest you don't waste energy fighting this and embrace the method that the browser so helpfully gives you — ask the user before you seemingly crash their page.

In other words, unless your webpage's script has control of the window which was opened, you should/cannot close said window. That is because the script running the window.close is not in control of the opened window.

EDIT #3

So many edits I know! But I am answering this in between my daily routine so bear with me. To answer the porthole.js question, it should be much more possible to do something with it, however you need to realize that you are working with iframes.

There is a significant difference when working with websites vs working with iframes, in which iframes are Widgets and websites (including mini sites) are given a URL. There are lots of considerations as well in terms of security and sandboxing, as can be seen on the portholejs demo here. This difference is also what does not allow you to work with different websites the way you want to initially.

My advise would be to evaluate your options with respect to your implementation: website to website vs website to widget.

Good luck!

Community
  • 1
  • 1
AGE
  • 3,752
  • 3
  • 38
  • 60
  • Please see edit. This is not what I'm asking. Is there any way to pass the reference to the myWindow.close() function INTO the second window, so that the second window can CLOSE ITSELF. I have control over both codebases. – parliament Oct 21 '15 at 16:07
  • 1
    When you open this new tab/window, the window will close itself automatically without a delay in time? Or will it wait for you to do something to close it such as a button press? – AGE Oct 21 '15 at 16:10
  • 1
    @parliament control over both codebases means javascript control over the new window, which you have access to and can modify at any time? – AGE Oct 21 '15 at 16:12
  • yes, the user need to click a button in the new tab to close the new tab (revealing the previous tab that originally spawned it). And yes, I have control over and can modify code in both apps, the one spawning the new tab, as well as the app being loaded in the new tab. – parliament Oct 21 '15 at 16:21
  • 1
    Ok so it flows like so: a window, click on a button opens a new window, click on that button, close the current window, reveal the window that spawned it... how? I have made edits to my answer to help you reach an answer while you are working on it. As you can see I am only struggling to adhere to your implementation, but the code is already starting to take shape. – AGE Oct 21 '15 at 16:27
  • I edited the question again with something i tried. I used window.opener too but let me try your approach of firing an event on the original window, that just might work – parliament Oct 21 '15 at 16:31
  • Ok, it didnt work. Trying to access window.opener.$('body') throws the same cross-domain exception I was getting trying to call window.opener.tab.close(). I also have the idea that I can spawn app#2 in an iframe in the new tab on the same domain as app#1. But then the problem is passing the click event from the button inside the iframe, to the outside of the iframe so that I can call window.opener.tab.close() (which would now be on the same domain). But I think this can be accomplished via porthole.js . Do you think this will work? – parliament Oct 21 '15 at 16:40
  • You should know that closing a window that you did not open yourself will not work in Javascript, jQuery might give you a warning however this is due to the mechanism imparted into window.open, you need that reference in order to close the window itself. It is a cross browser compatibility issue you can look into if you like – AGE Oct 21 '15 at 16:40
  • @parliament I am not familiar with porthole.js, but it could end up being a good question to ask on stack overflow, which could add to the answer you are looking for. Try to consider the possibilities first: it may not be possible. As far as my research and understanding goes, using javascript to close the current window (without you having opened it) simply doesn't work, as a matter of fact it's a hack and it's not cross browser compatible anyways. See here: http://stackoverflow.com/questions/57854/how-can-i-close-a-browser-window-without-receiving-the-do-you-want-to-close-thi – AGE Oct 21 '15 at 16:43
1

Ok, I was able to accomplish this in the way I theorized by using porthole.js. I believe this is the only cross-browser way to accomplish this without using hacks.

The solution consists of 2 apps (you must add code to both app for this to work).

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

In my case, I needed app#1 to spawn a need tab containing app#2. Then I needed app#2 to be able to CLOSE ITSELF upon clicking a button inside app#2.

If these apps were on the same domain (including same port), this would be relatively easy by saving a reference to the tab in app#1:

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

And then accessing that reference from within app#2 via window.opener.tab.close()

However, for my case the apps needed to be on diff domains and doing this method resulted in a browser security exception. So instead, what I needed to do was host app#2 within an iframe inside app#1 (on some specific route, say /iframe), this way they ARE on the same domain as far as the browser windows are concerned, and now the second tab should be able to close itself using window.opener.tab.close().

However, a problem still remained because I needed the trigger to be a button INSIDE app#2 (aka a button inside the iframe), and since the hosting app and the iframe app are again not on the same domain, it seems like I would be back to square one... or maybe not.

In this case, porthole.js saves the day. You must load porthole.js into both apps (this is why you need access to both codebases). Here's the code:

in 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();
       }
    });
}

in app#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');
        });
    }

And wa-lah, a self closing tab.

parliament
  • 21,544
  • 38
  • 148
  • 238