Last Updated: February 25, 2016
·
952
· pete-otaqui

Browser Visibility API Polyfill

/**
Visibility API polyfill-of-sorts

    This is wrapped as an AMD module for convenience, and assumes
    that you are using a 'pubusb' library of some kind.  That's
    all fairly easy to remove (amd and the dependency).
*/
define(['pubsub'], function (pubsub) {
    'use strict';

    var current_state;

    var hidden = 'hidden';

    // Standards:
    if (hidden in document) {
        document.addEventListener('visibilitychange', onVisibilityChange);
    } else if ('mozHidden' in document) {
        hidden = 'mozHidden';
        document.addEventListener('mozvisibilitychange', onVisibilityChange);
    } else if ('webkitHidden' in document) {
        hidden = 'webkitHidden';
        document.addEventListener('webkitvisibilitychange', onVisibilityChange);
    } else if ('msHidden' in document) {
        hidden = 'msHidden';
        document.addEventListener('msvisibilitychange', onVisibilityChange);
    }

    /* Generalised "Visibility API" polyfill */
    function onVisibilityChange (evt) {
        var state = 'unknown',
            v = 'visible', h = 'hidden',
            evtMap = {
                focus:v,
                focusin:v,
                pageshow:v,
                blur:h,
                focusout:h,
                pagehide:h
            };

        evt = evt || window.event;
        if (evt.type in evtMap) {
            state = evtMap[evt.type];
        } else {
            state = document[hidden] ? h : v;
        }
        // (nb - might be triggered twice, so we track "current_state")
        if (state !== current_state) {
            current_state = state;
            // this is the bit you would change if you aren't using
            // amd or a pubsub library
            pubsub.publish('visibility-change', [state]);
        }
    }
    // let's do this too in for other browsers
    window.addEventListener('pageshow', onVisibilityChange, false);
    window.addEventListener('pagehide', onVisibilityChange, false);
});