axisLabelFontSize can now be configured per-axis.
authorRobert Konigsberg <konigsberg@gmail.com>
Mon, 31 Dec 2012 18:27:14 +0000 (13:27 -0500)
committerRobert Konigsberg <konigsberg@gmail.com>
Mon, 31 Dec 2012 18:27:14 +0000 (13:27 -0500)
auto_tests/tests/axis_labels.js
dygraph-options.js
dygraph.js
experimental/palette/options.js
plugins/axes.js

index 00f3913..98f48bb 100644 (file)
@@ -577,6 +577,53 @@ AxisLabelsTestCase.prototype.testIncludeZero = function() {
   assertEquals(['500','600','700','800','900','1000'], Util.getYLabels());
 }
 
+AxisLabelsTestCase.prototype.testAxisLabelFontSize = function() {
+  var graph = document.getElementById("graph");
+  var g = new Dygraph(graph, AxisLabelsTestCase.simpleData, {});
+
+  // Be sure we're dealing with a 14-point default.
+  assertEquals(14, Dygraph.DEFAULT_ATTRS.axisLabelFontSize);
+
+  Util.assertFontSizes(graph, "dygraph-axis-label-x", 14);
+  Util.assertFontSizes(graph, "dygraph-axis-label-y", 14);
+
+  g.updateOptions({ axisLabelFontSize : 8});
+  Util.assertFontSizes(graph, "dygraph-axis-label-x", 8); 
+  Util.assertFontSizes(graph, "dygraph-axis-label-y", 8); 
+
+  g.updateOptions({
+    axisLabelFontSize : null,
+    axes : { 
+      x : { axisLabelFontSize : 5 },
+    }   
+  }); 
+
+  Util.assertFontSizes(graph, "dygraph-axis-label-x", 5); 
+  Util.assertFontSizes(graph, "dygraph-axis-label-y", 14);
+
+  g.updateOptions({
+    axes : { 
+      y : { axisLabelFontSize : 20 },
+    }   
+  }); 
+
+  Util.assertFontSizes(graph, "dygraph-axis-label-x", 5); 
+  Util.assertFontSizes(graph, "dygraph-axis-label-y", 20); 
+
+  g.updateOptions({
+    series : { 
+      Y2 : { axis : "y2" } // copy y2 series to y2 axis.
+    },  
+    axes : { 
+      y2 : { axisLabelFontSize : 12 },
+    }   
+  }); 
+
+  Util.assertFontSizes(graph, "dygraph-axis-label-x", 5); 
+  Util.assertFontSizes(graph, "dygraph-axis-label-y1", 20); 
+  Util.assertFontSizes(graph, "dygraph-axis-label-y2", 12); 
+}
+
 AxisLabelsTestCase.prototype.testAxisLabelFontSizeNull = function() {
   var graph = document.getElementById("graph");
   var g = new Dygraph(graph, AxisLabelsTestCase.simpleData,
index f059ff9..81f7667 100644 (file)
@@ -11,7 +11,8 @@
  * dygraph_ - the graph.
  * global_ - global attributes (common among all graphs, AIUI)
  * user - attributes set by the user
- * axes_ - array of axis index to { series : [ series names ] , options : { axis-specific options. }
+ * yAxes_ - array of axis index to { series : [ series names ] , options : { axis-specific options. }
+ * xAxis_ - { options : { axis-specific options. }
  * series_ - { seriesName -> { idx, yAxis, options }}
  * labels_ - used as mapping from index to series name.
  */
@@ -28,7 +29,8 @@
  */
 var DygraphOptions = function(dygraph) {
   this.dygraph_ = dygraph;
-  this.axes_ = [];
+  this.yAxes_ = [];
+  this.xAxis_ = {};
   this.series_ = {};
 
   // Once these two objects are initialized, you can call get();
@@ -92,7 +94,8 @@ DygraphOptions.axisToIndex_ = function(axis) {
 DygraphOptions.prototype.reparseSeries = function() {
   this.labels = this.get("labels").slice(1);
 
-  this.axes_ = [ { series : [], options : {}} ]; // Always one axis at least.
+  this.yAxes_ = [ { series : [], options : {}} ]; // Always one axis at least.
+  this.xAxis_ = { options : {} };
   this.series_ = {};
 
   // Traditionally, per-series options were specified right up there with the options. For instance
@@ -131,12 +134,12 @@ DygraphOptions.prototype.reparseSeries = function() {
       var axis = optionsForSeries["axis"];
       if (typeof(axis) == 'object') {
         yAxis = ++axisId;
-        this.axes_[yAxis] = { series : [ seriesName ], options : axis };
+        this.yAxes_[yAxis] = { series : [ seriesName ], options : axis };
       }
 
       // Associate series without axis options with axis 0.
       if (!axis) { // undefined
-        this.axes_[0].series.push(seriesName);
+        this.yAxes_[0].series.push(seriesName);
       }
 
       this.series_[seriesName] = { idx: idx, yAxis: yAxis, options : optionsForSeries };
@@ -157,7 +160,7 @@ DygraphOptions.prototype.reparseSeries = function() {
         }
         var yAxis = this.series_[axis].yAxis;
         this.series_[seriesName].yAxis = yAxis;
-        this.axes_[yAxis].series.push(seriesName);
+        this.yAxes_[yAxis].series.push(seriesName);
       }
     }
   } else {
@@ -171,20 +174,20 @@ DygraphOptions.prototype.reparseSeries = function() {
         yAxis: yAxis,
         options : optionsForSeries };
 
-      if (!this.axes_[yAxis]) {
-        this.axes_[yAxis] =  { series : [ seriesName ], options : {} };
+      if (!this.yAxes_[yAxis]) {
+        this.yAxes_[yAxis] =  { series : [ seriesName ], options : {} };
       } else {
-        this.axes_[yAxis].series.push(seriesName);
+        this.yAxes_[yAxis].series.push(seriesName);
       }
     }
   }
 
-  // This doesn't support reading from the 'x' axis, only 'y' and 'y2.
   var axis_opts = this.user_["axes"] || {};
-  Dygraph.update(this.axes_[0].options, axis_opts["y"] || {});
-  if (this.axes_.length > 1) {
-    Dygraph.update(this.axes_[1].options, axis_opts["y2"] || {});   
+  Dygraph.update(this.yAxes_[0].options, axis_opts["y"] || {});
+  if (this.yAxes_.length > 1) {
+    Dygraph.update(this.yAxes_[1].options, axis_opts["y2"] || {});   
   }
+  Dygraph.update(this.xAxis_.options, axis_opts["x"] || {});
 };
 
 /**
@@ -223,19 +226,35 @@ DygraphOptions.prototype.getGlobalDefault_ = function(name) {
  *
  * @param {String} name the name of the option.
  * @param {String|number} axis the axis to search. Can be the string representation
- * ("y", "y2") or the axis number (0, 1).
+ * ("x", "y", "y2") or the y-axis number (0, 1). (x-axis can't be specified by number.')
  */
 DygraphOptions.prototype.getForAxis = function(name, axis) {
-  var axisIdx = 0;
+  var axisIdx;
+  var axisString;
+
+  // Since axis can be a number or a string, straighten everything out here.
   if (typeof(axis) == 'number') {
     axisIdx = axis;
+    axisString = axisIdx == 0 ? "y" : "y2";
   } else {
-    // TODO(konigsberg): Accept only valid axis strings?
-    axisIdx = (axis == "y2") ? 1 : 0;
+    if (axis == "y1") { axis = "y"; } // Standardize on 'y'. Is this bad? I think so.
+    if (axis == "y") {
+      axisIdx = 0;
+    } else if (axis == "y2") {
+      axisIdx = 1;
+    } else if (axis == "x") {
+      axisIdx = -1; // simply a placeholder for below.
+    } else {
+      throw "Unknown axis " + axis;
+    }
+    axisString = axis;
   }
+
+  var userAxis = (axisIdx == -1) ? this.xAxis_ : this.yAxes_[axisIdx];
+
   // Search the user-specified axis option first.
-  if (this.axes_[axisIdx]) {
-    var axisOptions = this.axes_[axisIdx].options;
+  if (userAxis) { // This condition could be removed if we always set up this.yAxes_ for y2.
+    var axisOptions = userAxis.options;
     if (axisOptions.hasOwnProperty(name)) {
       return axisOptions[name];
     }
@@ -248,7 +267,6 @@ DygraphOptions.prototype.getForAxis = function(name, axis) {
   }
 
   // Default axis options third.
-  var axisString = axis == 0 ? "y" : "y2";
   var defaultAxisOptions = Dygraph.DEFAULT_ATTRS.axes[axisString];
   if (defaultAxisOptions.hasOwnProperty(name)) {
     return defaultAxisOptions[name];
@@ -294,7 +312,7 @@ DygraphOptions.prototype.getForSeries = function(name, series) {
  * @return {Number} the number of axes.
  */
 DygraphOptions.prototype.numAxes = function() {
-  return this.axes_.length;
+  return this.yAxes_.length;
 };
 
 /**
@@ -307,15 +325,16 @@ DygraphOptions.prototype.axisForSeries = function(seriesName) {
 /**
  * Returns the options for the specified axis.
  */
+// TODO(konigsberg): this is y-axis specific. Support the x axis.
 DygraphOptions.prototype.axisOptions = function(yAxis) {
-  return this.axes_[yAxis].options;
+  return this.yAxes_[yAxis].options;
 };
 
 /**
  * Return the series associated with an axis.
  */
 DygraphOptions.prototype.seriesForAxis = function(yAxis) {
-  return this.axes_[yAxis].series;
+  return this.yAxes_[yAxis].series;
 };
 
 /**
index 2bccd60..d7c558b 100644 (file)
@@ -598,6 +598,9 @@ Dygraph.prototype.getOption = function(name, opt_seriesName) {
   return this.attr_(name, opt_seriesName);
 };
 
+Dygraph.prototype.getOptionForAxis = function(name, axis) {
+  return this.attributes_.getForAxis(name, axis);
+}
 /**
  * @private
  * @param  String} axis The name of the axis (i.e. 'x', 'y' or 'y2')
index c91439d..bb74957 100644 (file)
@@ -69,7 +69,7 @@ var opts = {
   },
   axisLabelFontSize : {
     type : "int",
-    // scope : [ "x", "y", "y2" ]
+    scope : [ "global", "x", "y", "y2" ]
   },
   axisLabelFormatter : {
     type : "function(numberOrDate, granularity, opts, dygraph)",
index 1f9c256..40b826c 100644 (file)
@@ -52,7 +52,7 @@ axes.prototype.layout = function(e) {
     if (g.getOption('xAxisHeight')) {
       h = g.getOption('xAxisHeight');
     } else {
-      h = g.getOption('axisLabelFontSize') + 2 * g.getOption('axisTickSize');
+      h = g.getOptionForAxis('axisLabelFontSize', 'x') + 2 * g.getOption('axisTickSize');
     }
     var x_axis_rect = e.reserveSpaceBottom(h);
   }
@@ -101,18 +101,34 @@ axes.prototype.willDrawChart = function(e) {
 
   var label, x, y, tick, i;
 
-  var labelStyle = {
-    position: "absolute",
-    fontSize: g.getOption('axisLabelFontSize') + "px",
-    zIndex: 10,
-    color: g.getOption('axisLabelColor'),
-    width: g.getOption('axisLabelWidth') + "px",
-    // height: this.attr_('axisLabelFontSize') + 2 + "px",
-    lineHeight: "normal",  // Something other than "normal" line-height screws up label positioning.
-    overflow: "hidden"
+  var makeLabelStyle = function(axis) {
+    return {
+      position: "absolute",
+      fontSize: g.getOptionForAxis('axisLabelFontSize', axis) + "px",
+      zIndex: 10,
+      color: g.getOption('axisLabelColor'),
+      width: g.getOption('axisLabelWidth') + "px",
+      // height: g.getOptionForAxis('axisLabelFontSize', 'x') + 2 + "px",
+      lineHeight: "normal",  // Something other than "normal" line-height screws up label positioning.
+      overflow: "hidden"
+    };
+  }
+
+  var labelStyles = {
+    x : makeLabelStyle('x'),
+    y : makeLabelStyle('y'),
+    y2 : makeLabelStyle('y2'),
   };
+
   var makeDiv = function(txt, axis, prec_axis) {
+    /*
+     * This seems to be called with the following three sets of axis/perc_axis:
+     * x: undefined
+     * y: y1
+     * y: y2
+     */
     var div = document.createElement("div");
+    var labelStyle = labelStyles[prec_axis == 'y2' ? 'y2' : axis];
     for (var name in labelStyle) {
       if (labelStyle.hasOwnProperty(name)) {
         div.style[name] = labelStyle[name];
@@ -149,6 +165,7 @@ axes.prototype.willDrawChart = function(e) {
           sgn = -1;
           prec_axis = 'y2';
         }
+        var fontSize = g.getOptionForAxis('axisLabelFontSize', prec_axis);
         y = area.y + tick[1] * area.h;
 
         /* Tick marks are currently clipped, so don't bother drawing them.
@@ -160,10 +177,10 @@ axes.prototype.willDrawChart = function(e) {
         */
 
         label = makeDiv(tick[2], 'y', num_axes == 2 ? prec_axis : null);
-        var top = (y - g.getOption('axisLabelFontSize') / 2);
+        var top = (y - fontSize / 2);
         if (top < 0) top = 0;
 
-        if (top + g.getOption('axisLabelFontSize') + 3 > canvasHeight) {
+        if (top + fontSize + 3 > canvasHeight) {
           label.style.bottom = "0px";
         } else {
           label.style.top = top + "px";
@@ -185,7 +202,8 @@ axes.prototype.willDrawChart = function(e) {
       // tick on the x-axis. Shift the bottom tick up a little bit to
       // compensate if necessary.
       var bottomTick = this.ylabels_[0];
-      var fontSize = g.getOption('axisLabelFontSize');
+      // Interested in the y2 axis also?
+      var fontSize = g.getOptionForAxis('axisLabelFontSize', "y");
       var bottom = parseInt(bottomTick.style.top, 10) + fontSize;
       if (bottom > canvasHeight - fontSize) {
         bottomTick.style.top = (parseInt(bottomTick.style.top, 10) -