oliverbj
oliverbj

Reputation: 6052

Detect if browser tab is active or user has switched away

How can I detect if a user is switching to another browser tab?

Currently, I have this:

$(window).on("blur focus", function (e) {

    var prevType = $(this).data("prevType");

    if (prevType != e.type) { //  reduce double fire issues
        switch (e.type) {
            case "blur":
                $('.message').html('<div class="alert alert-error">Oops. You navigated away from the ads <a id="start" class="butt green">Resume</a></div>');

                var myDiv = $("#bar");
                myDiv.clearQueue();
                myDiv.stop();
                clearInterval($timer);
                $timer = null;
                break;
            case "focus":
                // do work
                break;
        }
    }

    $(this).data("prevType", e.type);
});

But that only works when the user is minimizing the active window.

Upvotes: 68

Views: 91094

Answers (6)

Wesley McGinn
Wesley McGinn

Reputation: 11

The answer can really be very simple:

document.hidden

This will return false when the user is actively on the tab and will immediately switch to true when the user minimises or goes to another tab.

If you want function a() to run when you are in the tab and function b() to run when you are away, something like this should do:

setInterval(function() {
  if (document.hidden) {
    b();
  } else {
    a();
  }
}, 100);

Upvotes: 0

Hexodus
Hexodus

Reputation: 12927

This is an ES6 multi-browser-solution which I use to determine the tab visibility. I took inspiration from Deny's solution and tailored it to my needs.

const vis = (c) => {
  let self = this
  const browserProps = {
    hidden: "visibilitychange",
    msHidden: "msvisibilitychange",
    webkitHidden: "webkitvisibilitychange",
    mozHidden: "mozvisibilitychange",
  }
  for (item in browserProps) {
    if (item in document) {
      eventKey = browserProps[item]
      break
    }
  }

  if (c) {
    if (!self._init && !(typeof document.addEventListener === "undefined")) {
      document.addEventListener(eventKey, c)
      self._init = true
      c()
    } 
  }
  return  !document[item] 
}

vis(() => {
  let tabVisibility = vis() ? 'Visible' : 'Not visible';
  console.log(tabVisibility)
})

Upvotes: 4

danefondo
danefondo

Reputation: 555

If you want to detect whether the tab is visible to the user, use document.visibilityState to perform the check (a read-only property). Although document.hidden works too, as others have written, then W3C considers it 'historical' and recommends using the former approach.

If you only want to know whether the tab is active, use document.hasFocus() to perform the check. In this case, the tab could still otherwise be visible, but not active (e.g. two parallel view browser windows, where only one is active, both visible).

If you want capture the change to the state of visibility (and naturally also the active state in this case), then listen to the visibilitychange event from the Page Visibility API.

Example using all three

// Capture change to visibility
document.addEventListener("visibilitychange", function() {
    // Check if tab content is visible
    if (document.visibilityState) { 
        console.log("Tab is visible!") 
    }

    // Check if tab is active
    if (document.hasFocus()) {
        console.log("Tab is active!");
    }
});

Handling browser compatibilities

You can set up the following checks to cover incompatible browsers.

Note: Does not include hasFocus() as it's compatible all the way to IE6.

var visibilityState, visibilityChange;
if (typeof document.visibilityState !== "undefined") {
    visibilityState = "visibilityState";
    visibilityChange = "visibilitychange";
} 
else if (typeof document.mozVisibilityState !== "undefined") {
    visibilityState = "mozVisibilityState";
    visibilityChange = "mozvisibilitychange";
} 
else if (typeof document.msVisibilityState !== "undefined") {
    visibilityState = "msVisibilityState";
    visibilityChange = "msvisibilitychange";
} 
else if (typeof document.webkitVisibilityState !== "undefined") {
    visibilityState = "webkitVisibilityState";
    visibilityChange = "webkitvisibilitychange";
}

if (visibilityChange != null && visibilityState != null) {
    document.addEventListener(visibilityChange, function() {
        if (document[visibilityState]) { 
            console.log("Tab is visible!") 
        }
    }, false);
}

Quick MDN references

Upvotes: 9

Rohit Tagadiya
Rohit Tagadiya

Reputation: 3730

CASE 1

Just add this EventListener in your constructor.

document.addEventListener("visibilitychange", function() {
      if (document.hidden) {
        //do whatever you want
        console.log("Hidden");
      }
      else {
        //do whatever you want
        console.log("SHOWN");
      }
});

CASE 2

See here If you change tab $(window).blur(function () function will call and If you again come to this tab $(window).focus(function () function will call. Add this code in your constructor

$(window).focus(function () {
      //do something
       console.log("You are in this tab");
});

$(window).blur(function () {
      //do something
       console.log("You left this tab");
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<p>Click here and click outside of this..</p>

Upvotes: 7

Sahil Ralkar
Sahil Ralkar

Reputation: 2424

These 3 lines of code worked for me

document.addEventListener("visibilitychange", function() {
      document.title = document.hidden ? "I'm away" : "I'm here";
});
      

reference link: document.hidden

demo: https://iamsahilralkar.github.io/document-hidden-demo/

Upvotes: 29

Denys S&#233;guret
Denys S&#233;guret

Reputation: 382132

Now we can use the visibility API.

To deal with the different browser-specific syntaxes, I made this small code :

var vis = (function(){
    var stateKey, eventKey, keys = {
        hidden: "visibilitychange",
        webkitHidden: "webkitvisibilitychange",
        mozHidden: "mozvisibilitychange",
        msHidden: "msvisibilitychange"
    };
    for (stateKey in keys) {
        if (stateKey in document) {
            eventKey = keys[stateKey];
            break;
        }
    }
    return function(c) {
        if (c) document.addEventListener(eventKey, c);
        return !document[stateKey];
    }
})();

Usage :

var visible = vis(); // gives current state

vis(aFunction);      // registers a handler for visibility changes

Example :

vis(function(){
  document.title = vis() ? 'Visible' : 'Not visible';
});

Demonstration page

Upvotes: 178

Related Questions