window visibility test

using Page_Visibility_API and requestAnimationFrame fallback.

by Laurens Maneschijn

HTML

<pre>
Experiment to test if we can check if the current window is visible.
Uses the <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/API/Page_Visibility_API">Page_Visibility_API</a>, or <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame">requestAnimationFrame</a> as fallback.

Try alt-tabbing or ctrl-tabbing to test results.

Tip: Log also written to console, which you can open in another window to monitor state if this window is not visible.
</pre>
Also see: 
<a target="_blank" href="https://stackoverflow.com/questions/1060008/is-there-a-way-to-detect-if-a-browser-window-is-not-currently-active/1060034#1060034">1</a><br>

<a target="_blank" href="https://jsfiddle.net/ElMoonLite/29npzx9v/">open in new window</a> 
(ctrl-click to open initially invisible)<br>

<hr>

<div>visible now: <span id="visiblenow"></span></div>
Log: (newest events on top)<br>
<div id="log"></div>

CSS

#visiblenow {
  display:inline-block;
  margin:2px;
  padding:2px;
  border:1px solid #888;
}
#log, .logline {
  display:block;
  margin:2px;
  padding:2px;
  border:1px solid #888;
}

body{
  transition: outline 1s ease 0s;
}
body.windowvisible {outline:2px solid #0f0;}
body.windowhidden  {outline:2px solid #f00;}

JavaScript

(function($){
		var force_using_requestAnimationFrame_fallback = true;
		var is_page_visible_now = null;	// null: unknown untill proven otherwise.

		// update display current is_page_visible_now value:
		setInterval(function(){
      $('#visiblenow').html( {null:'?',false:'false',true:'true'}[is_page_visible_now] );
    }, 100);
    
		function triggerEvent(visiblestate){
      log('event visible state: ' + (visiblestate ? 'true':'false') );
//    window.title = (visiblestate ? 'visible':'hidden');
//    window.parent.title = (visiblestate ? 'visible':'hidden');
//	  document.body.style.outline = (visiblestate ? '1px solid #0f0':'1px solid #f00');
			// NB: you should never see hidden variant.
			$('body').removeClass('windowhidden windowvisible').addClass(visiblestate ? 'windowvisible':'windowhidden');
    }
    function timestamp(){
      return (new Date()).toISOString().replace('T',' ').replace('Z','');
    }
    function log(s){
    	if(console && console.log){
      	console.log.apply(this, [].slice.apply(arguments) );
      }
    	$('#log').prepend( $('<pre class="logline">').text(timestamp() + ': ' + s) );
    }


		function observePageVisibility () {
				if(force_using_requestAnimationFrame_fallback){
					observePageVisibility_requestAnimationFrame_fallback();
          log('Forced using requestAnimationFrame fallback for Page Visibility API.');
          return;
        }
        
        if( setupDocumentHiddenChangeEventListener() ){
          log('Using onchange + document.hidden (or moz/ms/webkit equivalent) for Page Visibility API.');
				} else if (window.requestAnimationFrame) {
					// Support for Chrome 10+, Firefox 4+, IE10+, Opera 15+, Safari/WebKit 6+
					observePageVisibility_requestAnimationFrame_fallback();
          log('Using requestAnimationFrame fallback for Page Visibility API.');
				} else {
					log('No support for the Page Visibility API.');
				}
		}

		function setupDocumentHiddenChangeEventListener() {
				if (!...