* middle of the years.
*/
-/*jshint globalstrict: true */
+/*jshint globalstrict:true, sub:true */
/*global Dygraph:false */
"use strict";
/** @typedef {Array.<{v:number, label:string, label_v:(string|undefined)}>} */
-Dygraph.TickList;
+Dygraph.TickList = undefined; // the ' = undefined' keeps jshint happy.
/** @typedef {function(
* number,
* Array.<number>=
* ): Dygraph.TickList}
*/
-Dygraph.Ticker;
-
+Dygraph.Ticker = undefined; // the ' = undefined' keeps jshint happy.
/** @type {Dygraph.Ticker} */
Dygraph.numericLinearTicks = function(a, b, pixels, opts, dygraph, vals) {
// The first spacing greater than pixelsPerYLabel is what we use.
// TODO(danvk): version that works on a log scale.
var kmg2 = opts("labelsKMG2");
- var mults;
+ var mults, base;
if (kmg2) {
- mults = [1, 2, 4, 8];
+ mults = [1, 2, 4, 8, 16, 32, 64, 128, 256];
+ base = 16;
} else {
- mults = [1, 2, 5];
+ mults = [1, 2, 5, 10, 20, 50, 100];
+ base = 10;
}
- var scale, low_val, high_val;
- for (i = -10; i < 50; i++) {
- var base_scale;
- if (kmg2) {
- base_scale = pow(16, i);
- } else {
- base_scale = pow(10, i);
- }
- var spacing = 0;
- for (j = 0; j < mults.length; j++) {
- scale = base_scale * mults[j];
- low_val = Math.floor(a / scale) * scale;
- high_val = Math.ceil(b / scale) * scale;
- nTicks = Math.abs(high_val - low_val) / scale;
- spacing = pixels / nTicks;
- // wish I could break out of both loops at once...
- if (spacing > pixels_per_tick) break;
- }
+
+ // Get the maximum number of permitted ticks based on the
+ // graph's pixel size and pixels_per_tick setting.
+ var max_ticks = Math.ceil(pixels / pixels_per_tick);
+
+ // Now calculate the data unit equivalent of this tick spacing.
+ // Use abs() since graphs may have a reversed Y axis.
+ var units_per_tick = Math.abs(b - a) / max_ticks;
+
+ // Based on this, get a starting scale which is the largest
+ // integer power of the chosen base (10 or 16) that still remains
+ // below the requested pixels_per_tick spacing.
+ var base_power = Math.floor(Math.log(units_per_tick) / Math.log(base));
+ var base_scale = Math.pow(base, base_power);
+
+ // Now try multiples of the starting scale until we find one
+ // that results in tick marks spaced sufficiently far apart.
+ // The "mults" array should cover the range 1 .. base^2 to
+ // adjust for rounding and edge effects.
+ var scale, low_val, high_val, spacing;
+ for (j = 0; j < mults.length; j++) {
+ scale = base_scale * mults[j];
+ low_val = Math.floor(a / scale) * scale;
+ high_val = Math.ceil(b / scale) * scale;
+ nTicks = Math.abs(high_val - low_val) / scale;
+ spacing = pixels / nTicks;
if (spacing > pixels_per_tick) break;
}
}
// Add formatted labels to the ticks.
- var k = 1;
+ var k;
var k_labels = [];
var m_labels = [];
if (opts("labelsKMB")) {
m_labels = [ "m", "u", "n", "p", "f", "a", "z", "y" ];
}
+ k = k || 1; // If neither option is specified.
+
var formatter = /**@type{AxisLabelFormatter}*/(opts('axisLabelFormatter'));
// Add labels to the ticks.