Determine if a tab has focus in JavaScript

Tabbed browsing has become the standard so modern browsers have provided a way for developers to determine if a tab has focus. This uses the HTML 5 Page Visibility API. Different browsers currently use different implementations, but this guide should help simplify things for you.

1

document.hidden

The first and most simple thing this API provides is a property on the document that lets you know if the page is currently hidden. To run a quick test, open the console on this very page (cmd + option + j on Mac) and type:

document.hidden
As expected this should print:
false
Obviously, the page you are currently viewing is not hidden. But now type this into your console:
setTimeout(function() { console.log(document.hidden); }, 4000);
and immediately switch to another tab. Wait at least four seconds and switch back to this tab. You will now see:
true
This is because the page was hidden when the timeout callback fired.

2

There are three possible visibility states: hidden, visible, and prerender. hidden and visible are self-explanatory, and prerender is simply the state before the page is fully rendered while the tab is in focus.

3

This is the event that is fired whenever the browser comes into or goes out of focus.

document.addEventListener('visibilitychange', function(e) {
    console.log(document.hidden);
});

4

The following code is a modification of what you'll find at the Mozilla Developer Network documentation for the Page Visibility API.

// Set the name of the hidden property and the change event for visibility
var hidden, visibilityChange;
if (typeof document.hidden !== "undefined") { // Opera 12.10 and Firefox 18 and later support
    hidden = "hidden";
    visibilityChange = "visibilitychange";
    state = "visibilityState";
} else if (typeof document.mozHidden !== "undefined") {
    hidden = "mozHidden";
    visibilityChange = "mozvisibilitychange";
    state = "mozVisibilityState";
} else if (typeof document.msHidden !== "undefined") {
    hidden = "msHidden";
    visibilityChange = "msvisibilitychange";
    state = "msVisibilityState";
} else if (typeof document.webkitHidden !== "undefined") {
    hidden = "webkitHidden";
    visibilityChange = "webkitvisibilitychange";
    state = "webkitVisibilityState";
}
We need to determine the correct attribute names based on the browser. So utilizing the code above we will access our hidden property like this:
document[hidden]
as opposed to:
document.hidden
This will help keep our code compatible across browsers. Whenever a user changes tabs and the visibility state changes, an event is fired. To listen to the event you can do the following:
document.addEventListener(visibilityChange, function() {
    console.log(document[hidden]);
});
With the code above, you can switch tabs and it will log the state to the console.

5

Check out our page-visibility module on Github. We will probably expand this over time, but the main purpose is to abstract the code that makes this thing cross browser compatible. So with our module, instead of doing this:

document[hidden]
or
document.hidden
you can do:
Visibility.isHidden()
And you can also get the event name easily:
document.addEventListener(Visibility.visibilitychange, function() {
    console.log(Visibility.isHidden());
});
And if you want your callback to run only the first time the page becomes visible you can do this:
document.addEventListener(Visibility.visibilitychange, function(e) {
    var hidden = Visibility.isHidden();
    if (!hidden) {
        console.log('This first only the first time the page is visible!!');
        e.target.removeEventListener(e.type, arguments.callee);
    }
});