Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Check if my website is open in another tab

I want to check with JavaScript if the user has already opened my website in another tab in their browser.

It seems I cannot do that with pagevisibility...

The only way I see is to use WebSocket based on a session cookie, and check if the client has more than one socket. But by this way, from current tab, I have to ask my server if this user has a tab opened right next to their current browser tab. It is a little far-fetched!

Maybe with localstorage?

like image 404
ManUtopiK Avatar asked May 16 '14 00:05

ManUtopiK


People also ask

Can a website tell if you open another tab?

Modern websites use multiple "event listeners" and can detect every move the user is executing. So, if a user switches the tab or hovers over to another tab, it can gather the data and see whether the user stayed on the web page or not. A website can detect this anomaly by using cookies and IDs.

How do I stop a URL being opened in another tab?

You cannot (and should not) do that. User can always just open use another browser or another computer to open another view onto the web site. So, basically you cannot ever prevent this. Your web-site should be able to handle multiple tabs viewing the same state.

How do you check if a tab is already open in Javascript?

How do you check if a tab is already open in Javascript? if (+localStorage. tabCount > 0) alert('Already open! '); else localStorage.


2 Answers

Using local storage I created a simple demo that should accomplish what your looking to do. Basically, it simply maintains a count of currently opened windows. When the window is closed the unload events fire and remove it from the total window count.

When you first look at it, you may think there's more going on than there really is. Most of it was a shotty attempt to add logic into who was the "main" window, and who should take over as the "main" window as you closed children. (Hence the setTimeout calls to recheck if it should be promoted to a main window) After some head scratching, I decided it would take too much time to implement and was outside the scope of this question. However, if you have two windows open (Main, and Child) and you close the Main, the child will be promoted to a main.

For the most part you should be able to get the general idea of whats going on and use it for your own implementation.

See it all in action here: http://jsbin.com/mipanuro/1/edit

Oh yeah, to actually see it in action... Open the link in multiple windows. :)

Update:

I've made the necessary changes to have the the local storage maintain the "main" window. As you close tabs child windows can then become promoted to a main window. There are two ways to control the "main" window state through a parameter passed to the constructor of WindowStateManager. This implementation is much nicer than my previous attempt.

JavaScript:

// noprotect  var statusWindow = document.getElementById('status');  (function (win) {     //Private variables     var _LOCALSTORAGE_KEY = 'WINDOW_VALIDATION';     var RECHECK_WINDOW_DELAY_MS = 100;     var _initialized = false;     var _isMainWindow = false;     var _unloaded = false;     var _windowArray;     var _windowId;     var _isNewWindowPromotedToMain = false;     var _onWindowUpdated;           function WindowStateManager(isNewWindowPromotedToMain, onWindowUpdated)     {         //this.resetWindows();         _onWindowUpdated = onWindowUpdated;         _isNewWindowPromotedToMain = isNewWindowPromotedToMain;         _windowId = Date.now().toString();          bindUnload();          determineWindowState.call(this);          _initialized = true;          _onWindowUpdated.call(this);     }      //Determine the state of the window      //If its a main or child window     function determineWindowState()     {         var self = this;         var _previousState = _isMainWindow;          _windowArray = localStorage.getItem(_LOCALSTORAGE_KEY);          if (_windowArray === null || _windowArray === "NaN")         {             _windowArray = [];         }         else         {             _windowArray = JSON.parse(_windowArray);         }          if (_initialized)         {             //Determine if this window should be promoted             if (_windowArray.length <= 1 ||                (_isNewWindowPromotedToMain ? _windowArray[_windowArray.length - 1] : _windowArray[0]) === _windowId)             {                 _isMainWindow = true;             }             else             {                 _isMainWindow = false;             }         }         else         {             if (_windowArray.length === 0)             {                 _isMainWindow = true;                 _windowArray[0] = _windowId;                 localStorage.setItem(_LOCALSTORAGE_KEY, JSON.stringify(_windowArray));             }             else             {                 _isMainWindow = false;                 _windowArray.push(_windowId);                 localStorage.setItem(_LOCALSTORAGE_KEY, JSON.stringify(_windowArray));             }         }          //If the window state has been updated invoke callback         if (_previousState !== _isMainWindow)         {             _onWindowUpdated.call(this);         }          //Perform a recheck of the window on a delay         setTimeout(function()                    {                      determineWindowState.call(self);                    }, RECHECK_WINDOW_DELAY_MS);     }      //Remove the window from the global count     function removeWindow()     {         var __windowArray = JSON.parse(localStorage.getItem(_LOCALSTORAGE_KEY));         for (var i = 0, length = __windowArray.length; i < length; i++)         {             if (__windowArray[i] === _windowId)             {                 __windowArray.splice(i, 1);                 break;             }         }         //Update the local storage with the new array         localStorage.setItem(_LOCALSTORAGE_KEY, JSON.stringify(__windowArray));     }      //Bind unloading events       function bindUnload()     {         win.addEventListener('beforeunload', function ()         {             if (!_unloaded)             {                 removeWindow();             }         });         win.addEventListener('unload', function ()         {             if (!_unloaded)             {                 removeWindow();             }         });     }      WindowStateManager.prototype.isMainWindow = function ()     {         return _isMainWindow;     };      WindowStateManager.prototype.resetWindows = function ()     {         localStorage.removeItem(_LOCALSTORAGE_KEY);     };      win.WindowStateManager = WindowStateManager; })(window);  var WindowStateManager = new WindowStateManager(false, windowUpdated);  function windowUpdated() {     //"this" is a reference to the WindowStateManager     statusWindow.className = (this.isMainWindow() ? 'main' : 'child'); } //Resets the count in case something goes wrong in code //WindowStateManager.resetWindows() 

HTML:

<!DOCTYPE html> <html> <head>   <meta charset="utf-8">   <title>JS Bin</title> </head> <body>   <div id='status'>      <span class='mainWindow'>Main Window</span>     <span class='childWindow'>Child Window</span>   </div> </body> </html> 

CSS:

#status {   display:table;   width:100%;   height:500px;   border:1px solid black; } span {   vertical-align:middle;   text-align:center;    margin:0 auto;   font-size:50px;   font-family:arial;   color:#ba3fa3;     display:none; }  #status.main .mainWindow, #status.child .childWindow {   display:table-cell; }  .mainWindow {   background-color:#22d86e; } .childWindow {   background-color:#70aeff; } 
like image 144
cgatian Avatar answered Sep 19 '22 17:09

cgatian


The shorter version with localStorage and Storage listener

<script type="text/javascript">         // Broadcast that you're opening a page.         localStorage.openpages = Date.now();         var onLocalStorageEvent = function(e){             if(e.key == "openpages"){                 // Listen if anybody else is opening the same page!                 localStorage.page_available = Date.now();             }             if(e.key == "page_available"){                 alert("One more page already open");             }         };         window.addEventListener('storage', onLocalStorageEvent, false); </script> 

Update:

  • Works on page crash as well.
  • Stimulate page crash in chrome: chrome://inducebrowsercrashforrealz

Live demo

like image 23
Sasi Varunan Avatar answered Sep 17 '22 17:09

Sasi Varunan