Add dygraph-options.js. Add code to compare behavior. Looks like it's only working...
authorRobert Konigsberg <konigsberg@google.com>
Sun, 18 Nov 2012 00:41:17 +0000 (18:41 -0600)
committerRobert Konigsberg <konigsberg@google.com>
Sun, 18 Nov 2012 00:41:17 +0000 (18:41 -0600)
dygraph-dev.js
dygraph-options.js [new file with mode: 0644]
dygraph.js

index 4ca6bb3..b90796c 100644 (file)
@@ -20,6 +20,7 @@
     "rgbcolor/rgbcolor.js",
     "stacktrace.js",
     "dashed-canvas.js",
+    "dygraph-options.js",
     "dygraph-layout.js",
     "dygraph-canvas.js",
     "dygraph.js",
diff --git a/dygraph-options.js b/dygraph-options.js
new file mode 100644 (file)
index 0000000..562fa24
--- /dev/null
@@ -0,0 +1,118 @@
+/**
+ * @fileoverview DygraphOptions is responsible for parsing and returning information about options.
+ *
+ * Still tightly coupled to Dygraphs, we could remove some of that, you know.
+ */
+
+"use strict";
+
+/*
+ * Interesting member variables:
+ * dygraph_ - the graph.
+ * global - global attributes (common among all graphs, AIUI)
+ * global_user - attributes set by the user
+ * axes
+ * series - { seriesName -> { idx, yAxis, options }
+ * labels - used as mapping from index to series name.
+ */
+
+/**
+ * @constructor
+ *
+ * This parses attributes into an object that can be easily queried.
+ *
+ * @param {Dyraph} dygraph The chart to which these options belong.
+ */
+var DygraphOptions = function(dygraph) {
+  this.dygraph_ = dygraph;
+  this.axes = [];
+  this.series = {};
+
+  // Once these two objects are initialized, you can call find();
+  this.global = this.dygraph_.attrs_;
+  this.global_user = this.dygraph_.user_attrs_ || {};
+
+  // Get a list of series names.
+  this.labels = this.find("labels").slice(1);
+
+  var axisId = 0; // 0-offset; there's always one.
+  // Go through once, add all the series, and for those with {} axis options, add a new axis.
+  for (var idx = 0; idx < this.labels.length; idx++) {
+    var seriesName = this.labels[idx];
+
+    var optionsForSeries = this.global_user[seriesName] || {};
+    var yAxis = 0;
+
+    var axis = optionsForSeries["axis"];
+    if (typeof(axis) == 'object') {
+      yAxis = ++axisId;
+    }
+    this.series[seriesName] = { idx: idx, yAxis: yAxis, options : optionsForSeries };
+  }
+
+  // Go through one more time and assign series to an axis defined by another
+  // series, e.g. { 'Y1: { axis: {} }, 'Y2': { axis: 'Y1' } }
+  for (var idx = 0; idx < this.labels.length; idx++) {
+    var seriesName = this.labels[idx];
+    var optionsForSeries = this.series[seriesName]["options"]; 
+    var axis = optionsForSeries["axis"];
+
+    if (typeof(axis) == 'string') {
+      if (!this.series.hasOwnProperty(axis)) {
+        this.dygraph_.error("Series " + seriesName + " wants to share a y-axis with " +
+                   "series " + axis + ", which does not define its own axis.");
+        return null;
+      }
+      this.series[seriesName].yAxis = this.series[axis].yAxis;
+    }
+  }
+
+  // This doesn't support reading from the 'x' axis, only 'y' and 'y2.
+  // Read from the global "axes" option.
+  if (this.global_user.hasOwnProperty("axes")) {
+    var axis_opts = this.global_user.axes;
+
+    this.axes.push(axis_opts["y"] || {}); 
+    this.axes.push(axis_opts["y2"] || {}); 
+  } else {
+    this.axes.push(axis_opts["y"] || {});  // There has to be at least one axis.
+  }
+};
+
+DygraphOptions.prototype.find = function(name) {
+  if (this.global_user.hasOwnProperty(name)) {
+    return this.global_user[name];
+  }
+  if (this.global.hasOwnProperty(name)) {
+    return this.global[name];
+  }
+  return null;
+}
+
+DygraphOptions.prototype.findForAxis = function(name, axis) {
+
+  var axisIdx = (axis == "y2" || axis == 1) ? 1 : 0;
+
+  var axisOptions = this.axes[axisIdx];
+  if (axisOptions.hasOwnProperty(name)) {
+    return axisOptions[name];
+  }
+  return this.find(name);
+}
+
+DygraphOptions.prototype.findForSeries = function(name, series) {
+  // Honors indexes as series.
+  var seriesName = (typeof(series) == "number") ? this.labels[series] : series;
+
+  if (!this.series.hasOwnProperty(seriesName)) {
+    throw "Unknown series: " + series;
+  }
+
+  var seriesObj = this.series[seriesName];
+  var seriesOptions = seriesObj["options"];
+  if (seriesOptions.hasOwnProperty(name)) {
+    return seriesOptions[name];
+  }
+  return this.findForAxis(name, seriesObj["yAxis"]);
+}
+
index 621ea32..4189750 100644 (file)
@@ -437,6 +437,8 @@ Dygraph.prototype.__init__ = function(div, file, attrs) {
   this.registeredEvents_ = [];
   this.eventListeners_ = {};
 
+  this.attributes_ = new DygraphOptions(this);
+
   // Create the containing DIV and other interactive elements
   this.createInterface_();
 
@@ -568,6 +570,12 @@ Dygraph.prototype.attr_ = function(name, seriesName) {
   }
 // </REMOVE_FOR_COMBINED>
 
+  // Building an array which we peruse in backwards order to find the correct value.
+  // Options are checked in this order:
+  // series, axis, user attrs, global attrs.
+  // TODO(konigsberg): Can this be made faster by starting with the series and working outward,
+  // rather than building an array?
+
   var sources = [];
   sources.push(this.attrs_);
   if (this.user_attrs_) {
@@ -576,6 +584,8 @@ Dygraph.prototype.attr_ = function(name, seriesName) {
       if (this.user_attrs_.hasOwnProperty(seriesName)) {
         sources.push(this.user_attrs_[seriesName]);
       }
+
+      // TODO(konigsberg): This special case ought to be documented.
       if (seriesName === this.highlightSet_ &&
           this.user_attrs_.hasOwnProperty('highlightSeriesOpts')) {
         sources.push(this.user_attrs_.highlightSeriesOpts);
@@ -591,7 +601,15 @@ Dygraph.prototype.attr_ = function(name, seriesName) {
       break;
     }
   }
-  return ret;
+
+  var computedValue = seriesName ? this.attributes_.findForSeries(name, seriesName) : this.attributes_.find(name);
+
+  if (ret !== computedValue) {
+    console.log("Mismatch", name, seriesName, ret, computedValue);
+  } else {
+    console.log("Match", name, seriesName, ret, computedValue);
+  }
+  return computedValue;
 };
 
 /**
@@ -2179,7 +2197,8 @@ Dygraph.prototype.predraw_ = function() {
   // rolling averages.
   this.rolledSeries_ = [null];  // x-axis is the first series and it's special
   for (var i = 1; i < this.numColumns(); i++) {
-    var logScale = this.attr_('logscale', i); // TODO(klausw): this looks wrong
+    // var logScale = this.attr_('logscale', i); // TODO(klausw): this looks wrong // konigsberg thinks so too.
+    var logScale = this.attr_('logscale');
     var series = this.extractSeries_(this.rawData_, i, logScale);
     series = this.rollingAverage(series, this.rollPeriod_);
     this.rolledSeries_.push(series);