Using PC Hardware more efficiently in HTML5: New Web Performance APIs, Part 2

Web developers need API’s to efficiently take advantage of modern PC hardware through
HTML5, improving the performance of Web applications, the power efficiency of the
Web platform, and the resulting customer experience. The second
IE10 Platform Preview supports emerging API’s from the
W3C Web Performance Working Group which enable developers to make the
most of the underlying hardware and use battery power more efficiently. This post
details how to use
Page Visibility, one of the emerging API’s, for better performance and power
efficiency.


Page Visibility: adjust work depending on if the user is looking

Knowing whether a page is visible makes it possible for a developer to make better
decisions about what the page does, especially around power usage and background
tasks. Take a look at the Page Visibility
Test Drive to see how a Web application can be aware of whether the page
is visible or not to the user.

Screen shot of Page Visibility API test drive demo

The Page Visibility API is now available through vendor prefixed implementations in IE10 and Chrome 13.

The developer can adjust or scale back what work the page does based on visibility.
For example, if a Web based email client is visible, it may check the server for
new mail every few seconds. When hidden it might scale checking email to every few
minutes. Other examples include a puzzle application that can be paused when the
user no longer has the game visible or showing ads only if the page is visible to
the user.

The Page Visibility specification enables developers to determine the current visibility
of a document and be notified of visibility changes. It consists of two properties
and an event:

  • document.hidden: A boolean that describes whether the page is visible or not.
  • document.visibilityState: An attribute that returns the detailed page visibility
    state, e.g., PAGE_VISIBLE, PAGE_PREVIEW, etc.
  • visibilitychange: An event that gets fired any time the visibility state of the
    page changes.

IE10 has prefixed these attributes and event with the ‘ms’ vendor prefix.

With this interface, Web applications may choose to alter behavior based on whether
they are visible to the user or not. For example, the following JavaScript shows
a theoretical Web based email client checking for new emails every second without
knowledge of the Page Visibility:

<!DOCTYPE html>

<html>

<head>

<title>Typical setInterval Pattern</title>

<script>

var timer = 0;

var PERIOD = 1000; // check for mail every second

 

function onLoad() {

timer = setInterval(checkEmail, PERIOD);

}

 

function checkEmail() {

debugMessage("Checking email at " + new Date().toTimeString());

}

 

function debugMessage(s) {

var p = document.createElement("p");

p.appendChild(document.createTextNode(s));

document.body.appendChild(p);

}

</script>

</head>

<body onload="onLoad()">

</body>

</html>

Using Page Visibility, the same page can throttle back how often it checks email
when the page is not visible:

<!DOCTYPE html>

<html>

<head>

<title>Visibility API Example</title>

<script>

var timer = 0;

var PERIOD_VISIBLE = 1000; // 1 second

var PERIOD_NOT_VISIBLE = 10000; // 10 seconds

var vendorHidden, vendorVisibilitychange;

 

function detectHiddenFeature() {

// draft standard implementation

if (typeof document.hidden != "undefined") {

vendorHidden = "hidden";

vendorVisibilitychange = "visibilitychange";

return true;

}

 

// IE10 prefixed implementation

if (typeof document.msHidden != "undefined") {

vendorHidden = "msHidden";

vendorVisibilitychange = "msvisibilitychange";

return true;

}

 

// Chrome 13 prefixed implementation

if (typeof document.webkitHidden != "undefined") {

vendorHidden = "webkitHidden";

vendorVisibilitychange = "webkitvisibilitychange";

return true;

}

 

// feature is not supported

return false;

}

 

function onLoad() {

// if the document.hidden feature is supported, vary interval based on visibility.

// otherwise, just use setInterval with a fixed time.

if (detectHiddenFeature()) {

timer = setInterval(checkEmail, document[vendorHidden] ? PERIOD_NOT_VISIBLE : PERIOD_VISIBLE);

document.addEventListener(vendorVisibilitychange, visibilityChanged);

}

else {

timer = setInterval(checkEmail, PERIOD_VISIBLE);

}

}

 

function checkEmail() {

debugMessage("Checking email at " + new Date().toTimeString());

}

 

function visibilityChanged() {

clearTimeout(timer);

timer = setInterval(checkEmail, document[vendorHidden] ? PERIOD_NOT_VISIBLE : PERIOD_VISIBLE);

debugMessage("Going " + (document[vendorHidden] ? "not " : "") + "visible at " + new Date().toTimeString());

}

 

function debugMessage(s) {

var p = document.createElement("p");

p.appendChild(document.createTextNode(s));

document.body.appendChild(p);

}

</script>

</head>

<body onload="onLoad()">

</body>

</html>

With the Page Visibility API, Web developers can create more power conscious Web
applications. To learn about other emerging API from the
W3C Web Performance Working Group supported in the second IE10 Platform
Preview, read my post on the requestAnimationFrame API (link).

—Jatinder Mann, Internet Explorer Program Manager

Comments

  • Anonymous
    July 08, 2011
    Hmm… if the draft changes then it might break this code even when there is a prefixed variant that works the "old" way?

  • Anonymous
    July 08, 2011
    I can't get it, if IE10 will follow the HTML5 standards, then why we need to use the "ms" vendor prefix. It will be more easier to use the same attributes and events across all the web browsers.

  • Anonymous
    July 08, 2011
    Very good idea, yet the IE10 is easily tricked to think that page is visible, while its not. Hopefuly, that would be fixed before release.

  • Anonymous
    July 08, 2011
    @Tariq: Until the draft becomes a Candidate Recommendation, it's better to assume that any implementations are vendor extensions. This is because drafts could change at any time. If they implemented a draft spec without prefixing (and then the draft changes), you would have to rely on browser-sniffing rather than feature detection to work out if you can use it.

  • Anonymous
    July 09, 2011
    IE Team .jxr(JPEGXR) Filename extension image file support!

  • Anonymous
    July 09, 2011
    Seems like I am not the only one remarking on this: lists.webkit.org/.../017537.html

  • Anonymous
    July 10, 2011
    IE team please build the very basic ability to queue downloads/download only certain number of files at a time to the IE download manager in IE10. Downloading many medium sized files is a total pain as you have to manually start every download, then pause them individually, then resume them one by one. If there is a registry setting somewhere to control maximum number of downloads at a time, please document it in a KB article.

  • Anonymous
    July 10, 2011
    @Björn I'm sorry but that argument makes no sense, the code is coded for how it currently works.  How exactly are you supposed to provide code for something that doesn't exist yet?  Of course they all work the same now, but in the future you could do them differently if things change for the non-prefxed version.

  • Anonymous
    July 10, 2011
    I create Visibility.js library to autodetect prefix and add nice syntax sugar: github.com/.../visibility.js

  • Anonymous
    July 11, 2011
    Do you guys know that PC World just posted an article that tells people not to use IE unless they have to?

  • Anonymous
    July 11, 2011
    @ Prior Semblance: Exactly! Nobody knows how the non-prefixed version might look like and behave they shouldn't provide code for it and esp. not with a higher priority than the prefixed versions.

  • Anonymous
    July 11, 2011
    The comment has been removed

  • Anonymous
    July 11, 2011
    @hdmi: people shouldn't read PC World unless they reall have to (like, if they're dumb or something).

  • Anonymous
    July 11, 2011
    The comment has been removed

  • Anonymous
    July 12, 2011
    It is frustrating to see such sloppy code formatting. //correct formatting if(condition){  //do stuff } else {  //do other stuff } your code with stuff like this is painful to read: else {

  • Anonymous
    July 12, 2011
    The comment has been removed

  • Anonymous
    July 12, 2011
    @please fix your code samples - For me, it's easiest to read when formatted like this: if (condition) {    // do things } else {    // do other things }

  • Anonymous
    July 12, 2011
    @MSFT IE Team should listen to their users - "could we please have the option for a separate search bar in IE9" The option to set the address bar and tabs on separate rows has been in place since IE9 was in Release Candidate status.

  • Anonymous
    July 12, 2011
    @please fix your code samples : everybody format their code like they want. But your way of doing it is weird. You should code in TCL, you'll be so happy with this language because you'll be forced to format your code as you like. In TCL: "incorrect" formatting = error, so for me it's a bad language.