+ * Returns the number of y-axes on the chart.
+ * @return {Number} the number of axes.
+ */
+Dygraph.prototype.numAxes = function() {
+ var last_axis = 0;
+ for (var series in this.seriesToAxisMap_) {
+ if (!this.seriesToAxisMap_.hasOwnProperty(series)) continue;
+ var idx = this.seriesToAxisMap_[series];
+ if (idx > last_axis) last_axis = idx;
+ }
+ return 1 + last_axis;
+};
+
+/**
+ * Determine the value range and tick marks for each axis.
+ * @param {Object} extremes A mapping from seriesName -> [low, high]
+ * This fills in the valueRange and ticks fields in each entry of this.axes_.
+ */
+Dygraph.prototype.computeYAxisRanges_ = function(extremes) {
+ // Build a map from axis number -> [list of series names]
+ var seriesForAxis = [];
+ for (var series in this.seriesToAxisMap_) {
+ if (!this.seriesToAxisMap_.hasOwnProperty(series)) continue;
+ var idx = this.seriesToAxisMap_[series];
+ while (seriesForAxis.length <= idx) seriesForAxis.push([]);
+ seriesForAxis[idx].push(series);
+ }
+
+ // Compute extreme values, a span and tick marks for each axis.
+ for (var i = 0; i < this.axes_.length; i++) {
+ var axis = this.axes_[i];
+ if (axis.valueRange) {
+ axis.computedValueRange = [axis.valueRange[0], axis.valueRange[1]];
+ } else {
+ // Calcuate the extremes of extremes.
+ var series = seriesForAxis[i];
+ var minY = Infinity; // extremes[series[0]][0];
+ var maxY = -Infinity; // extremes[series[0]][1];
+ for (var j = 0; j < series.length; j++) {
+ minY = Math.min(extremes[series[j]][0], minY);
+ maxY = Math.max(extremes[series[j]][1], maxY);
+ }
+ if (axis.includeZero && minY > 0) minY = 0;
+
+ // Add some padding and round up to an integer to be human-friendly.
+ var span = maxY - minY;
+ // special case: if we have no sense of scale, use +/-10% of the sole value.
+ if (span == 0) { span = maxY; }
+ var maxAxisY = maxY + 0.1 * span;
+ var minAxisY = minY - 0.1 * span;
+
+ // Try to include zero and make it minAxisY (or maxAxisY) if it makes sense.
+ if (minAxisY < 0 && minY >= 0) minAxisY = 0;
+ if (maxAxisY > 0 && maxY <= 0) maxAxisY = 0;
+
+ if (this.attr_("includeZero")) {
+ if (maxY < 0) maxAxisY = 0;
+ if (minY > 0) minAxisY = 0;
+ }
+
+ axis.computedValueRange = [minAxisY, maxAxisY];
+ }
+
+ // Add ticks. By default, all axes inherit the tick positions of the
+ // primary axis. However, if an axis is specifically marked as having
+ // independent ticks, then that is permissible as well.
+ if (i == 0 || axis.independentTicks) {
+ axis.ticks =
+ Dygraph.numericTicks(axis.computedValueRange[0],
+ axis.computedValueRange[1],
+ this,
+ axis);
+ } else {
+ var p_axis = this.axes_[0];
+ var p_ticks = p_axis.ticks;
+ var p_scale = p_axis.computedValueRange[1] - p_axis.computedValueRange[0];
+ var scale = axis.computedValueRange[1] - axis.computedValueRange[0];
+ var tick_values = [];
+ for (var i = 0; i < p_ticks.length; i++) {
+ var y_frac = (p_ticks[i].v - p_axis.computedValueRange[0]) / p_scale;
+ var y_val = axis.computedValueRange[0] + y_frac * scale;
+ tick_values.push(y_val);
+ }
+
+ axis.ticks =
+ Dygraph.numericTicks(axis.computedValueRange[0],
+ axis.computedValueRange[1],
+ this, axis, tick_values);
+ }
+ }
+
+ return [this.axes_, this.seriesToAxisMap_];
+};
+
+/**