From 749281f855678908181d622157ceee12fa0f8349 Mon Sep 17 00:00:00 2001 From: Dan Vanderkam Date: Sun, 13 Oct 2013 21:45:26 -0400 Subject: [PATCH] copy datahandler changes over from full-closure branch --- datahandler/bars-custom.js | 15 +- datahandler/bars-error.js | 15 +- datahandler/bars-fractions.js | 15 +- datahandler/bars.js | 48 ++++- datahandler/datahandler.js | 382 +++++++++++++++++++-------------------- datahandler/default-fractions.js | 8 +- datahandler/default.js | 12 +- 7 files changed, 277 insertions(+), 218 deletions(-) diff --git a/datahandler/bars-custom.js b/datahandler/bars-custom.js index 37255e5..7313ca2 100644 --- a/datahandler/bars-custom.js +++ b/datahandler/bars-custom.js @@ -14,11 +14,17 @@ /*global Dygraph:false */ "use strict"; -Dygraph.DataHandlers.CustomBarsHandler = Dygraph.DataHandler(); +/** + * @constructor + * @extends Dygraph.DataHandlers.BarsHandler + */ +Dygraph.DataHandlers.CustomBarsHandler = function() { +}; + var CustomBarsHandler = Dygraph.DataHandlers.CustomBarsHandler; CustomBarsHandler.prototype = new Dygraph.DataHandlers.BarsHandler(); -// customBars +/** @inheritDoc */ CustomBarsHandler.prototype.extractSeries = function(rawData, i, options) { // TODO(danvk): pre-allocate series here. var series = []; @@ -49,8 +55,9 @@ CustomBarsHandler.prototype.extractSeries = function(rawData, i, options) { return series; }; -CustomBarsHandler.prototype.rollingAverage = function(originalData, rollPeriod, - options) { +/** @inheritDoc */ +CustomBarsHandler.prototype.rollingAverage = + function(originalData, rollPeriod, options) { rollPeriod = Math.min(rollPeriod, originalData.length); var rollingData = []; var y, low, high, mid,count, i, extremes; diff --git a/datahandler/bars-error.js b/datahandler/bars-error.js index 6da2fc5..71dbe34 100644 --- a/datahandler/bars-error.js +++ b/datahandler/bars-error.js @@ -14,11 +14,17 @@ /*global Dygraph:false */ "use strict"; -Dygraph.DataHandlers.ErrorBarsHandler = Dygraph.DataHandler(); +/** + * @constructor + * @extends Dygraph.DataHandlers.BarsHandler + */ +Dygraph.DataHandlers.ErrorBarsHandler = function() { +}; + var ErrorBarsHandler = Dygraph.DataHandlers.ErrorBarsHandler; ErrorBarsHandler.prototype = new Dygraph.DataHandlers.BarsHandler(); -// errorBars +/** @inheritDoc */ ErrorBarsHandler.prototype.extractSeries = function(rawData, i, options) { // TODO(danvk): pre-allocate series here. var series = []; @@ -53,8 +59,9 @@ ErrorBarsHandler.prototype.extractSeries = function(rawData, i, options) { return series; }; -ErrorBarsHandler.prototype.rollingAverage = function(originalData, rollPeriod, - options) { +/** @inheritDoc */ +ErrorBarsHandler.prototype.rollingAverage = + function(originalData, rollPeriod, options) { rollPeriod = Math.min(rollPeriod, originalData.length); var rollingData = []; var sigma = options.get("sigma"); diff --git a/datahandler/bars-fractions.js b/datahandler/bars-fractions.js index 28c0491..8594c07 100644 --- a/datahandler/bars-fractions.js +++ b/datahandler/bars-fractions.js @@ -15,11 +15,17 @@ /*global Dygraph:false */ "use strict"; -Dygraph.DataHandlers.FractionsBarsHandler = Dygraph.DataHandler(); +/** + * @constructor + * @extends Dygraph.DataHandlers.BarsHandler + */ +Dygraph.DataHandlers.FractionsBarsHandler = function() { +}; + var FractionsBarsHandler = Dygraph.DataHandlers.FractionsBarsHandler; FractionsBarsHandler.prototype = new Dygraph.DataHandlers.BarsHandler(); -// errorBars +/** @inheritDoc */ FractionsBarsHandler.prototype.extractSeries = function(rawData, i, options) { // TODO(danvk): pre-allocate series here. var series = []; @@ -58,8 +64,9 @@ FractionsBarsHandler.prototype.extractSeries = function(rawData, i, options) { return series; }; -FractionsBarsHandler.prototype.rollingAverage = function(originalData, rollPeriod, - options) { +/** @inheritDoc */ +FractionsBarsHandler.prototype.rollingAverage = + function(originalData, rollPeriod, options) { rollPeriod = Math.min(rollPeriod, originalData.length); var rollingData = []; var sigma = options.get("sigma"); diff --git a/datahandler/bars.js b/datahandler/bars.js index 914ee27..a6b0cc5 100644 --- a/datahandler/bars.js +++ b/datahandler/bars.js @@ -17,30 +17,61 @@ /*global DygraphLayout:false */ "use strict"; -Dygraph.DataHandlers.BarsHandler = Dygraph.DataHandler(); +/** + * @constructor + * @extends {Dygraph.DataHandler} + */ +Dygraph.DataHandlers.BarsHandler = function() { + Dygraph.DataHandler.call(this); +}; +Dygraph.DataHandlers.BarsHandler.prototype = new Dygraph.DataHandler(); + +// alias for the rest of the implementation var BarsHandler = Dygraph.DataHandlers.BarsHandler; -// errorBars -BarsHandler.prototype.extractSeries = function(rawData, i, options) { +// TODO(danvk): figure out why the jsdoc has to be copy/pasted from superclass. +// (I get closure compiler errors if this isn't here.) +/** + * @override + * @param {!Array.} rawData The raw data passed into dygraphs where + * rawData[i] = [x,ySeries1,...,ySeriesN]. + * @param {!number} seriesIndex Index of the series to extract. All other + * series should be ignored. + * @param {!DygraphOptions} options Dygraph options. + * @return {Array.<[!number,?number,?]>} The series in the unified data format + * where series[i] = [x,y,{extras}]. + */ +BarsHandler.prototype.extractSeries = function(rawData, seriesIndex, options) { // Not implemented here must be extended }; +/** + * @override + * @param {!Array.<[!number,?number,?]>} series The series in the unified + * data format where series[i] = [x,y,{extras}]. + * @param {!number} rollPeriod The number of points over which to average the data + * @param {!DygraphOptions} options The dygraph options. + * TODO(danvk): be more specific than "Array" here. + * @return {!Array.<[!number,?number,?]>} the rolled series. + */ BarsHandler.prototype.rollingAverage = - function(originalData, rollPeriod, options) { + function(series, rollPeriod, options) { // Not implemented here, must be extended. }; +/** @inheritDoc */ BarsHandler.prototype.onPointsCreated_ = function(series, points) { for (var i = 0; i < series.length; ++i) { var item = series[i]; var point = points[i]; point.y_top = NaN; point.y_bottom = NaN; - point.yval_minus = DygraphLayout.parseFloat_(item[2][0]); - point.yval_plus = DygraphLayout.parseFloat_(item[2][1]); + point.yval_minus = Dygraph.parseFloat(item[2][0]); + point.yval_plus = Dygraph.parseFloat(item[2][1]); } }; +/** @inheritDoc */ BarsHandler.prototype.getExtremeYValues = function(series, dateWindow, options) { var minY = null, maxY = null, y; @@ -64,13 +95,14 @@ BarsHandler.prototype.getExtremeYValues = function(series, dateWindow, options) return [ minY, maxY ]; }; +/** @inheritDoc */ BarsHandler.prototype.onLineEvaluated = function(points, axis, logscale) { var point; for (var j = 0; j < points.length; j++) { // Copy over the error terms point = points[j]; - point.y_top = DygraphLayout._calcYNormal(axis, point.yval_minus, logscale); - point.y_bottom = DygraphLayout._calcYNormal(axis, point.yval_plus, logscale); + point.y_top = DygraphLayout.calcYNormal_(axis, point.yval_minus, logscale); + point.y_bottom = DygraphLayout.calcYNormal_(axis, point.yval_plus, logscale); } }; diff --git a/datahandler/datahandler.js b/datahandler/datahandler.js index 5ed0112..b9eb67c 100644 --- a/datahandler/datahandler.js +++ b/datahandler/datahandler.js @@ -41,223 +41,213 @@ /*global Dygraph:false */ /*global DygraphLayout:false */ -(function() { - -"use strict"; - -/** - * A collection of functions to create and retrieve data handlers. - * @type {Object.} - */ -Dygraph.DataHandlers = {}; - /** * * The data handler is responsible for all data specific operations. All of the * series data it receives and returns is always in the unified data format. * Initially the unified data is created by the extractSeries method + * @constructor */ Dygraph.DataHandler = function () { - /** - * Constructor for all data handlers. - * @constructor - */ - var handler = function() { - return this; - }; +}; + +/** + * A collection of functions to create and retrieve data handlers. + * @type {Object.} + */ +Dygraph.DataHandlers = {}; - /** - * X-value array index constant for unified data samples. - * @const - * @type {number} - */ - handler.X = 0; +(function() { - /** - * Y-value array index constant for unified data samples. - * @const - * @type {number} - */ - handler.Y = 1; +"use strict"; - /** - * Extras-value array index constant for unified data samples. - * @const - * @type {number} - */ - handler.EXTRAS = 2; +var handler = Dygraph.DataHandler; - /** - * Extracts one series from the raw data (a 2D array) into an array of the - * unified data format. - * This is where undesirable points (i.e. negative values on log scales and - * missing values through which we wish to connect lines) are dropped. - * TODO(danvk): the "missing values" bit above doesn't seem right. - * - * @param rawData {!Array.} The raw data passed into dygraphs where - * rawData[i] = [x,ySeries1,...,ySeriesN]. - * @param seriesIndex {!number} Index of the series to extract. All other series should - * be ignored. - * @param options {!DygraphOptions} Dygraph options. - * @returns {Array.<[!number,?number,?]>} The series in the unified data format - * where series[i] = [x,y,{extras}]. - * @public - */ - handler.prototype.extractSeries = function(rawData, seriesIndex, options) { - }; +/** + * X-value array index constant for unified data samples. + * @const + * @type {number} + */ +handler.X = 0; - /** - * Converts a series to a Point array. - * - * @param {!Array.<[!number,?number,?]>} series The series in the unified - * data format where series[i] = [x,y,{extras}]. - * @param {!string} setName Name of the series. - * @param {!number} boundaryIdStart Index offset of the first point, equal to the - * number of skipped points left of the date window minimum (if any). - * @return {!Array.} List of points for this series. - * @public - */ - handler.prototype.seriesToPoints = function(series, setName, boundaryIdStart) { - // TODO(bhs): these loops are a hot-spot for high-point-count charts. In - // fact, - // on chrome+linux, they are 6 times more expensive than iterating through - // the - // points and drawing the lines. The brunt of the cost comes from allocating - // the |point| structures. - var points = []; - for ( var i = 0; i < series.length; ++i) { - var item = series[i]; - var yraw = item[1]; - var yval = yraw === null ? null : DygraphLayout.parseFloat_(yraw); - var point = { - x : NaN, - y : NaN, - xval : DygraphLayout.parseFloat_(item[0]), - yval : yval, - name : setName, // TODO(danvk): is this really necessary? - idx : i + boundaryIdStart - }; - points.push(point); - } - handler.prototype.onPointsCreated_(series, points); - return points; - }; +/** + * Y-value array index constant for unified data samples. + * @const + * @type {number} + */ +handler.Y = 1; + +/** + * Extras-value array index constant for unified data samples. + * @const + * @type {number} + */ +handler.EXTRAS = 2; + +/** + * Extracts one series from the raw data (a 2D array) into an array of the + * unified data format. + * This is where undesirable points (i.e. negative values on log scales and + * missing values through which we wish to connect lines) are dropped. + * TODO(danvk): the "missing values" bit above doesn't seem right. + * + * @param {!Array.} rawData The raw data passed into dygraphs where + * rawData[i] = [x,ySeries1,...,ySeriesN]. + * @param {!number} seriesIndex Index of the series to extract. All other + * series should be ignored. + * @param {!DygraphOptions} options Dygraph options. + * @return {Array.<[!number,?number,?]>} The series in the unified data format + * where series[i] = [x,y,{extras}]. + */ +handler.prototype.extractSeries = function(rawData, seriesIndex, options) { +}; - /** - * Callback called for each series after the series points have been generated - * which will later be used by the plotters to draw the graph. - * Here data may be added to the seriesPoints which is needed by the plotters. - * The indexes of series and points are in sync meaning the original data - * sample for series[i] is points[i]. - * - * @param {!Array.<[!number,?number,?]>} series The series in the unified - * data format where series[i] = [x,y,{extras}]. - * @param {!Array.} points The corresponding points passed - * to the plotter. - * @private - */ - handler.prototype.onPointsCreated_ = function(series, points) { - }; +/** + * Converts a series to a Point array. + * + * @param {!Array.<[!number,?number,?]>} series The series in the unified + * data format where series[i] = [x,y,{extras}]. + * @param {!string} setName Name of the series. + * @param {!number} boundaryIdStart Index offset of the first point, equal to the + * number of skipped points left of the date window minimum (if any). + * @return {!Array.} List of points for this series. + */ +handler.prototype.seriesToPoints = function(series, setName, boundaryIdStart) { + // TODO(bhs): these loops are a hot-spot for high-point-count charts. In + // fact, + // on chrome+linux, they are 6 times more expensive than iterating through + // the + // points and drawing the lines. The brunt of the cost comes from allocating + // the |point| structures. + var points = []; + for ( var i = 0; i < series.length; ++i) { + var item = series[i]; + var yraw = item[1]; + var yval = yraw === null ? null : Dygraph.parseFloat(yraw); + var point = { + x : NaN, + y : NaN, + xval : Dygraph.parseFloat(item[0]), + yval : yval, + name : setName, // TODO(danvk): is this really necessary? + idx : i + boundaryIdStart + }; + points.push(point); + } + this.onPointsCreated_(series, points); + return points; +}; - /** - * Calculates the rolling average of a data set. - * - * @param {!Array.<[!number,?number,?]>} series The series in the unified - * data format where series[i] = [x,y,{extras}]. - * @param {!number} rollPeriod The number of points over which to average the data - * @param {!DygraphOptions} options The dygraph options. - * @return the rolled series. - * @public - */ - handler.prototype.rollingAverage = function(series, rollPeriod, options) { - }; +/** + * Callback called for each series after the series points have been generated + * which will later be used by the plotters to draw the graph. + * Here data may be added to the seriesPoints which is needed by the plotters. + * The indexes of series and points are in sync meaning the original data + * sample for series[i] is points[i]. + * + * @param {!Array.<[!number,?number,?]>} series The series in the unified + * data format where series[i] = [x,y,{extras}]. + * @param {!Array.} points The corresponding points passed + * to the plotter. + * @protected + */ +handler.prototype.onPointsCreated_ = function(series, points) { +}; - /** - * Computes the range of the data series (including confidence intervals). - * - * @param {!Array.<[!number,?number,?]>} series The series in the unified - * data format where series[i] = [x,y,{extras}]. - * @param {!Array.} dateWindow The x-value range to display with - * the format: [min,max]. - * @param {!DygraphOptions} options The dygraph options. - * @return {Array.} The low and high extremes of the series in the given window with - * the format: [low, high]. - * @public - */ - handler.prototype.getExtremeYValues = function(series, dateWindow, options) { - }; +/** + * Calculates the rolling average of a data set. + * + * @param {!Array.<[!number,?number,?]>} series The series in the unified + * data format where series[i] = [x,y,{extras}]. + * @param {!number} rollPeriod The number of points over which to average the data + * @param {!DygraphOptions} options The dygraph options. + * TODO(danvk): be more specific than "Array" here. + * @return {!Array.<[!number,?number,?]>} the rolled series. + */ +handler.prototype.rollingAverage = function(series, rollPeriod, options) { +}; - /** - * Callback called for each series after the layouting data has been - * calculated before the series is drawn. Here normalized positioning data - * should be calculated for the extras of each point. - * - * @param {!Array.} points The points passed to - * the plotter. - * @param {!Object} axis The axis on which the series will be plotted. - * @param {!boolean} logscale Weather or not to use a logscale. - * @public - */ - handler.prototype.onLineEvaluated = function(points, axis, logscale) { - }; +/** + * Computes the range of the data series (including confidence intervals). + * + * @param {!Array.<[!number,?number,?]>} series The series in the unified + * data format where series[i] = [x, y, {extras}]. + * @param {!Array.} dateWindow The x-value range to display with + * the format: [min, max]. + * @param {!DygraphOptions} options The dygraph options. + * @return {Array.} The low and high extremes of the series in the + * given window with the format: [low, high]. + */ +handler.prototype.getExtremeYValues = function(series, dateWindow, options) { +}; - /** - * Helper method that computes the y value of a line defined by the points p1 - * and p2 and a given x value. - * - * @param {!Array.} p1 left point ([x,y]). - * @param {!Array.} p2 right point ([x,y]). - * @param {!number} xValue The x value to compute the y-intersection for. - * @return {number} corresponding y value to x on the line defined by p1 and p2. - * @private - */ - handler.prototype.computeYInterpolation_ = function(p1, p2, xValue) { - var deltaY = p2[1] - p1[1]; - var deltaX = p2[0] - p1[0]; - var gradient = deltaY / deltaX; - var growth = (xValue - p1[0]) * gradient; - return p1[1] + growth; - }; +/** + * Callback called for each series after the layouting data has been + * calculated before the series is drawn. Here normalized positioning data + * should be calculated for the extras of each point. + * + * @param {!Array.} points The points passed to + * the plotter. + * @param {!Object} axis The axis on which the series will be plotted. + * @param {!boolean} logscale Weather or not to use a logscale. + */ +handler.prototype.onLineEvaluated = function(points, axis, logscale) { +}; - /** - * Helper method that returns the first and the last index of the given series - * that lie inside the given dateWindow. - * - * @param {!Array.<[!number,?number,?]>} series The series in the unified - * data format where series[i] = [x,y,{extras}]. - * @param {!Array.} dateWindow The x-value range to display with - * the format: [min,max]. - * @return {!Array.<[!number,?number,?]>} The samples of the series that - * are in the given date window. - * @private - */ - handler.prototype.getIndexesInWindow_ = function(series, dateWindow) { - var firstIdx = 0, lastIdx = series.length - 1; - if (dateWindow) { - var idx = 0; - var low = dateWindow[0]; - var high = dateWindow[1]; +/** + * Helper method that computes the y value of a line defined by the points p1 + * and p2 and a given x value. + * + * @param {!Array.} p1 left point ([x,y]). + * @param {!Array.} p2 right point ([x,y]). + * @param {!number} xValue The x value to compute the y-intersection for. + * @return {number} corresponding y value to x on the line defined by p1 and p2. + * @private + */ +handler.prototype.computeYInterpolation_ = function(p1, p2, xValue) { + var deltaY = p2[1] - p1[1]; + var deltaX = p2[0] - p1[0]; + var gradient = deltaY / deltaX; + var growth = (xValue - p1[0]) * gradient; + return p1[1] + growth; +}; - // Start from each side of the array to minimize the performance - // needed. - while (idx < series.length - 1 && series[idx][0] < low) { - firstIdx++; - idx++; - } - idx = series.length - 1; - while (idx > 0 && series[idx][0] > high) { - lastIdx--; - idx--; - } +/** + * Helper method that returns the first and the last index of the given series + * that lie inside the given dateWindow. + * + * @param {!Array.<[!number,?number,?]>} series The series in the unified + * data format where series[i] = [x,y,{extras}]. + * @param {!Array.} dateWindow The x-value range to display with + * the format: [min,max]. + * @return {!Array.<[!number,?number,?]>} The samples of the series that + * are in the given date window. + * @private + */ +handler.prototype.getIndexesInWindow_ = function(series, dateWindow) { + var firstIdx = 0, lastIdx = series.length - 1; + if (dateWindow) { + var idx = 0; + var low = dateWindow[0]; + var high = dateWindow[1]; + + // Start from each side of the array to minimize the performance + // needed. + while (idx < series.length - 1 && series[idx][0] < low) { + firstIdx++; + idx++; } - if (firstIdx <= lastIdx) { - return [ firstIdx, lastIdx ]; - } else { - return [ 0, series.length - 1 ]; + idx = series.length - 1; + while (idx > 0 && series[idx][0] > high) { + lastIdx--; + idx--; } - }; - - return handler; + } + if (firstIdx <= lastIdx) { + return [ firstIdx, lastIdx ]; + } else { + return [ 0, series.length - 1 ]; + } }; })(); diff --git a/datahandler/default-fractions.js b/datahandler/default-fractions.js index 8da8e42..35d36eb 100644 --- a/datahandler/default-fractions.js +++ b/datahandler/default-fractions.js @@ -14,7 +14,13 @@ /*global Dygraph:false */ "use strict"; -Dygraph.DataHandlers.DefaultFractionHandler = Dygraph.DataHandler(); +/** + * @extends Dygraph.DataHandlers.DefaultHandler + * @constructor + */ +Dygraph.DataHandlers.DefaultFractionHandler = function() { +}; + var DefaultFractionHandler = Dygraph.DataHandlers.DefaultFractionHandler; DefaultFractionHandler.prototype = new Dygraph.DataHandlers.DefaultHandler(); diff --git a/datahandler/default.js b/datahandler/default.js index 6e6697f..e42b92b 100644 --- a/datahandler/default.js +++ b/datahandler/default.js @@ -14,9 +14,17 @@ /*global Dygraph:false */ "use strict"; -Dygraph.DataHandlers.DefaultHandler = Dygraph.DataHandler(); +/** + * @constructor + * @extends Dygraph.DataHandler + */ +Dygraph.DataHandlers.DefaultHandler = function() { +}; + var DefaultHandler = Dygraph.DataHandlers.DefaultHandler; +DefaultHandler.prototype = new Dygraph.DataHandler(); +/** @inheritDoc */ DefaultHandler.prototype.extractSeries = function(rawData, i, options) { // TODO(danvk): pre-allocate series here. var series = []; @@ -36,6 +44,7 @@ DefaultHandler.prototype.extractSeries = function(rawData, i, options) { return series; }; +/** @inheritDoc */ DefaultHandler.prototype.rollingAverage = function(originalData, rollPeriod, options) { rollPeriod = Math.min(rollPeriod, originalData.length); @@ -68,6 +77,7 @@ DefaultHandler.prototype.rollingAverage = function(originalData, rollPeriod, return rollingData; }; +/** @inheritDoc */ DefaultHandler.prototype.getExtremeYValues = function(series, dateWindow, options) { var minY = null, maxY = null, y; -- 2.7.4