parent
5629d15d02
commit
f5e372a70d
@ -69,6 +69,7 @@ v2.2.0 (UNRELEASED)
|
||||
- Remove unused iScroll libraries and references.
|
||||
- Remove unused jQuery.Mobile.iScrollView libraries and references.
|
||||
- Remove unused jQuery.Truncate libraries and references.
|
||||
- Avoid polling for current track and time changes. (Fixes: `#40 <https://github.com/pimusicbox/mopidy-musicbox-webclient/issues/40>`_).
|
||||
|
||||
**Fixes**
|
||||
|
||||
|
||||
@ -179,11 +179,6 @@
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
#songelapsed, #songlength {
|
||||
font-size: 10px;
|
||||
margin-top: 12px;
|
||||
}
|
||||
|
||||
/************************
|
||||
* Volume Slider
|
||||
***********************/
|
||||
@ -432,10 +427,14 @@ a {
|
||||
|
||||
.pull-right {
|
||||
float: right;
|
||||
font-size: 10px;
|
||||
margin-top: 12px;
|
||||
}
|
||||
|
||||
.pull-left {
|
||||
float: left;
|
||||
font-size: 10px;
|
||||
margin-top: 12px;
|
||||
}
|
||||
|
||||
.hidden, #allresultloader, .loader {
|
||||
|
||||
@ -297,10 +297,10 @@
|
||||
</div>
|
||||
|
||||
<div id="slidercontainer"><!-- slider for track position -->
|
||||
<span id="songelapsed" class="pull-left"> 0:00 </span>
|
||||
<span id="songlength" class="pull-right"> 0:00 </span>
|
||||
<span id="songelapsed" class="pull-left"></span>
|
||||
<span id="songlength" class="pull-right"></span>
|
||||
<label for="trackslider" disabled="disabled" class="ui-hidden-accessible">Position</label>
|
||||
<input id="trackslider" name="trackslider" data-mini="true" type="range" onchange="doSeekPos(this.value);" />
|
||||
<input id="trackslider" name="trackslider" data-mini="true" type="range" />
|
||||
</div>
|
||||
</div>
|
||||
<!-- /nowplaying -->
|
||||
@ -469,6 +469,8 @@
|
||||
<!-- /page one -->
|
||||
<script type="text/javascript" src="../mopidy/mopidy.min.js"></script>
|
||||
<script src="vendors/jquery_cookie/jquery.cookie.js"></script>
|
||||
<script src="vendors/media_progress_timer/timer.js"></script>
|
||||
<script src="js/progress_timer.js"></script>
|
||||
<script src="js/controls.js"></script>
|
||||
<script src="js/library.js"></script>
|
||||
<script src="js/functionsvars.js"></script>
|
||||
|
||||
61
mopidy_musicbox_webclient/static/js/controls.js
vendored
61
mopidy_musicbox_webclient/static/js/controls.js
vendored
@ -260,11 +260,14 @@ function setPlayState(nwplay) {
|
||||
$("#btplayNowPlaying").attr('title', 'Pause');
|
||||
$("#btplay >i").removeClass('fa-play').addClass('fa-pause');
|
||||
$("#btplay").attr('title', 'Pause');
|
||||
mopidy.playback.getTimePosition().then(processCurrentposition, console.error);
|
||||
startProgressTimer();
|
||||
} else {
|
||||
$("#btplayNowPlaying >i").removeClass('fa-pause').addClass('fa-play');
|
||||
$("#btplayNowPlaying").attr('title', 'Play');
|
||||
$("#btplay >i").removeClass('fa-pause').addClass('fa-play');
|
||||
$("#btplay").attr('title', 'Play');
|
||||
progressTimer.stop();
|
||||
}
|
||||
play = nwplay;
|
||||
}
|
||||
@ -357,40 +360,13 @@ function doSingle() {
|
||||
* Use a timer to prevent looping of commands *
|
||||
***********************************************/
|
||||
function doSeekPos(value) {
|
||||
var val = $("#trackslider").val();
|
||||
newposition = Math.round(val);
|
||||
if (!initgui) {
|
||||
pausePosTimer();
|
||||
//set timer to not trigger it too much
|
||||
clearTimeout(seekTimer);
|
||||
$("#songelapsed").html(timeFromSeconds(val / 1000));
|
||||
seekTimer = setTimeout(triggerPos, 500);
|
||||
}
|
||||
}
|
||||
|
||||
function triggerPos() {
|
||||
if (mopidy) {
|
||||
posChanging = true;
|
||||
mopidy.playback.seek({'time_position': newposition});
|
||||
resumePosTimer();
|
||||
posChanging = false;
|
||||
mopidy.playback.seek({'time_position': Math.round(value)});
|
||||
}
|
||||
}
|
||||
|
||||
function setPosition(pos) {
|
||||
if (posChanging) {
|
||||
return;
|
||||
}
|
||||
var oldval = initgui;
|
||||
if (pos > songlength) {
|
||||
pos = songlength;
|
||||
pausePosTimer();
|
||||
}
|
||||
currentposition = pos;
|
||||
initgui = true;
|
||||
$("#trackslider").val(currentposition).slider('refresh');
|
||||
initgui = oldval;
|
||||
$("#songelapsed").html(timeFromSeconds(currentposition / 1000));
|
||||
setProgressTimer(pos);
|
||||
}
|
||||
|
||||
/***********************************************
|
||||
@ -430,33 +406,6 @@ function doMute() {
|
||||
mopidy.mixer.setMute({'mute': !mute});
|
||||
}
|
||||
|
||||
/**************************
|
||||
* Track position timer *
|
||||
**************************/
|
||||
|
||||
//timer function to update interface
|
||||
function updatePosTimer() {
|
||||
currentposition += TRACK_TIMER;
|
||||
setPosition(currentposition);
|
||||
}
|
||||
|
||||
function resumePosTimer() {
|
||||
pausePosTimer();
|
||||
if (songlength > 0) {
|
||||
posTimer = setInterval(updatePosTimer, TRACK_TIMER);
|
||||
}
|
||||
}
|
||||
|
||||
function initPosTimer() {
|
||||
pausePosTimer();
|
||||
// setPosition(0);
|
||||
resumePosTimer();
|
||||
}
|
||||
|
||||
function pausePosTimer() {
|
||||
clearInterval(posTimer);
|
||||
}
|
||||
|
||||
/************
|
||||
* Stream *
|
||||
************/
|
||||
|
||||
@ -15,11 +15,8 @@ var single;
|
||||
var currentVolume = -1;
|
||||
var mute;
|
||||
var volumeChanging = false;
|
||||
var posChanging = false;
|
||||
|
||||
var posTimer;
|
||||
var volumeTimer;
|
||||
var seekTimer;
|
||||
var initgui = true;
|
||||
var currentpos = 0;
|
||||
var popupData = {};
|
||||
@ -74,12 +71,6 @@ PLAY_NOW_SEARCH = 5;
|
||||
|
||||
MAX_TABLEROWS = 50;
|
||||
|
||||
//update track slider timer, milliseconds
|
||||
TRACK_TIMER = 1000;
|
||||
|
||||
//check status timer, every 5 or 10 sec
|
||||
STATUS_TIMER = 10000;
|
||||
|
||||
// the first part of Mopidy extensions which serve radio streams
|
||||
var radioExtensionsList = ['somafm', 'tunein', 'dirble', 'audioaddict'];
|
||||
|
||||
|
||||
@ -7,8 +7,7 @@
|
||||
* Song Info Sreen *
|
||||
********************/
|
||||
function resetSong() {
|
||||
if (!posChanging) {
|
||||
pausePosTimer();
|
||||
resetProgressTimer();
|
||||
setPlayState(false);
|
||||
setPosition(0);
|
||||
var data = new Object;
|
||||
@ -20,7 +19,6 @@ function resetSong() {
|
||||
data.track.uri = ' ';
|
||||
setSongInfo(data);
|
||||
}
|
||||
}
|
||||
|
||||
function resizeMb() {
|
||||
$("#infoname").html(songdata.track.name);
|
||||
@ -104,18 +102,18 @@ function setSongInfo(data) {
|
||||
songdata = data;
|
||||
|
||||
setSongTitle(data.track.name, false);
|
||||
songlength = Infinity;
|
||||
|
||||
if (!data.track.length || data.track.length == 0) {
|
||||
songlength = 0;
|
||||
$("#songlength").html('');
|
||||
pausePosTimer();
|
||||
resetProgressTimer();
|
||||
$('#trackslider').next().find('.ui-slider-handle').hide();
|
||||
$('#trackslider').slider('disable');
|
||||
// $('#streamnameinput').val(data.track.name);
|
||||
// $('#streamuriinput').val(data.track.uri);
|
||||
} else {
|
||||
songlength = data.track.length;
|
||||
$("#songlength").html(timeFromSeconds(data.track.length / 1000));
|
||||
$('#trackslider').slider('enable');
|
||||
$('#trackslider').next().find('.ui-slider-handle').show();
|
||||
}
|
||||
|
||||
var arttmp = '';
|
||||
@ -143,7 +141,8 @@ function setSongInfo(data) {
|
||||
$("#modalartist").html(arttmp);
|
||||
|
||||
$("#trackslider").attr("min", 0);
|
||||
$("#trackslider").attr("max", data.track.length);
|
||||
$("#trackslider").attr("max", songlength);
|
||||
progressTimer.reset().set(0, songlength);
|
||||
|
||||
resizeMb();
|
||||
}
|
||||
@ -248,15 +247,8 @@ function initSocketevents() {
|
||||
mopidy.on("event:optionsChanged", updateOptions);
|
||||
|
||||
mopidy.on("event:trackPlaybackStarted", function(data) {
|
||||
mopidy.playback.getTimePosition().then(processCurrentposition, console.error);
|
||||
setPlayState(true);
|
||||
setSongInfo(data.tl_track);
|
||||
initPosTimer();
|
||||
});
|
||||
|
||||
mopidy.on("event:trackPlaybackPaused", function(data) {
|
||||
pausePosTimer();
|
||||
setPlayState(false);
|
||||
setPlayState(true);
|
||||
});
|
||||
|
||||
mopidy.on("event:playlistsLoaded", function(data) {
|
||||
@ -276,12 +268,11 @@ function initSocketevents() {
|
||||
|
||||
mopidy.on("event:playbackStateChanged", function(data) {
|
||||
switch (data["new_state"]) {
|
||||
case "paused":
|
||||
case "stopped":
|
||||
resetSong();
|
||||
setPlayState(false);
|
||||
break;
|
||||
case "playing":
|
||||
mopidy.playback.getTimePosition().then(processCurrentposition, console.error);
|
||||
resumePosTimer();
|
||||
setPlayState(true);
|
||||
break;
|
||||
}
|
||||
@ -293,6 +284,9 @@ function initSocketevents() {
|
||||
|
||||
mopidy.on("event:seeked", function(data) {
|
||||
setPosition(parseInt(data["time_position"]));
|
||||
if (play) {
|
||||
startProgressTimer();
|
||||
}
|
||||
});
|
||||
|
||||
mopidy.on("event:streamTitleChanged", function(data) {
|
||||
@ -354,13 +348,6 @@ function setHeadline(site){
|
||||
$('#contentHeadline').html('<a href="#home" onclick="switchContent(\'home\'); return false;">' + str + '</a>');
|
||||
}
|
||||
|
||||
//update timer
|
||||
function updateStatusTimer() {
|
||||
mopidy.playback.getCurrentTlTrack().then(processCurrenttrack, console.error);
|
||||
mopidy.playback.getTimePosition().then(processCurrentposition, console.error);
|
||||
//TODO check offline?
|
||||
}
|
||||
|
||||
//update tracklist options.
|
||||
function updateOptions() {
|
||||
mopidy.tracklist.getRepeat().then(processRepeat, console.error);
|
||||
@ -483,6 +470,11 @@ $(document).ready(function(event) {
|
||||
//initialize events
|
||||
initSocketevents();
|
||||
|
||||
progressTimer = new ProgressTimer({
|
||||
callback: timerCallback,
|
||||
//updateRate: 2000,
|
||||
});
|
||||
|
||||
resetSong();
|
||||
|
||||
if (location.hash.length < 2) {
|
||||
@ -492,9 +484,6 @@ $(document).ready(function(event) {
|
||||
initgui = false;
|
||||
window.onhashchange = locationHashChanged;
|
||||
|
||||
//update gui status every x seconds from mopdidy
|
||||
setInterval(updateStatusTimer, STATUS_TIMER);
|
||||
|
||||
//only show backbutton if in UIWebview
|
||||
if (window.navigator.standalone) {
|
||||
$("#btback").show();
|
||||
@ -581,6 +570,10 @@ $(document).ready(function(event) {
|
||||
$("#panel").panel("close");
|
||||
event.stopImmediatePropagation(); }
|
||||
} );
|
||||
|
||||
$( "#trackslider" ).on( "slidestart", function() { progressTimer.stop(); } )
|
||||
$( "#trackslider" ).on( "slidestop", function() { doSeekPos( $(this).val() ); } );
|
||||
|
||||
});
|
||||
|
||||
function updatePlayIcons (uri, tlid) {
|
||||
|
||||
@ -60,8 +60,7 @@ function processSingle(data) {
|
||||
* process results of current position
|
||||
*********************************************************/
|
||||
function processCurrentposition(data) {
|
||||
var pos = parseInt(data);
|
||||
setPosition(pos);
|
||||
setPosition(parseInt(data));
|
||||
}
|
||||
|
||||
/********************************************************
|
||||
@ -70,7 +69,6 @@ function processCurrentposition(data) {
|
||||
function processPlaystate(data) {
|
||||
if (data == 'playing') {
|
||||
setPlayState(true);
|
||||
resumePosTimer();
|
||||
} else {
|
||||
setPlayState(false);
|
||||
}
|
||||
|
||||
171
mopidy_musicbox_webclient/static/js/progress_timer.js
Normal file
171
mopidy_musicbox_webclient/static/js/progress_timer.js
Normal file
@ -0,0 +1,171 @@
|
||||
var progressTimer;
|
||||
var progressElement = document.getElementById('trackslider');
|
||||
var positionNode = document.createTextNode('0:00');
|
||||
var durationNode = document.createTextNode('0:00');
|
||||
|
||||
var START_BEATS = 5 // 0.5 seconds, needs to be less than 1s to prevent unwanted updates.
|
||||
var RUN_BEATS = 300 // 30 seconds assuming default timer update rate of 100ms
|
||||
var callbackHeartbeats = 0; // Timer will check syncs on every n-number of calls.
|
||||
var targetPosition = null;
|
||||
|
||||
var MAX_SYNCS = 5; // Maximum number of consecutive successful syncs to perform.
|
||||
var syncsLeft = MAX_SYNCS;
|
||||
var synced = false;
|
||||
var consecutiveSyncs = 0;
|
||||
|
||||
document.getElementById('songelapsed').appendChild(positionNode);
|
||||
document.getElementById('songlength').appendChild(durationNode);
|
||||
|
||||
function timerCallback(position, duration, isRunning) {
|
||||
updateTimers(position, duration, isRunning);
|
||||
|
||||
if (callbackHeartbeats == 0) {
|
||||
callbackHeartbeats = getHeartbeat();
|
||||
}
|
||||
|
||||
if (mopidy && position > 0) {
|
||||
// Mopidy and timer are both initialized.
|
||||
if (callbackHeartbeats-- == 1) {
|
||||
// Get time position from Mopidy on every nth callback until
|
||||
// synced.
|
||||
mopidy.playback.getTimePosition().then(
|
||||
function(mopidy_position) {
|
||||
syncTimer(position, mopidy_position);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function updateTimers(position, duration, isRunning) {
|
||||
var ready = !(duration == Infinity && position == 0 && !isRunning); // Timer has been properly initialized.
|
||||
var streaming = (duration == Infinity && position > 0); // Playing a stream.
|
||||
var ok = synced && isRunning; // Normal operation.
|
||||
var syncing = !synced && isRunning; // Busy syncing.
|
||||
|
||||
if (!ready) {
|
||||
//Make sure that default values are displayed while the timer is being initialized.
|
||||
positionNode.nodeValue = '';
|
||||
durationNode.nodeValue = '';
|
||||
$("#trackslider").val(0).slider('refresh');
|
||||
} else if (syncing) {
|
||||
if (!targetPosition) {
|
||||
// Waiting for Mopidy to provide a target position.
|
||||
positionNode.nodeValue = '(wait)';
|
||||
} else {
|
||||
// Busy seeking to new target position.
|
||||
positionNode.nodeValue = '(sync)';
|
||||
}
|
||||
} else if (streaming) {
|
||||
positionNode.nodeValue = format(position);;
|
||||
durationNode.nodeValue = '(n/a)';
|
||||
} else if (synced) {
|
||||
positionNode.nodeValue = format(position);
|
||||
durationNode.nodeValue = format(duration || 0);
|
||||
}
|
||||
|
||||
if (ok) {
|
||||
// Don't update the track slider unless it is synced and running.
|
||||
// (prevents awkward 'jitter' animation).
|
||||
$("#trackslider").val(position).slider('refresh');
|
||||
}
|
||||
}
|
||||
|
||||
function getHeartbeat() {
|
||||
if (syncsLeft > 0 && callbackHeartbeats == 0) {
|
||||
// Step back exponentially while increasing heartbeat.
|
||||
return Math.round(delay_exponential(5, 2, MAX_SYNCS - syncsLeft));
|
||||
} else if (syncsLeft == 0 && callbackHeartbeats == 0) {
|
||||
// Sync completed, keep checking using maximum number of heartbeats.
|
||||
return RUN_BEATS;
|
||||
} else {
|
||||
return START_BEATS;
|
||||
}
|
||||
}
|
||||
|
||||
function syncTimer(current, target) {
|
||||
if (target) {
|
||||
var drift = Math.abs(target - current);
|
||||
if (drift <= 500) {
|
||||
syncsLeft--;
|
||||
// Less than 500ms == in sync.
|
||||
if (++consecutiveSyncs == 2) {
|
||||
// Need at least two consecutive syncs to know that Mopidy
|
||||
// is progressing playback and we are in sync.
|
||||
synced = true;
|
||||
targetPosition = null;
|
||||
consecutiveSyncs = 0;
|
||||
}
|
||||
} else {
|
||||
// Drift is too large, re-sync with Mopidy.
|
||||
reset();
|
||||
targetPosition = target;
|
||||
progressTimer.set(targetPosition);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function toInt(value) {
|
||||
return value.match(/^\w*\d+\w*$/) ? parseInt(value) : null;
|
||||
}
|
||||
|
||||
function format(milliseconds) {
|
||||
if (milliseconds === Infinity) {
|
||||
return '0:00';
|
||||
}
|
||||
|
||||
var seconds = Math.floor(milliseconds / 1000);
|
||||
var minutes = Math.floor(seconds / 60);
|
||||
seconds = seconds % 60;
|
||||
|
||||
seconds = seconds < 10 ? '0' + seconds : seconds;
|
||||
return minutes + ':' + seconds;
|
||||
}
|
||||
|
||||
function delay_exponential(base, growthFactor, attempts) {
|
||||
/*Calculate number of beats between syncs based on exponential function.
|
||||
The format is::
|
||||
|
||||
base * growthFactor ^ (attempts - 1)
|
||||
|
||||
If ``base`` is set to 'rand' then a random number between
|
||||
0 and 1 will be used as the base.
|
||||
Base must be greater than 0.
|
||||
*/
|
||||
if (base == 'rand') {
|
||||
base = Math.random();
|
||||
}
|
||||
beats = base * (Math.pow(growthFactor, (attempts - 1)));
|
||||
return beats;
|
||||
}
|
||||
|
||||
function reset() {
|
||||
synced = false;
|
||||
consecutiveSyncs = 0;
|
||||
syncsLeft = MAX_SYNCS;
|
||||
callbackHeartbeats = START_BEATS;
|
||||
targetPosition = null;
|
||||
}
|
||||
|
||||
function setProgressTimer(pos) {
|
||||
reset();
|
||||
targetPosition = pos;
|
||||
progressTimer.set(pos);
|
||||
if (!play) {
|
||||
// Set lapsed time and slider position directly as timer callback is not currently
|
||||
// running.
|
||||
positionNode.nodeValue = format(pos);
|
||||
$("#trackslider").val(pos).slider('refresh');
|
||||
}
|
||||
}
|
||||
|
||||
function startProgressTimer() {
|
||||
reset();
|
||||
progressTimer.start();
|
||||
}
|
||||
|
||||
function resetProgressTimer() {
|
||||
progressTimer.reset();
|
||||
reset();
|
||||
targetPosition = 0;
|
||||
}
|
||||
125
mopidy_musicbox_webclient/static/vendors/media_progress_timer/timer.js
vendored
Normal file
125
mopidy_musicbox_webclient/static/vendors/media_progress_timer/timer.js
vendored
Normal file
@ -0,0 +1,125 @@
|
||||
/*! timer.js v2.0.2
|
||||
* https://github.com/adamcik/media-progress-timer
|
||||
* Copyright (c) 2015 Thomas Adamcik
|
||||
* Licensed under the Apache License, Version 2.0 */
|
||||
|
||||
(function() {
|
||||
|
||||
'use strict';
|
||||
|
||||
var now = typeof window.performance !== 'undefined' &&
|
||||
typeof window.performance.now !== 'undefined' &&
|
||||
window.performance.now.bind(window.performance) || Date.now ||
|
||||
function() { return new Date().getTime(); };
|
||||
|
||||
function ProgressTimer(options) {
|
||||
if (!(this instanceof ProgressTimer)) {
|
||||
return new ProgressTimer(options);
|
||||
} else if (typeof options === 'function') {
|
||||
options = {'callback': options};
|
||||
} else if (typeof options !== 'object') {
|
||||
throw 'ProgressTimer must be called with a callback or options.';
|
||||
} else if (typeof options.callback !== 'function') {
|
||||
throw 'ProgressTimer needs a callback to operate.';
|
||||
}
|
||||
|
||||
this._running = false;
|
||||
this._updateRate = Math.max(options.updateRate || 100, 10);
|
||||
this._callback = options.callback;
|
||||
this._fallback = typeof window.requestAnimationFrame === 'undefined' ||
|
||||
options.disableRequestAnimationFrame|| false;
|
||||
|
||||
if (!this._fallback) {
|
||||
this._callUpdate = this._scheduleAnimationFrame;
|
||||
this._scheduleUpdate = this._scheduleAnimationFrame;
|
||||
}
|
||||
|
||||
this._boundCallUpdate = this._callUpdate.bind(this);
|
||||
this._boundUpdate = this._update.bind(this);
|
||||
|
||||
this.reset();
|
||||
}
|
||||
|
||||
ProgressTimer.prototype.set = function(position, duration) {
|
||||
if (arguments.length === 0) {
|
||||
throw 'set requires at least a position argument.';
|
||||
} else if (arguments.length === 1) {
|
||||
duration = this._state.duration;
|
||||
} else {
|
||||
duration = Math.floor(
|
||||
Math.max(duration === null ? Infinity : duration || 0, 0));
|
||||
}
|
||||
position = Math.floor(Math.min(Math.max(position || 0, 0), duration));
|
||||
|
||||
this._state = {
|
||||
initialTimestamp: null,
|
||||
initialPosition: position,
|
||||
previousPosition: position,
|
||||
duration: duration
|
||||
};
|
||||
|
||||
this._callback(position, duration, this._running);
|
||||
return this;
|
||||
};
|
||||
|
||||
ProgressTimer.prototype.start = function() {
|
||||
this._running = true;
|
||||
this._callUpdate();
|
||||
return this;
|
||||
};
|
||||
|
||||
ProgressTimer.prototype.stop = function() {
|
||||
this._running = false;
|
||||
var state = this._state;
|
||||
return this.set(state.previousPosition, state.duration);
|
||||
};
|
||||
|
||||
ProgressTimer.prototype.reset = function() {
|
||||
this._running = false;
|
||||
return this.set(0, Infinity);
|
||||
};
|
||||
|
||||
ProgressTimer.prototype._callUpdate = function() {
|
||||
this._update(now());
|
||||
};
|
||||
|
||||
ProgressTimer.prototype._scheduleUpdate = function(timestamp) {
|
||||
var adjustedTimeout = timestamp + this._updateRate - now();
|
||||
setTimeout(this._boundCallUpdate, adjustedTimeout);
|
||||
};
|
||||
|
||||
ProgressTimer.prototype._scheduleAnimationFrame = function() {
|
||||
window.requestAnimationFrame(this._boundUpdate);
|
||||
};
|
||||
|
||||
ProgressTimer.prototype._update = function(timestamp) {
|
||||
if (!this._running) {
|
||||
return;
|
||||
}
|
||||
|
||||
var state = this._state;
|
||||
state.initialTimestamp = state.initialTimestamp || timestamp;
|
||||
|
||||
var position = state.initialPosition + timestamp - state.initialTimestamp;
|
||||
var duration = state.duration;
|
||||
|
||||
if (position < duration || duration === null) {
|
||||
var delta = position - state.previousPosition;
|
||||
if (delta >= this._updateRate || this._fallback) {
|
||||
this._callback(Math.floor(position), duration, this._running);
|
||||
state.previousPosition = position;
|
||||
}
|
||||
this._scheduleUpdate(timestamp);
|
||||
} else {
|
||||
this._running = false;
|
||||
this._callback(duration, duration, this._running);
|
||||
}
|
||||
};
|
||||
|
||||
if(typeof module !== 'undefined') {
|
||||
module.exports = ProgressTimer;
|
||||
} else {
|
||||
window.ProgressTimer = ProgressTimer;
|
||||
}
|
||||
|
||||
}());
|
||||
Loading…
Reference in New Issue
Block a user