Cleanup from DataHandler change.
authorDan Vanderkam <danvdk@gmail.com>
Wed, 28 Aug 2013 04:00:57 +0000 (00:00 -0400)
committerDan Vanderkam <danvdk@gmail.com>
Wed, 28 Aug 2013 04:00:57 +0000 (00:00 -0400)
Highlights:
- Move from the string-based DataHandler registration system to plain
  old JS symbols. This gets us some extra sanity checking from the
  JS interpretor and linter.
- Standardize module pattern and indentation across datahandler/*.js.
- Document dataHandler option.

datahandler/bars-custom.js
datahandler/bars-error.js
datahandler/bars-fractions.js
datahandler/bars.js
datahandler/datahandler.js
datahandler/default-fractions.js
datahandler/default.js
dygraph-options-reference.js
dygraph.js

index e77d746..37255e5 100644 (file)
  */
 
 (function() {
-  /*global Dygraph:false */
-  "use strict";
 
-  var CustomBarsHandler = Dygraph.DataHandler();
-  CustomBarsHandler.prototype = Dygraph.DataHandlers.createHandler("bars");
-  Dygraph.DataHandlers.registerHandler("bars-custom", CustomBarsHandler);
-  // customBars
-  CustomBarsHandler.prototype.extractSeries = function(rawData, i, options) {
-    // TODO(danvk): pre-allocate series here.
-    var series = [];
-    var x, y, point;
-    var logScale = options.get('logscale');
-    for ( var j = 0; j < rawData.length; j++) {
-      x = rawData[j][0];
-      point = rawData[j][i];
-      if (logScale && point !== null) {
-        // On the log scale, points less than zero do not exist.
-        // This will create a gap in the chart.
-        if (point[0] <= 0 || point[1] <= 0 || point[2] <= 0) {
-          point = null;
-        }
+/*global Dygraph:false */
+"use strict";
+
+Dygraph.DataHandlers.CustomBarsHandler = Dygraph.DataHandler();
+var CustomBarsHandler = Dygraph.DataHandlers.CustomBarsHandler;
+CustomBarsHandler.prototype = new Dygraph.DataHandlers.BarsHandler();
+
+// customBars
+CustomBarsHandler.prototype.extractSeries = function(rawData, i, options) {
+  // TODO(danvk): pre-allocate series here.
+  var series = [];
+  var x, y, point;
+  var logScale = options.get('logscale');
+  for ( var j = 0; j < rawData.length; j++) {
+    x = rawData[j][0];
+    point = rawData[j][i];
+    if (logScale && point !== null) {
+      // On the log scale, points less than zero do not exist.
+      // This will create a gap in the chart.
+      if (point[0] <= 0 || point[1] <= 0 || point[2] <= 0) {
+        point = null;
       }
-      // Extract to the unified data format.
-      if (point !== null) {
-        y = point[1];
-        if (y !== null && !isNaN(y)) {
-          series.push([ x, y, [ point[0], point[2] ] ]);
-        } else {
-          series.push([ x, y, [ y, y ] ]);
-        }
+    }
+    // Extract to the unified data format.
+    if (point !== null) {
+      y = point[1];
+      if (y !== null && !isNaN(y)) {
+        series.push([ x, y, [ point[0], point[2] ] ]);
       } else {
-        series.push([ x, null, [ null, null ] ]);
+        series.push([ x, y, [ y, y ] ]);
       }
+    } else {
+      series.push([ x, null, [ null, null ] ]);
     }
-    return series;
-  };
+  }
+  return series;
+};
 
-  CustomBarsHandler.prototype.rollingAverage = function(originalData, rollPeriod,
-      options) {
-    rollPeriod = Math.min(rollPeriod, originalData.length);
-    var rollingData = [];
-    var y, low, high, mid,count, i, extremes;
+CustomBarsHandler.prototype.rollingAverage = function(originalData, rollPeriod,
+    options) {
+  rollPeriod = Math.min(rollPeriod, originalData.length);
+  var rollingData = [];
+  var y, low, high, mid,count, i, extremes;
 
-    low = 0;
-    mid = 0;
-    high = 0;
-    count = 0;
-    for (i = 0; i < originalData.length; i++) {
-      y = originalData[i][1];
-      extremes = originalData[i][2];
-      rollingData[i] = originalData[i];
+  low = 0;
+  mid = 0;
+  high = 0;
+  count = 0;
+  for (i = 0; i < originalData.length; i++) {
+    y = originalData[i][1];
+    extremes = originalData[i][2];
+    rollingData[i] = originalData[i];
 
-      if (y !== null && !isNaN(y)) {
-        low += extremes[0];
-        mid += y;
-        high += extremes[1];
-        count += 1;
-      }
-      if (i - rollPeriod >= 0) {
-        var prev = originalData[i - rollPeriod];
-        if (prev[1] !== null && !isNaN(prev[1])) {
-          low -= prev[2][0];
-          mid -= prev[1];
-          high -= prev[2][1];
-          count -= 1;
-        }
-      }
-      if (count) {
-        rollingData[i] = [
-            originalData[i][0],
-            1.0 * mid / count, 
-            [ 1.0 * low / count,
-              1.0 * high / count ] ];
-      } else {
-        rollingData[i] = [ originalData[i][0], null, [ null, null ] ];
+    if (y !== null && !isNaN(y)) {
+      low += extremes[0];
+      mid += y;
+      high += extremes[1];
+      count += 1;
+    }
+    if (i - rollPeriod >= 0) {
+      var prev = originalData[i - rollPeriod];
+      if (prev[1] !== null && !isNaN(prev[1])) {
+        low -= prev[2][0];
+        mid -= prev[1];
+        high -= prev[2][1];
+        count -= 1;
       }
     }
+    if (count) {
+      rollingData[i] = [
+          originalData[i][0],
+          1.0 * mid / count, 
+          [ 1.0 * low / count,
+            1.0 * high / count ] ];
+    } else {
+      rollingData[i] = [ originalData[i][0], null, [ null, null ] ];
+    }
+  }
+
+  return rollingData;
+};
 
-    return rollingData;
-  };
 })();
index ff4ba92..6da2fc5 100644 (file)
  */
 
 (function() {
-  /*global Dygraph:false */
-  "use strict";
 
-  var ErrorBarsHandler = Dygraph.DataHandler();
-  ErrorBarsHandler.prototype = Dygraph.DataHandlers.createHandler("bars");
-  Dygraph.DataHandlers.registerHandler("bars-error", ErrorBarsHandler);
-  // errorBars
-  ErrorBarsHandler.prototype.extractSeries = function(rawData, i, options) {
-    // TODO(danvk): pre-allocate series here.
-    var series = [];
-    var x, y, variance, point;
-    var sigma = options.get("sigma");
-    var logScale = options.get('logscale');
-    for ( var j = 0; j < rawData.length; j++) {
-      x = rawData[j][0];
-      point = rawData[j][i];
-      if (logScale && point !== null) {
-        // On the log scale, points less than zero do not exist.
-        // This will create a gap in the chart.
-        if (point[0] <= 0 || point[0] - sigma * point[1] <= 0) {
-          point = null;
-        }
+/*global Dygraph:false */
+"use strict";
+
+Dygraph.DataHandlers.ErrorBarsHandler = Dygraph.DataHandler();
+var ErrorBarsHandler = Dygraph.DataHandlers.ErrorBarsHandler;
+ErrorBarsHandler.prototype = new Dygraph.DataHandlers.BarsHandler();
+
+// errorBars
+ErrorBarsHandler.prototype.extractSeries = function(rawData, i, options) {
+  // TODO(danvk): pre-allocate series here.
+  var series = [];
+  var x, y, variance, point;
+  var sigma = options.get("sigma");
+  var logScale = options.get('logscale');
+  for ( var j = 0; j < rawData.length; j++) {
+    x = rawData[j][0];
+    point = rawData[j][i];
+    if (logScale && point !== null) {
+      // On the log scale, points less than zero do not exist.
+      // This will create a gap in the chart.
+      if (point[0] <= 0 || point[0] - sigma * point[1] <= 0) {
+        point = null;
       }
-      // Extract to the unified data format.
-      if (point !== null) {
-        y = point[0];
-        if (y !== null && !isNaN(y)) {
-          variance = sigma * point[1];
-          // preserve original error value in extras for further
-          // filtering
-          series.push([ x, y, [ y - variance, y + variance, point[1] ] ]);
-        } else {
-          series.push([ x, y, [ y, y, y ] ]);
-        }
+    }
+    // Extract to the unified data format.
+    if (point !== null) {
+      y = point[0];
+      if (y !== null && !isNaN(y)) {
+        variance = sigma * point[1];
+        // preserve original error value in extras for further
+        // filtering
+        series.push([ x, y, [ y - variance, y + variance, point[1] ] ]);
       } else {
-        series.push([ x, null, [ null, null, null ] ]);
+        series.push([ x, y, [ y, y, y ] ]);
       }
+    } else {
+      series.push([ x, null, [ null, null, null ] ]);
     }
-    return series;
-  };
+  }
+  return series;
+};
 
-  ErrorBarsHandler.prototype.rollingAverage = function(originalData, rollPeriod,
-      options) {
-    rollPeriod = Math.min(rollPeriod, originalData.length);
-    var rollingData = [];
-    var sigma = options.get("sigma");
+ErrorBarsHandler.prototype.rollingAverage = function(originalData, rollPeriod,
+    options) {
+  rollPeriod = Math.min(rollPeriod, originalData.length);
+  var rollingData = [];
+  var sigma = options.get("sigma");
 
-    var i, j, y, v, sum, num_ok, stddev, variance, value;
+  var i, j, y, v, sum, num_ok, stddev, variance, value;
 
-    // Calculate the rolling average for the first rollPeriod - 1 points
-    // where there is not enough data to roll over the full number of points
-    for (i = 0; i < originalData.length; i++) {
-      sum = 0;
-      variance = 0;
-      num_ok = 0;
-      for (j = Math.max(0, i - rollPeriod + 1); j < i + 1; j++) {
-        y = originalData[j][1];
-        if (y === null || isNaN(y))
-          continue;
-        num_ok++;
-        sum += y;
-        variance += Math.pow(originalData[j][2][2], 2);
-      }
-      if (num_ok) {
-        stddev = Math.sqrt(variance) / num_ok;
-        value = sum / num_ok;
-        rollingData[i] = [ originalData[i][0], value,
-            [value - sigma * stddev, value + sigma * stddev] ];
-      } else {
-        // This explicitly preserves NaNs to aid with "independent
-        // series".
-        // See testRollingAveragePreservesNaNs.
-        v = (rollPeriod == 1) ? originalData[i][1] : null;
-        rollingData[i] = [ originalData[i][0], v, [ v, v ] ];
-      }
+  // Calculate the rolling average for the first rollPeriod - 1 points
+  // where there is not enough data to roll over the full number of points
+  for (i = 0; i < originalData.length; i++) {
+    sum = 0;
+    variance = 0;
+    num_ok = 0;
+    for (j = Math.max(0, i - rollPeriod + 1); j < i + 1; j++) {
+      y = originalData[j][1];
+      if (y === null || isNaN(y))
+        continue;
+      num_ok++;
+      sum += y;
+      variance += Math.pow(originalData[j][2][2], 2);
     }
+    if (num_ok) {
+      stddev = Math.sqrt(variance) / num_ok;
+      value = sum / num_ok;
+      rollingData[i] = [ originalData[i][0], value,
+          [value - sigma * stddev, value + sigma * stddev] ];
+    } else {
+      // This explicitly preserves NaNs to aid with "independent
+      // series".
+      // See testRollingAveragePreservesNaNs.
+      v = (rollPeriod == 1) ? originalData[i][1] : null;
+      rollingData[i] = [ originalData[i][0], v, [ v, v ] ];
+    }
+  }
+
+  return rollingData;
+};
 
-    return rollingData;
-  };
 })();
index 88c5ca6..28c0491 100644 (file)
  */
 
 (function() {
-  /*global Dygraph:false */
-  "use strict";
 
-  var FractionsBarsHandler = Dygraph.DataHandler();
-  FractionsBarsHandler.prototype = Dygraph.DataHandlers.createHandler("bars");
-  Dygraph.DataHandlers.registerHandler("bars-fractions", FractionsBarsHandler);
-  // errorBars
-  FractionsBarsHandler.prototype.extractSeries = function(rawData, i, options) {
-    // TODO(danvk): pre-allocate series here.
-    var series = [];
-    var x, y, point, num, den, value, stddev, variance;
-    var mult = 100.0;
-    var sigma = options.get("sigma");
-    var logScale = options.get('logscale');
-    for ( var j = 0; j < rawData.length; j++) {
-      x = rawData[j][0];
-      point = rawData[j][i];
-      if (logScale && point !== null) {
-        // On the log scale, points less than zero do not exist.
-        // This will create a gap in the chart.
-        if (point[0] <= 0 || point[1] <= 0) {
-          point = null;
-        }
+/*global Dygraph:false */
+"use strict";
+
+Dygraph.DataHandlers.FractionsBarsHandler = Dygraph.DataHandler();
+var FractionsBarsHandler = Dygraph.DataHandlers.FractionsBarsHandler;
+FractionsBarsHandler.prototype = new Dygraph.DataHandlers.BarsHandler();
+
+// errorBars
+FractionsBarsHandler.prototype.extractSeries = function(rawData, i, options) {
+  // TODO(danvk): pre-allocate series here.
+  var series = [];
+  var x, y, point, num, den, value, stddev, variance;
+  var mult = 100.0;
+  var sigma = options.get("sigma");
+  var logScale = options.get('logscale');
+  for ( var j = 0; j < rawData.length; j++) {
+    x = rawData[j][0];
+    point = rawData[j][i];
+    if (logScale && point !== null) {
+      // On the log scale, points less than zero do not exist.
+      // This will create a gap in the chart.
+      if (point[0] <= 0 || point[1] <= 0) {
+        point = null;
       }
-      // Extract to the unified data format.
-      if (point !== null) {
-        num = point[0];
-        den = point[1];
-        if (num !== null && !isNaN(num)) {
-          value = den ? num / den : 0.0;
-          stddev = den ? sigma * Math.sqrt(value * (1 - value) / den) : 1.0;
-          variance = mult * stddev;
-          y = mult * value;
-          // preserve original values in extras for further filtering
-          series.push([ x, y, [ y - variance, y + variance, num, den ] ]);
-        } else {
-          series.push([ x, num, [ num, num, num, den ] ]);
-        }
+    }
+    // Extract to the unified data format.
+    if (point !== null) {
+      num = point[0];
+      den = point[1];
+      if (num !== null && !isNaN(num)) {
+        value = den ? num / den : 0.0;
+        stddev = den ? sigma * Math.sqrt(value * (1 - value) / den) : 1.0;
+        variance = mult * stddev;
+        y = mult * value;
+        // preserve original values in extras for further filtering
+        series.push([ x, y, [ y - variance, y + variance, num, den ] ]);
       } else {
-        series.push([ x, null, [ null, null, null, null ] ]);
+        series.push([ x, num, [ num, num, num, den ] ]);
       }
+    } else {
+      series.push([ x, null, [ null, null, null, null ] ]);
     }
-    return series;
-  };
+  }
+  return series;
+};
 
-  FractionsBarsHandler.prototype.rollingAverage = function(originalData, rollPeriod,
-      options) {
-    rollPeriod = Math.min(rollPeriod, originalData.length);
-    var rollingData = [];
-    var sigma = options.get("sigma");
-    var wilsonInterval = options.get("wilsonInterval");
+FractionsBarsHandler.prototype.rollingAverage = function(originalData, rollPeriod,
+    options) {
+  rollPeriod = Math.min(rollPeriod, originalData.length);
+  var rollingData = [];
+  var sigma = options.get("sigma");
+  var wilsonInterval = options.get("wilsonInterval");
 
-    var low, high, i, stddev;
-    var num = 0;
-    var den = 0; // numerator/denominator
-    var mult = 100.0;
-    for (i = 0; i < originalData.length; i++) {
-      num += originalData[i][2][2];
-      den += originalData[i][2][3];
-      if (i - rollPeriod >= 0) {
-        num -= originalData[i - rollPeriod][2][2];
-        den -= originalData[i - rollPeriod][2][3];
-      }
+  var low, high, i, stddev;
+  var num = 0;
+  var den = 0; // numerator/denominator
+  var mult = 100.0;
+  for (i = 0; i < originalData.length; i++) {
+    num += originalData[i][2][2];
+    den += originalData[i][2][3];
+    if (i - rollPeriod >= 0) {
+      num -= originalData[i - rollPeriod][2][2];
+      den -= originalData[i - rollPeriod][2][3];
+    }
 
-      var date = originalData[i][0];
-      var value = den ? num / den : 0.0;
-      if (wilsonInterval) {
-        // For more details on this confidence interval, see:
-        // http://en.wikipedia.org/wiki/Binomial_confidence_interval
-        if (den) {
-          var p = value < 0 ? 0 : value, n = den;
-          var pm = sigma * Math.sqrt(p * (1 - p) / n + sigma * sigma / (4 * n * n));
-          var denom = 1 + sigma * sigma / den;
-          low = (p + sigma * sigma / (2 * den) - pm) / denom;
-          high = (p + sigma * sigma / (2 * den) + pm) / denom;
-          rollingData[i] = [ date, p * mult,
-              [ low * mult, high * mult ] ];
-        } else {
-          rollingData[i] = [ date, 0, [ 0, 0 ] ];
-        }
+    var date = originalData[i][0];
+    var value = den ? num / den : 0.0;
+    if (wilsonInterval) {
+      // For more details on this confidence interval, see:
+      // http://en.wikipedia.org/wiki/Binomial_confidence_interval
+      if (den) {
+        var p = value < 0 ? 0 : value, n = den;
+        var pm = sigma * Math.sqrt(p * (1 - p) / n + sigma * sigma / (4 * n * n));
+        var denom = 1 + sigma * sigma / den;
+        low = (p + sigma * sigma / (2 * den) - pm) / denom;
+        high = (p + sigma * sigma / (2 * den) + pm) / denom;
+        rollingData[i] = [ date, p * mult,
+            [ low * mult, high * mult ] ];
       } else {
-        stddev = den ? sigma * Math.sqrt(value * (1 - value) / den) : 1.0;
-        rollingData[i] = [ date, mult * value, 
-                           [ mult * (value - stddev), mult * (value + stddev) ] ];
+        rollingData[i] = [ date, 0, [ 0, 0 ] ];
       }
+    } else {
+      stddev = den ? sigma * Math.sqrt(value * (1 - value) / den) : 1.0;
+      rollingData[i] = [ date, mult * value, 
+                         [ mult * (value - stddev), mult * (value + stddev) ] ];
     }
+  }
+
+  return rollingData;
+};
 
-    return rollingData;
-  };
 })();
index 5b84b69..914ee27 100644 (file)
  */
 
 (function() {
-  /*global Dygraph:false */
-  /*global DygraphLayout:false */
-  "use strict";
-
-  var BarsHandler = Dygraph.DataHandler();
-  Dygraph.DataHandlers.registerHandler("bars", BarsHandler);
-  // errorBars
-  BarsHandler.prototype.extractSeries = function(rawData, i, options) {
-    // Not implemented here must be extended
-  };
-
-  BarsHandler.prototype.rollingAverage =  function(originalData, rollPeriod,
-      options) {
-    // Not implemented here, must be extended.
-  };
-
-  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]);
-    }
-  };
-
-  BarsHandler.prototype.getExtremeYValues = function(series, dateWindow, options) {
-    var minY = null, maxY = null, y;
-
-    var firstIdx = 0;
-    var lastIdx = series.length - 1;
-
-    for ( var j = firstIdx; j <= lastIdx; j++) {
-      y = series[j][1];
-      if (y === null || isNaN(y)) continue;
-
-      var low = series[j][2][0];
-      var high = series[j][2][1];
-
-      if (low > y) low = y; // this can happen with custom bars,
-      if (high < y) high = y; // e.g. in tests/custom-bars.html
-
-      if (maxY === null || high > maxY) maxY = high;
-      if (minY === null || low < minY) minY = low;
-    }
-
-    return [ minY, maxY ];
-  };
-
-  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);
-    }
-  };
+
+/*global Dygraph:false */
+/*global DygraphLayout:false */
+"use strict";
+
+Dygraph.DataHandlers.BarsHandler = Dygraph.DataHandler();
+var BarsHandler = Dygraph.DataHandlers.BarsHandler;
+
+// errorBars
+BarsHandler.prototype.extractSeries = function(rawData, i, options) {
+  // Not implemented here must be extended
+};
+
+BarsHandler.prototype.rollingAverage =
+    function(originalData, rollPeriod, options) {
+  // Not implemented here, must be extended.
+};
+
+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]);
+  }
+};
+
+BarsHandler.prototype.getExtremeYValues = function(series, dateWindow, options) {
+  var minY = null, maxY = null, y;
+
+  var firstIdx = 0;
+  var lastIdx = series.length - 1;
+
+  for ( var j = firstIdx; j <= lastIdx; j++) {
+    y = series[j][1];
+    if (y === null || isNaN(y)) continue;
+
+    var low = series[j][2][0];
+    var high = series[j][2][1];
+
+    if (low > y) low = y; // this can happen with custom bars,
+    if (high < y) high = y; // e.g. in tests/custom-bars.html
+
+    if (maxY === null || high > maxY) maxY = high;
+    if (minY === null || low < minY) minY = low;
+  }
+
+  return [ minY, maxY ];
+};
+
+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);
+  }
+};
+
 })();
index d08f7a7..5ed0112 100644 (file)
  * errorBar / customBar: [x, yVal, [yTopVariance, yBottomVariance] ]
  * 
  */
-/*jshint globalstrict: true */
 /*global Dygraph:false */
 /*global DygraphLayout:false */
+
+(function() {
+
 "use strict";
 
 /**
  * A collection of functions to create and retrieve data handlers.
+ * @type {Object.<!Dygraph.DataHandler>}
  */
 Dygraph.DataHandlers = {};
 
 /**
- * All registered data handlers are stored here.
- * 
- * @private
- */
-Dygraph.DataHandlers.handlers_ = {};
-
-/**
- * @param name {!string} The name the data handler should be registered to.
- *          Registers a data handler by the given name and makes it publicly
- *          accessible.
- * @param handler {!Dygraph.DataHandler} DataHandler implementation which must be an
- *          instance of Dygraph.DataHandler.
- * @public
- */
-Dygraph.DataHandlers.registerHandler = function(name, handler) {
-  if (!handler instanceof Dygraph.DataHandler) {
-    throw ("the handler must be a prototype of Dygraph.DataHandler");
-  }
-  Dygraph.DataHandlers.handlers_[name] = handler;
-};
-
-/**
- * Returns the data handler registered to the given name.
- * Note this is the data handler constructor method.
- * 
- * @param name {!string} The name, the handler was registered to.
- * @returns {Dygraph.DataHandler} The data handler constructor.
- * @public
- */
-Dygraph.DataHandlers.getHandler = function(name) {
-  return Dygraph.DataHandlers.handlers_[name];
-};
-
-/**
- * Returns the cunstructed data handler registered to the given name.
- * 
- * @param name {!string} The name, the handler was registered to.
- * @returns {Dygraph.DataHandler} A constructed instance of the data handler.
- * @public
- */
-Dygraph.DataHandlers.createHandler = function(name) {
-  return new Dygraph.DataHandlers.handlers_[name]();
-};
-
-/**
  * 
  * 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
- * 
- * @class
  */
 Dygraph.DataHandler = function () {
   /**
@@ -303,3 +259,5 @@ Dygraph.DataHandler = function () {
 
   return handler;
 };
+
+})();
index 7e234b0..8da8e42 100644 (file)
  */
 
 (function() {
-  /*global Dygraph:false */
-  "use strict";
 
-  var DefaultFractionHandler = Dygraph.DataHandler();
-  DefaultFractionHandler.prototype = Dygraph.DataHandlers.createHandler("default");
-  Dygraph.DataHandlers.registerHandler("default-fractions", DefaultFractionHandler);
+/*global Dygraph:false */
+"use strict";
 
-  DefaultFractionHandler.prototype.extractSeries = function(rawData, i, options) {
-    // TODO(danvk): pre-allocate series here.
-    var series = [];
-    var x, y, point, num, den, value;
-    var mult = 100.0;
-    var logScale = options.get('logscale');
-    for ( var j = 0; j < rawData.length; j++) {
-      x = rawData[j][0];
-      point = rawData[j][i];
-      if (logScale && point !== null) {
-        // On the log scale, points less than zero do not exist.
-        // This will create a gap in the chart.
-        if (point[0] <= 0 || point[1] <= 0) {
-          point = null;
-        }
+Dygraph.DataHandlers.DefaultFractionHandler = Dygraph.DataHandler();
+var DefaultFractionHandler = Dygraph.DataHandlers.DefaultFractionHandler;
+DefaultFractionHandler.prototype = new Dygraph.DataHandlers.DefaultHandler();
+
+DefaultFractionHandler.prototype.extractSeries = function(rawData, i, options) {
+  // TODO(danvk): pre-allocate series here.
+  var series = [];
+  var x, y, point, num, den, value;
+  var mult = 100.0;
+  var logScale = options.get('logscale');
+  for ( var j = 0; j < rawData.length; j++) {
+    x = rawData[j][0];
+    point = rawData[j][i];
+    if (logScale && point !== null) {
+      // On the log scale, points less than zero do not exist.
+      // This will create a gap in the chart.
+      if (point[0] <= 0 || point[1] <= 0) {
+        point = null;
       }
-      // Extract to the unified data format.
-      if (point !== null) {
-        num = point[0];
-        den = point[1];
-        if (num !== null && !isNaN(num)) {
-          value = den ? num / den : 0.0;
-          y = mult * value;
-          // preserve original values in extras for further filtering
-          series.push([ x, y, [ num, den ] ]);
-        } else {
-          series.push([ x, num, [ num, den ] ]);
-        }
+    }
+    // Extract to the unified data format.
+    if (point !== null) {
+      num = point[0];
+      den = point[1];
+      if (num !== null && !isNaN(num)) {
+        value = den ? num / den : 0.0;
+        y = mult * value;
+        // preserve original values in extras for further filtering
+        series.push([ x, y, [ num, den ] ]);
       } else {
-        series.push([ x, null, [ null, null ] ]);
+        series.push([ x, num, [ num, den ] ]);
       }
+    } else {
+      series.push([ x, null, [ null, null ] ]);
     }
-    return series;
-  };
-
-  DefaultFractionHandler.prototype.rollingAverage = function(originalData, rollPeriod,
-      options) {
-    rollPeriod = Math.min(rollPeriod, originalData.length);
-    var rollingData = [];
+  }
+  return series;
+};
 
-    var i;
-    var num = 0;
-    var den = 0; // numerator/denominator
-    var mult = 100.0;
-    for (i = 0; i < originalData.length; i++) {
-      num += originalData[i][2][0];
-      den += originalData[i][2][1];
-      if (i - rollPeriod >= 0) {
-        num -= originalData[i - rollPeriod][2][0];
-        den -= originalData[i - rollPeriod][2][1];
-      }
+DefaultFractionHandler.prototype.rollingAverage = function(originalData, rollPeriod,
+    options) {
+  rollPeriod = Math.min(rollPeriod, originalData.length);
+  var rollingData = [];
 
-      var date = originalData[i][0];
-      var value = den ? num / den : 0.0;
-      rollingData[i] = [ date, mult * value ];
+  var i;
+  var num = 0;
+  var den = 0; // numerator/denominator
+  var mult = 100.0;
+  for (i = 0; i < originalData.length; i++) {
+    num += originalData[i][2][0];
+    den += originalData[i][2][1];
+    if (i - rollPeriod >= 0) {
+      num -= originalData[i - rollPeriod][2][0];
+      den -= originalData[i - rollPeriod][2][1];
     }
 
-    return rollingData;
-  };
+    var date = originalData[i][0];
+    var value = den ? num / den : 0.0;
+    rollingData[i] = [ date, mult * value ];
+  }
+
+  return rollingData;
+};
+
 })();
index 79adcb5..6e6697f 100644 (file)
  */
 
 (function() {
-  /*global Dygraph:false */
-  "use strict";
 
-  var DefaultHandler = Dygraph.DataHandler();
-  Dygraph.DataHandlers.registerHandler("default", DefaultHandler);
+/*global Dygraph:false */
+"use strict";
 
-  DefaultHandler.prototype.extractSeries = function(rawData, i, options) {
-    // TODO(danvk): pre-allocate series here.
-    var series = [];
-    var logScale = options.get('logscale');
-    for ( var j = 0; j < rawData.length; j++) {
-      var x = rawData[j][0];
-      var point = rawData[j][i];
-      if (logScale) {
-        // On the log scale, points less than zero do not exist.
-        // This will create a gap in the chart.
-        if (point <= 0) {
-          point = null;
-        }
+Dygraph.DataHandlers.DefaultHandler = Dygraph.DataHandler();
+var DefaultHandler = Dygraph.DataHandlers.DefaultHandler;
+
+DefaultHandler.prototype.extractSeries = function(rawData, i, options) {
+  // TODO(danvk): pre-allocate series here.
+  var series = [];
+  var logScale = options.get('logscale');
+  for ( var j = 0; j < rawData.length; j++) {
+    var x = rawData[j][0];
+    var point = rawData[j][i];
+    if (logScale) {
+      // On the log scale, points less than zero do not exist.
+      // This will create a gap in the chart.
+      if (point <= 0) {
+        point = null;
       }
-      series.push([ x, point ]);
     }
-    return series;
-  };
+    series.push([ x, point ]);
+  }
+  return series;
+};
 
-  DefaultHandler.prototype.rollingAverage = function(originalData, rollPeriod,
-      options) {
-    rollPeriod = Math.min(rollPeriod, originalData.length);
-    var rollingData = [];
+DefaultHandler.prototype.rollingAverage = function(originalData, rollPeriod,
+    options) {
+  rollPeriod = Math.min(rollPeriod, originalData.length);
+  var rollingData = [];
 
-    var i, j, y, sum, num_ok;
-    // Calculate the rolling average for the first rollPeriod - 1 points
-    // where
-    // there is not enough data to roll over the full number of points
-    if (rollPeriod == 1) {
-      return originalData;
+  var i, j, y, sum, num_ok;
+  // Calculate the rolling average for the first rollPeriod - 1 points
+  // where
+  // there is not enough data to roll over the full number of points
+  if (rollPeriod == 1) {
+    return originalData;
+  }
+  for (i = 0; i < originalData.length; i++) {
+    sum = 0;
+    num_ok = 0;
+    for (j = Math.max(0, i - rollPeriod + 1); j < i + 1; j++) {
+      y = originalData[j][1];
+      if (y === null || isNaN(y))
+        continue;
+      num_ok++;
+      sum += originalData[j][1];
     }
-    for (i = 0; i < originalData.length; i++) {
-      sum = 0;
-      num_ok = 0;
-      for (j = Math.max(0, i - rollPeriod + 1); j < i + 1; j++) {
-        y = originalData[j][1];
-        if (y === null || isNaN(y))
-          continue;
-        num_ok++;
-        sum += originalData[j][1];
-      }
-      if (num_ok) {
-        rollingData[i] = [ originalData[i][0], sum / num_ok ];
-      } else {
-        rollingData[i] = [ originalData[i][0], null ];
-      }
+    if (num_ok) {
+      rollingData[i] = [ originalData[i][0], sum / num_ok ];
+    } else {
+      rollingData[i] = [ originalData[i][0], null ];
     }
+  }
 
-    return rollingData;
-  };
+  return rollingData;
+};
 
-  DefaultHandler.prototype.getExtremeYValues = function(series, dateWindow,
-      options) {
-    var minY = null, maxY = null, y;
-    var firstIdx = 0, lastIdx = series.length - 1;
+DefaultHandler.prototype.getExtremeYValues = function(series, dateWindow,
+    options) {
+  var minY = null, maxY = null, y;
+  var firstIdx = 0, lastIdx = series.length - 1;
 
-    for ( var j = firstIdx; j <= lastIdx; j++) {
-      y = series[j][1];
-      if (y === null || isNaN(y))
-        continue;
-      if (maxY === null || y > maxY) {
-        maxY = y;
-      }
-      if (minY === null || y < minY) {
-        minY = y;
-      }
+  for ( var j = firstIdx; j <= lastIdx; j++) {
+    y = series[j][1];
+    if (y === null || isNaN(y))
+      continue;
+    if (maxY === null || y > maxY) {
+      maxY = y;
     }
-    return [ minY, maxY ];
-  };
+    if (minY === null || y < minY) {
+      minY = y;
+    }
+  }
+  return [ minY, maxY ];
+};
+
 })();
index c952072..6220750 100644 (file)
@@ -802,7 +802,13 @@ Dygraph.OPTIONS_REFERENCE =  // <JSON>
     "default": "[]",
     "labels": ["Configuration"],
     "type": "Array<plugin>",
-    "description": "Defines per-graph plug-ins. Useful for per-graph customization"
+    "description": "Defines per-graph plugins. Useful for per-graph customization"
+  },
+  "dataHandler": {
+    "default": "(depends on data)",
+    "labels": ["Data"],
+    "type": "Dygraph.DataHandler",
+    "description": "Custom DataHandler. This is an advanced customization. See http://bit.ly/151E7Aq."
   }
 }
 ;  // </JSON>
index 48475ef..cd9f147 100644 (file)
@@ -2153,29 +2153,27 @@ Dygraph.prototype.addXTicks_ = function() {
 };
 
 /**
+ * Returns the correct handler class for the currently set options.
  * @private
- * Returns the correct handler ID for the currently set options. 
- * The actual handler may then be retrieved using the
- * Dygraph.DataHandlers.getHandler() method.
- */
-Dygraph.prototype.getHandlerId_ = function() {
-  var handlerId;
-  if (this.attr_("dataHandlerId")) {
-    handlerId =  this.attr_("dataHandlerId");
-  } else if (this.fractions_){
-    if (this.attr_("errorBars")) {
-      handlerId = "bars-fractions";
+ */
+Dygraph.prototype.getHandlerClass_ = function() {
+  var handlerClass;
+  if (this.attr_('dataHandler')) {
+    handlerClass =  this.attr_('dataHandler');
+  } else if (this.fractions_) {
+    if (this.attr_('errorBars')) {
+      handlerClass = Dygraph.DataHandlers.FractionsBarsHandler;
     } else {
-      handlerId = "default-fractions";
+      handlerClass = Dygraph.DataHandlers.DefaultFractionHandler;
     }
-  } else if (this.attr_("customBars")) {
-    handlerId = "bars-custom";
-  } else if (this.attr_("errorBars")) {
-    handlerId = "bars-error";
+  } else if (this.attr_('customBars')) {
+    handlerClass = Dygraph.DataHandlers.CustomBarsHandler;
+  } else if (this.attr_('errorBars')) {
+    handlerClass = Dygraph.DataHandlers.ErrorBarsHandler;
   } else {
-    handlerId = "default";
+    handlerClass = Dygraph.DataHandlers.DefaultHandler;
   }
-  return handlerId;
+  return handlerClass;
 };
 
 /**
@@ -2190,7 +2188,7 @@ Dygraph.prototype.predraw_ = function() {
   var start = new Date();
   
   // Create the correct dataHandler
-  this.dataHandler_ = new (Dygraph.DataHandlers.getHandler(this.getHandlerId_()))();
+  this.dataHandler_ = new (this.getHandlerClass_())();
 
   this.layout_.computePlotArea();