Search code examples
javascriptphptabsdom-eventsdom-manipulation

Javascript close window


I have a link in page_a.php which opens in new tab using target="_blank".

 <a href="page_b.php" target="_blank">Open Page B</a>

In the page B I have a script that will automatically close the tab/window once the user is no longer viewing it. My script looks like this:

<script type="text/javascript">
    function handleVisibilityChange() {
      if (document.visibilityState == "hidden") {
        window.close();
        console.log("hidden");
      } else {
        console.log("shown");
      }
    }
    document.addEventListener('visibilitychange', handleVisibilityChange, false);
</script>

So I have:

 localhost/test/page_a.php //loads jQuery
 localhost/test/page_b.php //doesn't load jQuery

On page_b.php I get the warning:

Scripts may close only the windows that were opened by it.

Since I am in-fact the one opening the window, is there a way to make this work?


Solution

  • The window must have been opened with JavaScript's window.open(), not with a <a href="..." target="..."> link. See window.close() documentation for more details.

    One way to do this, for instance, is by listening for the click event on the link, prevent the default action and then explicitly open the window with JavaScript:

    <script type="text/javascript">
      // wait for the DOM to have loaded
      document.addEventListener( 'DOMContentLoaded', function( e ) {
        let link = document.querySelector( 'some selector to get the proper link element' );
        link.addEventListener( 'click', function( e ) {
          // prevent window opening regularly
          e.preventDefault();
          // explicitly open with JavaScript
          window.open( this.href, 'MyNewWindow' );
        } );
      } );
    </script>
    

    There are possible issues with this, though:

    1. Your users may have configured their browsers to prevent opening new windows.
    2. If a user accesses page_b.php by some other means than through clicking your link, closing the window will not work either. You have to explicitly test whether the window was opened by your other window with window.opener:

      <script type="text/javascript">
        /*
           ...
        */
        // if this window has a reference to the window that opened this window
        if( window.opener ) {
          document.addEventListener('visibilitychange', handleVisibilityChange, false);
        }
      </script>
      

      But as you can see in the documentation, window.opener has its own issues as well.