Coding Robin

Using the PageVisibility API

13 March 2013, posted by Robin Mehner

Thanks to the new APIs and features coming to us through better implementations of HTML5, CSS3 and JavaScript, building a modern, usable web application with animations, notifications, real time communication and much more got a lot easier.

Introducing the PageVisibility API

One of the most overlooked APIs that we got is the PageVisibility API that lets you react to visibility changes of your website, e.g. when the user switches the tab. Sure, it’s not the first thing that comes to mind when you think of web development these days, but it allows for some nice features:

  • stop animations when the page is not visible
  • stop video playback when the user switches the tab
  • stop playing sound when the page is not visible (you all know that annoying “Damn, which tab is playing that sound”-problem)
  • give the user a digest of the latest changes when he comes back to the page
  • stop polling to save some precious CPU cycles
  • pause/resume a game
  • mark the user as away from keyboard (or tab) in a chat application
  • use Desktop Notifications to display important messages while the user is away (please only do that with user’s consent)
  • only track the visit if the site is visible (not prerendered)
  • a lot more

Demo

Check out the demo to see it in action and to get a hint of what’s possible.

Using it

Using the API is simple:

var onVisibilityChange = function(onVisible, onInvisible, onPrerender) {
  var bindVisibilityChange = function(eventName, propertyName) {
    document.addEventListener(eventName, function(event) {
      switch (document[propertyName]) {
        case 'visible':
          if (typeof onVisible === 'function') onVisible(event);
          break;
        case 'hidden':
          if (typeof onInvisible === 'function') onInvisible(event);
          break;
        case 'prerender':
          if (typeof onPrerender === 'function') onPrerender(event);
          break;
      }
    });
  };

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

onVisibilityChange(wakeUp, goToSleep);

This little snippet checks if the browser supports the API, binds the event handler when the visibility changes and calls the connect or disconnect functions with the event argument, based on the visibility of the page.

Browser support and possible fallbacks

Most browsers support the API nowadays, current Firefox versions even without the prefix. Only desktop and mobile Safari and the Android stock browser have to catch up.

When the browser supports the PageVisibility API it populates two properties in the document object. hidden, a boolean determining if the page is visble or not, and visibilityState which is a string that can be one of these:

  • prerender when the page is prerendered but not visible yet
  • hidden when the page is hidden
  • visible when the page is visible

As for fallbacks, don’t be misguided by the pageshow & pagehide events. Their names sound like the right tool, but in fact they’re just load & unload with special cache semantics.

Luckily there are some polyfills that emulate the behaviour by using focusin, focusout, focus & blur events.

‘Production’ example

With this tool in your belt you now have even more ways to explore the interactivity of web apps. This allows to save energy and spare battery life, for which especially your mobile users will be thankful. In spotify-remote we use this technique to recognize when the user does not see the remote interface and disconnect from the server. With no connections the server stops polling and the interface basically pauses, saving resources on both the client and server.

Further resources

The fine folks of html5rocks have also published an information filled article about this API. Also be sure to check the spec.

Now go ahead and build awesome stuff & let us know what you think and share your ideas on how to use this API.

Talk

I recently gave a talk about that topic at BerlinJS: You can find the slides here

I love building web applications!

I am a flexible software developer. I work closely with my clients to help them realize their ideas & projects, from beginning to end, using a wide range of technologies.

Robin Mehner

Robin Mehner has over a decade of experience building & shipping software, using Ruby, JavaScript, Node.js, SQL & NoSQL databases, PHP, Go and many more technologies. He also loves to organize community events.

This is what we do for fun!