From d91ba598b82c927945744c7041dc05500b5545b3 Mon Sep 17 00:00:00 2001 From: Adil Date: Tue, 4 Dec 2012 18:27:56 -0500 Subject: [PATCH] - Changes from code review: - Refactored repeatAndCleanup() function. - Reverted making private methods doUnzoom and predraw public. - Put requestAnimationFrame shim function in Dygraph namespace. --- dygraph-options-reference.js | 6 ++++ dygraph-utils.js | 73 ++++++++++++++++++++++++-------------------- dygraph.js | 8 ----- 3 files changed, 46 insertions(+), 41 deletions(-) diff --git a/dygraph-options-reference.js b/dygraph-options-reference.js index 5aa7f05..df19c7d 100644 --- a/dygraph-options-reference.js +++ b/dygraph-options-reference.js @@ -748,6 +748,12 @@ Dygraph.OPTIONS_REFERENCE = // "type": "string", "description": "The range selector mini plot fill color. This can be of the form \"#AABBCC\" or \"rgb(255,100,200)\" or \"yellow\". You can also specify null or \"\" to turn off fill." }, + "xIsEpochDate": { + "default": "false", + "labels": ["CSV parsing"], + "type": "boolean", + "description": "When set the X axis is interpreted as Unix epoch date values." + }, "animatedZooms": { "default": "false", "labels": ["Interactive Elements"], diff --git a/dygraph-utils.js b/dygraph-utils.js index 797adce..10a393c 100644 --- a/dygraph-utils.js +++ b/dygraph-utils.js @@ -816,7 +816,7 @@ Dygraph.createIterator = function(array, start, length, opt_predicate) { // Shim layer with setTimeout fallback. // From: http://paulirish.com/2011/requestanimationframe-for-smart-animating/ -window.requestAnimFrame = (function(){ +Dygraph.requestAnimFrame = (function(){ return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || @@ -828,45 +828,52 @@ window.requestAnimFrame = (function(){ })(); /** - * @private - * Call a function at most N times at an attempted given interval, then call a - * cleanup function once. repeat_fn is called once immediately, then (times - 1) - * times asynchronously. If times=1, then cleanup_fn() is also called - * synchronously. - * @param repeat_fn {Function} Called repeatedly -- takes the number of calls - * (from 0 to times-1) as an argument. - * @param times {number} The number of times max to call repeat_fn - * @param every_ms {number} Milliseconds to schedule between calls - * @param cleanup_fn {Function} A function to call after all repeat_fn calls. + * Call a function at most maxFrames times at an attempted interval of + * framePeriodInMillis, then call a cleanup function once. repeatFn is called + * once immediately, then at most (maxFrames - 1) times asynchronously. If + * maxFrames==1, then cleanup_fn() is also called synchronously. This function + * is used to sequence animation. + * @param {function(number)} repeatFn Called repeatedly -- takes the frame + * number (from 0 to maxFrames-1) as an argument. + * @param {number} maxFrames The max number of times to call repeatFn + * @param {number} framePeriodInMillis Max requested time between frames. + * @param {function()} cleanupFn A function to call after all repeatFn calls. * @private */ -Dygraph.repeatAndCleanup = function(repeat_fn, times, every_ms, cleanup_fn) { - var count = 0; - var previous_count; - var start_time = new Date().getTime(); - repeat_fn(count); - if (times == 1) { - cleanup_fn(); +Dygraph.repeatAndCleanup = function(repeatFn, maxFrames, framePeriodInMillis, + cleanupFn) { + var frameNumber = 0; + var previousFrameNumber; + var startTime = new Date().getTime(); + repeatFn(frameNumber); + if (maxFrames == 1) { + cleanupFn(); return; } + var maxFrameArg = maxFrames - 1; (function loop() { - if (count >= times) return; - window.requestAnimFrame(function(scheduled_epoch_time_ms) { - var delay = (scheduled_epoch_time_ms - start_time); - previous_count = count; - count = Math.floor(delay / every_ms); - if ((count - previous_count) > (times / 2)) { - count = previous_count + (times / 2); - } - if (count > times - 1) { - // Ensure call at max times. - if (previous_count !== (times - 1)) { - repeat_fn(times - 1); - } - cleanup_fn(); + if (frameNumber >= maxFrames) return; + Dygraph.requestAnimFrame(function() { + // Determine which frame to draw based on the delay so far. Will skip + // frames if necessary. + var currentTime = new Date().getTime(); + var delayInMillis = currentTime - startTime; + previousFrameNumber = frameNumber; + frameNumber = Math.floor(delayInMillis / framePeriodInMillis); + var frameDelta = frameNumber - previousFrameNumber; + // If we predict that the subsequent repeatFn call will overshoot our + // total frame target, so our last call will cause a stutter, then jump to + // the last call immediately. If we're going to cause a stutter, better + // to do it faster than slower. + var predictOvershootStutter = (frameNumber + frameDelta) > maxFrameArg; + if (predictOvershootStutter || (frameNumber >= maxFrameArg)) { + repeatFn(maxFrameArg); // Ensure final call with maxFrameArg. + cleanupFn(); } else { - repeat_fn(count); + if (frameDelta != 0) { // Don't call repeatFn with duplicate frames. + repeatFn(frameNumber); + } loop(); } }); diff --git a/dygraph.js b/dygraph.js index 3366fe3..ba8da98 100644 --- a/dygraph.js +++ b/dygraph.js @@ -1458,10 +1458,6 @@ Dygraph.prototype.doZoomY_ = function(lowY, highY) { }); }; -Dygraph.prototype.doUnzoom = function() { - this.doUnzoom_(); -}; - /** * Reset the zoom to the original view coordinates. This is the same as * double-clicking on the graph. @@ -2142,10 +2138,6 @@ Dygraph.prototype.extremeValues_ = function(series) { return [minY, maxY]; }; -Dygraph.prototype.predraw = function() { - this.predraw_(); -}; - /** * @private * This function is called once when the chart's data is changed or the options -- 2.7.4