summaryrefslogtreecommitdiff
path: root/www/wiki/resources/src/mediawiki/mediawiki.visibleTimeout.js
diff options
context:
space:
mode:
Diffstat (limited to 'www/wiki/resources/src/mediawiki/mediawiki.visibleTimeout.js')
-rw-r--r--www/wiki/resources/src/mediawiki/mediawiki.visibleTimeout.js114
1 files changed, 114 insertions, 0 deletions
diff --git a/www/wiki/resources/src/mediawiki/mediawiki.visibleTimeout.js b/www/wiki/resources/src/mediawiki/mediawiki.visibleTimeout.js
new file mode 100644
index 00000000..e2bbd683
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/mediawiki.visibleTimeout.js
@@ -0,0 +1,114 @@
+( function ( mw, document ) {
+ var hidden, visibilityChange,
+ nextVisibleTimeoutId = 0,
+ activeTimeouts = {},
+ init = function ( overrideDoc ) {
+ if ( overrideDoc !== undefined ) {
+ document = overrideDoc;
+ }
+
+ if ( document.hidden !== undefined ) {
+ hidden = 'hidden';
+ visibilityChange = 'visibilitychange';
+ } else if ( document.mozHidden !== undefined ) {
+ hidden = 'mozHidden';
+ visibilityChange = 'mozvisibilitychange';
+ } else if ( document.msHidden !== undefined ) {
+ hidden = 'msHidden';
+ visibilityChange = 'msvisibilitychange';
+ } else if ( document.webkitHidden !== undefined ) {
+ hidden = 'webkitHidden';
+ visibilityChange = 'webkitvisibilitychange';
+ }
+ };
+
+ init();
+
+ /**
+ * @class mw.visibleTimeout
+ * @singleton
+ */
+ module.exports = {
+ /**
+ * Generally similar to setTimeout, but turns itself on/off on page
+ * visibility changes. The passed function fires after the page has been
+ * cumulatively visible for the specified number of ms.
+ *
+ * @param {Function} fn The action to execute after visible timeout has expired.
+ * @param {number} delay The number of ms the page should be visible before
+ * calling fn.
+ * @return {number} A positive integer value which identifies the timer. This
+ * value can be passed to clearVisibleTimeout() to cancel the timeout.
+ */
+ set: function ( fn, delay ) {
+ var handleVisibilityChange,
+ timeoutId = null,
+ visibleTimeoutId = nextVisibleTimeoutId++,
+ lastStartedAt = mw.now(),
+ clearVisibleTimeout = function () {
+ if ( timeoutId !== null ) {
+ clearTimeout( timeoutId );
+ timeoutId = null;
+ }
+ delete activeTimeouts[ visibleTimeoutId ];
+ if ( hidden !== undefined ) {
+ document.removeEventListener( visibilityChange, handleVisibilityChange, false );
+ }
+ },
+ onComplete = function () {
+ clearVisibleTimeout();
+ fn();
+ };
+
+ handleVisibilityChange = function () {
+ var now = mw.now();
+
+ if ( document[ hidden ] ) {
+ // pause timeout if running
+ if ( timeoutId !== null ) {
+ delay = Math.max( 0, delay - Math.max( 0, now - lastStartedAt ) );
+ if ( delay === 0 ) {
+ onComplete();
+ } else {
+ clearTimeout( timeoutId );
+ timeoutId = null;
+ }
+ }
+ } else {
+ // resume timeout if not running
+ if ( timeoutId === null ) {
+ lastStartedAt = now;
+ timeoutId = setTimeout( onComplete, delay );
+ }
+ }
+ };
+
+ activeTimeouts[ visibleTimeoutId ] = clearVisibleTimeout;
+ if ( hidden !== undefined ) {
+ document.addEventListener( visibilityChange, handleVisibilityChange, false );
+ }
+ handleVisibilityChange();
+
+ return visibleTimeoutId;
+ },
+
+ /**
+ * Cancel a visible timeout previously established by calling set.
+ * Passing an invalid ID silently does nothing.
+ *
+ * @param {number} visibleTimeoutId The identifier of the visible
+ * timeout you want to cancel. This ID was returned by the
+ * corresponding call to set().
+ */
+ clear: function ( visibleTimeoutId ) {
+ if ( activeTimeouts.hasOwnProperty( visibleTimeoutId ) ) {
+ activeTimeouts[ visibleTimeoutId ]();
+ }
+ }
+ };
+
+ if ( window.QUnit ) {
+ module.exports.setDocument = init;
+ }
+
+}( mediaWiki, document ) );