Create a gist now

Instantly share code, notes, and snippets.

Embed
Visibility API
// assumes an ES5 compliant browser for Array.prototype.forEach
// and Object.defineProperty
// and a sane browser for Element.prototype.addEventListener
(function () {
"use strict";
//no need to shim if it's already there
if ( 'hidden' in document && 'onvisibilitychange' in document ) {
return;
}
// no-op on legacy browsers.
if ( !document.addEventListener ||
!Array.prototype.forEach ||
!Object.defineProperty ||
!window.addEventListener
) {
return;
}
//check to see if there's a native implementation
var prefixes = [ 'webkit', 'moz', 'o', 'ms' ], native = '', hiddenName = 'hidden';
prefixes.forEach(function ( prefix ) {
if ( (prefix + 'Hidden') in document ) {
native = prefix;
hiddenName = prefix + 'Hidden';
}
});
//will be called whenever the visibility has been changed
var visibilityChange = function () {
document[hiddenName] = hidden;
document.visibilityState = document.hidden ? 'hidden' : 'visible';
//create the visibilitychange event
var evt = document.createEvent( 'Event' );
evt.initEvent( 'visibilitychange', true, true );
//you're FIRED!
document.dispatchEvent( evt );
//check for document.onvisibilitychange and call it if it exists
var vischange = 'onvisibilitychange'; //it's really long to write...
if ( document[vischange] && document[vischange].call ) {
document[ vischange ].call( document, evt );
}
}, hidden = false;
//add the event listeners to tap into native functionality
if ( native ) {
document.addEventListener( native + 'visibilitychange', visibilityChange );
} else {
//the window.focus and window.blur events are, well, close enough
window.addEventListener( 'focus', function () {
hidden = false;
visibilityChange();
});
window.addEventListener( 'blur', function () {
hidden = true;
visibilityChange();
});
}
//add document.hidden, document.visibilityState
Object.defineProperty( document, 'hidden', {
value: hidden,
configurable: true
});
Object.defineProperty( document, 'visibilityState', {
value: document.hidden ? 'hidden' : 'visible',
configurable: true
});
}());
@domenic

This comment has been minimized.

Show comment
Hide comment
@domenic

domenic Jan 25, 2012

The onvisibilitychange addition wasn't useless; it made it non-enumerable and null instead of undefined, like all other document.onwhatever properties.

domenic commented Jan 25, 2012

The onvisibilitychange addition wasn't useless; it made it non-enumerable and null instead of undefined, like all other document.onwhatever properties.

@Raynos

This comment has been minimized.

Show comment
Hide comment
@Raynos

Raynos Jan 25, 2012

@domenicdenicola document.onclick === undefined; // true in Firefox.

Owner

Raynos commented Jan 25, 2012

@domenicdenicola document.onclick === undefined; // true in Firefox.

@domenic

This comment has been minimized.

Show comment
Hide comment
@domenic

domenic Jan 25, 2012

Not in Firefox 9... I'd screenshot my console window if I was a bit less lazy.

domenic commented Jan 25, 2012

Not in Firefox 9... I'd screenshot my console window if I was a bit less lazy.

@Zirak

This comment has been minimized.

Show comment
Hide comment
@Zirak

Zirak Jan 25, 2012

@Raynos defineProperty defines the property, it's an "I exist, acknowledge me". That way, things like the test in the beginning of the script, 'onvisibilitychange' in document, will give the correct results.

Zirak commented Jan 25, 2012

@Raynos defineProperty defines the property, it's an "I exist, acknowledge me". That way, things like the test in the beginning of the script, 'onvisibilitychange' in document, will give the correct results.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment