| /*! |
| * visibly - v0.6 Aug 2011 - Page Visibility API Polyfill |
| * http://github.com/addyosmani |
| * Copyright (c) 2011 Addy Osmani |
| * Dual licensed under the MIT and GPL licenses. |
| * |
| * Methods supported: |
| * visibly.onVisible(callback) |
| * visibly.onHidden(callback) |
| * visibly.hidden() |
| * visibly.visibilityState() |
| * visibly.visibilitychange(callback(state)); |
| */ |
| |
| ;(function () { |
| |
| window.visibly = { |
| q: document, |
| p: undefined, |
| prefixes: ['webkit', 'ms','o','moz','khtml'], |
| props: ['VisibilityState', 'visibilitychange', 'Hidden'], |
| m: ['focus', 'blur'], |
| visibleCallbacks: [], |
| hiddenCallbacks: [], |
| genericCallbacks:[], |
| _callbacks: [], |
| cachedPrefix:"", |
| fn:null, |
| |
| onVisible: function (_callback) { |
| if(typeof _callback == 'function' ){ |
| this.visibleCallbacks.push(_callback); |
| } |
| }, |
| onHidden: function (_callback) { |
| if(typeof _callback == 'function' ){ |
| this.hiddenCallbacks.push(_callback); |
| } |
| }, |
| getPrefix:function(){ |
| if(!this.cachedPrefix){ |
| for(var l=0;b=this.prefixes[l++];){ |
| if(b + this.props[2] in this.q){ |
| this.cachedPrefix = b; |
| return this.cachedPrefix; |
| } |
| } |
| } |
| }, |
| |
| visibilityState:function(){ |
| return this._getProp(0); |
| }, |
| hidden:function(){ |
| return this._getProp(2); |
| }, |
| visibilitychange:function(fn){ |
| if(typeof fn == 'function' ){ |
| this.genericCallbacks.push(fn); |
| } |
| |
| var n = this.genericCallbacks.length; |
| if(n){ |
| if(this.cachedPrefix){ |
| while(n--){ |
| this.genericCallbacks[n].call(this, this.visibilityState()); |
| } |
| }else{ |
| while(n--){ |
| this.genericCallbacks[n].call(this, arguments[0]); |
| } |
| } |
| } |
| |
| }, |
| isSupported: function (index) { |
| return ((this.cachedPrefix + this.props[2]) in this.q); |
| }, |
| _getProp:function(index){ |
| return this.q[this.cachedPrefix + this.props[index]]; |
| }, |
| _execute: function (index) { |
| if (index) { |
| this._callbacks = (index == 1) ? this.visibleCallbacks : this.hiddenCallbacks; |
| var n = this._callbacks.length; |
| while(n--){ |
| this._callbacks[n](); |
| } |
| } |
| }, |
| _visible: function () { |
| window.visibly._execute(1); |
| window.visibly.visibilitychange.call(window.visibly, 'visible'); |
| }, |
| _hidden: function () { |
| window.visibly._execute(2); |
| window.visibly.visibilitychange.call(window.visibly, 'hidden'); |
| }, |
| _nativeSwitch: function () { |
| this[this._getProp(2) ? '_hidden' : '_visible'](); |
| }, |
| _listen: function () { |
| try { /*if no native page visibility support found..*/ |
| if (!(this.isSupported())) { |
| if (this.q.addEventListener) { /*for browsers without focusin/out support eg. firefox, opera use focus/blur*/ |
| window.addEventListener(this.m[0], this._visible, 1); |
| window.addEventListener(this.m[1], this._hidden, 1); |
| } else { /*IE <10s most reliable focus events are onfocusin/onfocusout*/ |
| if (this.q.attachEvent) { |
| this.q.attachEvent('onfocusin', this._visible); |
| this.q.attachEvent('onfocusout', this._hidden); |
| } |
| } |
| } else { /*switch support based on prefix detected earlier*/ |
| this.q.addEventListener(this.cachedPrefix + this.props[1], function () { |
| window.visibly._nativeSwitch.apply(window.visibly, arguments); |
| }, 1); |
| } |
| } catch (e) {} |
| }, |
| init: function () { |
| this.getPrefix(); |
| this._listen(); |
| } |
| }; |
| |
| this.visibly.init(); |
| })(); |