Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Using the Page Visibility API

DZone's Guide to

Using the Page Visibility API

· Web Dev Zone
Free Resource

Learn how to build modern digital experience apps with Crafter CMS. Download this eBook now. Brought to you in partnership with Crafter Software

A few weeks ago at MAX I had the pleasure of giving half a presentation with Greg Wilson on "Cutting Edge HTML". One of the APIs I demonstrated to the audience was the Page Visibility API. As you can probably guess, this is a basic API to let you know if your page is visible to the end user. It doesn't have complete support yet, but it is (yet again) another great example of something you can add to your code with relative ease to enhance the experience for your end users.

So how well is it supported? The embed below comes from the excellent CanIUse and will be up to date no matter when you are reading this blog entry:

I think you could summarize this as a "good desktop support, poor mobile". That being said, the API is simple to use and doesn't cause any harm to your code if end user doesn't support it. Let's consider a simple example.

In the script below, I've got an AJAX call being run every (approximately) 2 seconds to fetch a news feed from the server.

<!DOCTYPE html>
<html>
    <body>

    <div id="newswell"></div>

    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>

    <script>
    var newsDiv;
                
    function getData() {

        $.ajax({url:"news.json"}).done(function(data) {
            newsDiv.innerHTML += "<p><b>Posted at " + new Date() + "<br/>" + data.message;
            //call it again in 2 seconds
            window.setTimeout(getData, 2000);
        }).fail(function(xhr,status,e) {
            console.dir(e);
        });
    }
        
    $(document).ready(function() {
        newsDiv = document.querySelector("#newswell");
            
        getData();
        
    });
        
    </script>
    </body>
</html>

I assume the code above is trivial enough to not really need any explanation, but if I'm wrong, just let me know in the comments. Now let's look at an updated version making use of the API.

<!DOCTYPE html>
<html>
    <body>

    <div id="newswell"></div>

    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>

    <script>
    var newsDiv;
    var active = true;
        
    function isVisible() {
        if("webkitHidden" in document) return !document.webkitHidden;
        if("mozHidden" in document) return !document.mozHidden;
        if("hidden" in document) return !document.hidden;  
        //worse case, just return true
        return true;
    }
        
    function getData() {

        $.ajax({url:"news.json"}).done(function(data) {
            newsDiv.innerHTML += "<p><b>Posted at " + new Date() + "<br/>" + data.message;
            //call it again in 2 seconds
            if(isVisible()) window.setTimeout(getData, 2000);
            else active = false;
        }).fail(function(xhr,status,e) {
            console.dir(e);
        });
    }
        
    $(document).ready(function() {
        newsDiv = document.querySelector("#newswell");
    
        $(document).bind("visibilitychange webkitvisibilitychange mozvisibilitychange",function(e) {
            console.log("VS CHANGE");
            console.log(isVisible());
            if(isVisible() && !active) {
                active = true;
                getData();
            }
        });
        
        getData();
        
    });
        
    </script>
    </body>
</html>

Let's tackle this bit by bit. First, note the use of the event handler in the document.ready block. The Page Visibility events are still prefixed so I built in support for the unprefixed, Chrome, and Mozilla versions. (Remember that IE supports this so in theory, I could add in the IE prefix too if necessary. I'd love it if someone could check to see if IE has this prefixed or not.)

Speaking of prefixes, I built a function, isVisible, that wraps the checks to the document.hidden property. This is the main way we can tell if our document is visible.

What about the active variable? Since we're dealing with AJAX calls and asynchronous crap, we've got a delicate situation. We may, or may not, have an ongoing AJAX call being fired when visibility changes. If we've gone from hidden to visible, but we had an existing AJAX call already, we don't want to fire one now. If we do have one active, the callback handler will handle scheduling the next call. In this way we ensure that we don't double up our AJAX calls or forget to start the process again.

Be sure to check the specification I linked to above. They have an interesting demo as well. Instead of stopping their AJAX calls they simply slow them down. I can see both ways of handling this being effective.

You can demo this here: http://raymondcamden.com/demos/2013/may/28/crap.html. If you want, you can also demo the pre-Page Visibility version here: http://raymondcamden.com/demos/2013/may/28/pre_crap.html

Pardon the file names. I'm not sure what I was thinking there.

There is only one real drawback to this API that I can think of. According to the specification, the browser should report as hidden when minimized. In my testing, this was not true. In fact, it doesn't report as hidden if you put another application in front. It only reported hidden when I switched to another tab. Again though, I figure this is better than nothing and the additional code (10 lines?) is trivial enough to make it worth your time. EDIT: FYI, Firefox does notice it when you minimize the application. Way to go, Firefox.

Later today (most likely tonight, I've got a big presentation this afternoon), I'm going to show another example of this using Edge Animate.



Crafter is a modern CMS platform for building modern websites and content-rich digital experiences. Download this eBook now. Brought to you in partnership with Crafter Software.

Topics:

Published at DZone with permission of Raymond Camden, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

THE DZONE NEWSLETTER

Dev Resources & Solutions Straight to Your Inbox

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.

X

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}