1 ( function ( mw
, document
) {
2 var hidden
, visibilityChange
,
3 nextVisibleTimeoutId
= 0,
5 init = function ( overrideDoc
) {
6 if ( overrideDoc
!== undefined ) {
7 document
= overrideDoc
;
10 if ( document
.hidden
!== undefined ) {
12 visibilityChange
= 'visibilitychange';
13 } else if ( document
.mozHidden
!== undefined ) {
15 visibilityChange
= 'mozvisibilitychange';
16 } else if ( document
.msHidden
!== undefined ) {
18 visibilityChange
= 'msvisibilitychange';
19 } else if ( document
.webkitHidden
!== undefined ) {
20 hidden
= 'webkitHidden';
21 visibilityChange
= 'webkitvisibilitychange';
28 * @class mw.visibleTimeout
33 * Generally similar to setTimeout, but turns itself on/off on page
34 * visibility changes. The passed function fires after the page has been
35 * cumulatively visible for the specified number of ms.
37 * @param {Function} fn The action to execute after visible timeout has expired.
38 * @param {number} delay The number of ms the page should be visible before
40 * @return {number} A positive integer value which identifies the timer. This
41 * value can be passed to clearVisibleTimeout() to cancel the timeout.
43 set: function ( fn
, delay
) {
44 var handleVisibilityChange
,
46 visibleTimeoutId
= nextVisibleTimeoutId
++,
47 lastStartedAt
= mw
.now(),
48 clearVisibleTimeout = function () {
49 if ( timeoutId
!== null ) {
50 clearTimeout( timeoutId
);
53 delete activeTimeouts
[ visibleTimeoutId
];
54 if ( hidden
!== undefined ) {
55 document
.removeEventListener( visibilityChange
, handleVisibilityChange
, false );
58 onComplete = function () {
59 clearVisibleTimeout();
63 handleVisibilityChange = function () {
66 if ( document
[ hidden
] ) {
67 // pause timeout if running
68 if ( timeoutId
!== null ) {
69 delay
= Math
.max( 0, delay
- Math
.max( 0, now
- lastStartedAt
) );
73 clearTimeout( timeoutId
);
78 // resume timeout if not running
79 if ( timeoutId
=== null ) {
81 timeoutId
= setTimeout( onComplete
, delay
);
86 activeTimeouts
[ visibleTimeoutId
] = clearVisibleTimeout
;
87 if ( hidden
!== undefined ) {
88 document
.addEventListener( visibilityChange
, handleVisibilityChange
, false );
90 handleVisibilityChange();
92 return visibleTimeoutId
;
96 * Cancel a visible timeout previously established by calling set.
97 * Passing an invalid ID silently does nothing.
99 * @param {number} visibleTimeoutId The identifier of the visible
100 * timeout you want to cancel. This ID was returned by the
101 * corresponding call to set().
103 clear: function ( visibleTimeoutId
) {
104 if ( Object
.prototype.hasOwnProperty
.call( activeTimeouts
, visibleTimeoutId
) ) {
105 activeTimeouts
[ visibleTimeoutId
]();
110 if ( window
.QUnit
) {
111 module
.exports
.setDocument
= init
;
114 }( mediaWiki
, document
) );