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,
* 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.
*/
*/
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();
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
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 };
}
var yAxis = this.series_[axis].yAxis;
this.series_[seriesName].yAxis = yAxis;
- this.axes_[yAxis].series.push(seriesName);
+ this.yAxes_[yAxis].series.push(seriesName);
}
}
} else {
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"] || {});
};
/**
*
* @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];
}
}
// Default axis options third.
- var axisString = axis == 0 ? "y" : "y2";
var defaultAxisOptions = Dygraph.DEFAULT_ATTRS.axes[axisString];
if (defaultAxisOptions.hasOwnProperty(name)) {
return defaultAxisOptions[name];
* @return {Number} the number of axes.
*/
DygraphOptions.prototype.numAxes = function() {
- return this.axes_.length;
+ return this.yAxes_.length;
};
/**
/**
* 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;
};
/**
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')
},
axisLabelFontSize : {
type : "int",
- // scope : [ "x", "y", "y2" ]
+ scope : [ "global", "x", "y", "y2" ]
},
axisLabelFormatter : {
type : "function(numberOrDate, granularity, opts, dygraph)",
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);
}
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];
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.
*/
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";
// 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) -