mirror of
https://github.com/ai/visibilityjs.git
synced 2026-04-19 03:00:02 -04:00
200 lines
6.5 KiB
JavaScript
200 lines
6.5 KiB
JavaScript
/*
|
||
* Copyright 2012 Andrey “A.I.” Sitnik <andrey@sitnik.ru>,
|
||
* sponsored by Evil Martians.
|
||
*
|
||
* This program is free software: you can redistribute it and/or modify
|
||
* it under the terms of the GNU Lesser General Public License as published by
|
||
* the Free Software Foundation, either version 3 of the License, or
|
||
* (at your option) any later version.
|
||
*
|
||
* This program is distributed in the hope that it will be useful,
|
||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
* GNU Lesser General Public License for more details.
|
||
*
|
||
* You should have received a copy of the GNU Lesser General Public License
|
||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||
*/
|
||
|
||
;(function () {
|
||
"use strict";
|
||
|
||
var defined = function(variable) {
|
||
return ('undefined' != typeof(variable));
|
||
};
|
||
|
||
var timers = {
|
||
|
||
// Run callback every `interval` milliseconds if page is visible and
|
||
// every `hiddenInterval` milliseconds if page is hidden.
|
||
//
|
||
// Visibility.every(60 * 1000, 5 * 60 * 1000, function () {
|
||
// checkNewMails();
|
||
// });
|
||
//
|
||
// You can skip `hiddenInterval` and callback will be called only if
|
||
// page is visible.
|
||
//
|
||
// Visibility.every(1000, function () {
|
||
// updateCountdown();
|
||
// });
|
||
//
|
||
// It is analog of `setInterval(callback, interval)` but use visibility
|
||
// state.
|
||
//
|
||
// It return timer ID, that you can use in `Visibility.stop(id)` to stop
|
||
// timer (`clearInterval` analog).
|
||
// Warning: timer ID is different from interval ID from `setInterval`,
|
||
// so don’t use it in `clearInterval`.
|
||
//
|
||
// On change state from hidden to visible timers will be execute.
|
||
//
|
||
// If you include jQuery Chrono plugin before Visibility.js, you could
|
||
// use Chrono’s syntax sugar in interval arguments:
|
||
//
|
||
// Visibility.every('second', function () {
|
||
// updateCountdown();
|
||
// });
|
||
// Visibility.every('1 minute', '5 minutes', function () {
|
||
// checkNewMails();
|
||
// });
|
||
every: function (interval, hiddenInterval, callback) {
|
||
this._initTimers();
|
||
|
||
if ( !defined(callback) ) {
|
||
callback = hiddenInterval;
|
||
hiddenInterval = null;
|
||
}
|
||
this._lastTimer += 1;
|
||
var number = this._lastTimer;
|
||
this._timers[number] = ({
|
||
interval: interval,
|
||
hiddenInterval: hiddenInterval,
|
||
callback: callback
|
||
});
|
||
this._runTimer(number, false);
|
||
|
||
if ( this.isSupported() ) {
|
||
this._setListener();
|
||
}
|
||
return number;
|
||
},
|
||
|
||
// Stop timer from `every` method by it ID (`every` method return it).
|
||
//
|
||
// slideshow = Visibility.every(5 * 1000, function () {
|
||
// changeSlide();
|
||
// });
|
||
// $('.stopSlideshow').click(function () {
|
||
// Visibility.stop(slideshow);
|
||
// });
|
||
stop: function(id) {
|
||
var timer = this._timers[id]
|
||
if ( !defined(timer) ) {
|
||
return false;
|
||
}
|
||
this._stopTimer(id);
|
||
delete this._timers[id];
|
||
return timer;
|
||
},
|
||
|
||
// Last timer number.
|
||
_lastTimer: -1,
|
||
|
||
// Callbacks and intervals added by `every` method.
|
||
_timers: { },
|
||
|
||
// Is setInterval method detected and listener is binded.
|
||
_timersInitialized: false,
|
||
|
||
// Initialize variables on page loading.
|
||
_initTimers: function () {
|
||
if ( this._timersInitialized ) {
|
||
return;
|
||
}
|
||
this._timersInitialized = true;
|
||
|
||
if ( defined(window.jQuery) && defined(jQuery.every) ) {
|
||
this._setInterval = this._chronoInterval;
|
||
} else {
|
||
this._setInterval = this._originalInterval;
|
||
}
|
||
this.change(function () {
|
||
Visibility._timersStopRun()
|
||
});
|
||
},
|
||
|
||
// Set interval directly by `setInterval` function without any syntax
|
||
// sugar.
|
||
_originalInterval: function (callback, interval) {
|
||
return setInterval(callback, interval);
|
||
},
|
||
|
||
// Set interval by jQuery Chrono plugin. Add syntax sugar to `interval`
|
||
// and `hiddenInterval` arguments, such as "1 second" and others.
|
||
//
|
||
// It will be automatically set to `_setInterval` on loading if
|
||
// you include jQuery Chrono plugin before Visibility.js.
|
||
_chronoInterval: function (callback, internal) {
|
||
return jQuery.every(internal, callback);
|
||
},
|
||
|
||
// Set interval by `setInterval`. Allow to change function for tests or
|
||
// syntax sugar in `interval` arguments.
|
||
//
|
||
// Function will be automatically set in `_init` method (which will be
|
||
// call on script loading). So you must include jQuery Chrono plugin
|
||
// before Visibility.js.
|
||
_setInterval: null,
|
||
|
||
// Try to run timer from every method by it’s ID. It will be use
|
||
// `interval` or `hiddenInterval` depending on visibility state.
|
||
// If page is hidden and `hiddenInterval` is null,
|
||
// it will not run timer.
|
||
//
|
||
// Argument `now` say, that timers must be execute now too.
|
||
_runTimer: function (id, now) {
|
||
var interval,
|
||
timer = this._timers[id];
|
||
if ( this.hidden() ) {
|
||
if ( null === timer.hiddenInterval ) {
|
||
return;
|
||
}
|
||
interval = timer.hiddenInterval;
|
||
} else {
|
||
interval = timer.interval;
|
||
}
|
||
if ( now ) {
|
||
timer.callback.call(window);
|
||
}
|
||
timer.id = this._setInterval(timer.callback, interval);
|
||
},
|
||
|
||
// Stop timer from `every` method by it’s ID.
|
||
_stopTimer: function (id) {
|
||
var timer = this._timers[id];
|
||
clearInterval(timer.id);
|
||
delete timer.id;
|
||
},
|
||
|
||
// Listener for `visibilitychange` event.
|
||
_timersStopRun: function (event) {
|
||
var isHidden = this.hidden(),
|
||
hiddenBefore = this._hiddenBefore;
|
||
|
||
if ( (isHidden && !hiddenBefore) || (!isHidden && hiddenBefore) ) {
|
||
for ( var i in this._timers ) {
|
||
this._stopTimer(i);
|
||
this._runTimer(i, !isHidden);
|
||
}
|
||
}
|
||
}
|
||
|
||
};
|
||
|
||
for ( var prop in timers ) {
|
||
Visibility[prop] = timers[prop];
|
||
}
|
||
|
||
})();
|