return legend.textContent;
}
+
+/**
+ * Takes in an array of strings and returns an array of floats.
+ */
+Util.makeNumbers = function(ary) {
+ var ret = [];
+ for (var i = 0; i < ary.length; i++) {
+ ret.push(parseFloat(ary[i]));
+ }
+ return ret;
+}
AxisLabelsTestCase.prototype.tearDown = function() {
};
-/**
- * Takes in an array of strings and returns an array of floats.
- */
-function makeNumbers(ary) {
- var ret = [];
- for (var i = 0; i < ary.length; i++) {
- ret.push(parseFloat(ary[i]));
- }
- return ret;
-}
+AxisLabelsTestCase.simpleData =
+ "X,Y,Y2\n" +
+ "0,-1,.5\n" +
+ "1,0,.7\n" +
+ "2,1,.4\n" +
+ "3,0,.98\n";
AxisLabelsTestCase.prototype.kCloseFloat = 1.0e-10;
var graph = document.getElementById("graph");
var g = new Dygraph(graph, data, opts);
- assertEqualsDelta(makeNumbers(["-0.1","-0.08","-0.06","-0.04","-0.02","0","0.02","0.04","0.06","0.08"]),
- makeNumbers(Util.getYLabels()), this.kCloseFloat);
+ assertEqualsDelta([-0.1, -0.08, -0.06, -0.04, -0.02, 0, 0.02, 0.04, 0.06, 0.08],
+ Util.makeNumbers(Util.getYLabels()), this.kCloseFloat);
opts.valueRange = [-0.05, 0.05];
g.updateOptions(opts);
- // TODO(danvk): why '1.00e-2' and not '0.01'?
- assertEquals(makeNumbers(["-0.05","-0.04","-0.03","-0.02","-0.01","0","1.00e-2","0.02","0.03","0.04"]),
- makeNumbers(Util.getYLabels()));
+ assertEquals([-0.05, -0.04, -0.03, -0.02, -0.01, 0, 0.01, 0.02, 0.03, 0.04],
+ Util.makeNumbers(Util.getYLabels()));
opts.valueRange = [-0.01, 0.01];
g.updateOptions(opts);
- assertEquals(makeNumbers(["-0.01","-8.00e-3","-6.00e-3","-4.00e-3","-2.00e-3","0","2.00e-3","4.00e-3","6.00e-3","8.00e-3"]), makeNumbers(Util.getYLabels()));
+ assertEquals([-0.01, -8.00e-3, -6.00e-3, -4.00e-3, -2.00e-3, 0, 2.00e-3, 4.00e-3, 6.00e-3, 8.00e-3],
+ Util.makeNumbers(Util.getYLabels()));
g.setSelection(1);
assertEquals('1: Y:0', Util.getLegend());
Util.getYLabels());
};
+// Same sa testLabelKMG2 but specifies the option at the
+// top of the option dictionary.
+AxisLabelsTestCase.prototype.testLabelKMG2_top = function() {
+ var data = [];
+ data.push([0,0]);
+ data.push([1,2000]);
+ data.push([2,1000]);
+
+ var g = new Dygraph(
+ document.getElementById("graph"),
+ data,
+ {
+ labels: [ 'X', 'bar' ],
+ labelsKMG2: true
+ }
+ );
+
+ assertEquals(
+ ["0","256","512","768","1k","1.25k","1.5k","1.75k","2k"],
+ Util.getYLabels());
+};
+
/**
* Verify that log scale axis range is properly specified.
*/
g.updateOptions({ includeZero : false });
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, {});
+ var assertSize = function(className, size) {
+ var sizePx = size + "px";
+ var labels = graph.getElementsByClassName(className);
+ assertTrue(labels.length > 0);
+
+ // window.getComputedStyle is apparently compatible with all browsers
+ // (IE first became compatible with IE9.)
+ // If this test fails on earlier browsers, then enable something like this,
+ // because the font size is set by the parent div.
+ // if (!window.getComputedStyle) {
+ // fontSize = label.parentElement.style.fontSize;
+ // }
+ for (var idx = 0; idx < labels.length; idx++) {
+ var label = labels[idx];
+ var fontSize = window.getComputedStyle(label).fontSize;
+ assertEquals(sizePx, fontSize);
+ }
+ }
+
+ // Be sure we're dealing with a 14-point default.
+ assertEquals(14, Dygraph.DEFAULT_ATTRS.axisLabelFontSize);
+
+ assertSize("dygraph-axis-label-x", 14);
+ assertSize("dygraph-axis-label-y", 14);
+
+ g.updateOptions({ axisLabelFontSize : 8});
+ assertSize("dygraph-axis-label-x", 8);
+ assertSize("dygraph-axis-label-y", 8);
+
+/*
+ Enable these tests when https://code.google.com/p/dygraphs/issues/detail?id=126
+ is fixed.
+
+ g.updateOptions({
+ axisLabelFontSize : null,
+ axes : {
+ x : { axisLabelFontSize : 5 },
+ }
+ });
+
+ assertSize("dygraph-axis-label-x", 5);
+ assertSize("dygraph-axis-label-y", 14);
+
+ g.updateOptions({
+ axisLabelFontSize : null,
+ axes : {
+ y : { axisLabelFontSize : 3 },
+ }
+ });
+
+ assertSize("dygraph-axis-label-x", 5);
+ assertSize("dygraph-axis-label-y", 3);
+
+ g.updateOptions({
+ series : {
+ Y2 : { axis : "y2" } // copy y2 series to y2 axis.
+ },
+ axes : {
+ y2 : { axisLabelFontSize : 8 },
+ }
+ });
+
+ assertSize("dygraph-axis-label-x", 5);
+ assertSize("dygraph-axis-label-y", 3);
+ assertSize("dygraph-axis-label-y2", 8);
+*/
+}
+
+/*
+ * This test will pass when
+ * https://code.google.com/p/dygraphs/issues/detail?id=413
+ * is fixed.
+AxisLabelsTestCase.prototype.testAxisLabelFontSize2 = function() {
+ var graph = document.getElementById("graph");
+ var g = new Dygraph(graph, AxisLabelsTestCase.simpleData,
+ {axisLabelFontSize: undefined});
+ var assertSize = function(className, size) {
+ var sizePx = size + "px";
+ var labels = graph.getElementsByClassName(className);
+ assertTrue(labels.length > 0);
+
+ // window.getComputedStyle is apparently compatible with all browsers
+ // (IE first became compatible with IE9.)
+ // If this test fails on earlier browsers, then enable something like this,
+ // because the font size is set by the parent div.
+ // if (!window.getComputedStyle) {
+ // fontSize = label.parentElement.style.fontSize;
+ // }
+ for (var idx = 0; idx < labels.length; idx++) {
+ var label = labels[idx];
+ var fontSize = window.getComputedStyle(label).fontSize;
+ assertEquals(sizePx, fontSize);
+ }
+ }
+
+ // Be sure we're dealing with a 14-point default.
+ assertEquals(14, Dygraph.DEFAULT_ATTRS.axisLabelFontSize);
+
+ assertSize("dygraph-axis-label-x", 14);
+ assertSize("dygraph-axis-label-y", 14);
+}
+*/
*/
var CustomBarsTestCase = TestCase("custom-bars");
+var _origFunc = Dygraph.getContext;
CustomBarsTestCase.prototype.setUp = function() {
document.body.innerHTML = "<div id='graph'></div>";
+ Dygraph.getContext = function(canvas) {
+ return new Proxy(_origFunc(canvas));
+ }
};
CustomBarsTestCase.prototype.tearDown = function() {
+ Dygraph.getContext = _origFunc;
};
// This test used to reliably produce an infinite loop.
var sampler = new PixelSampler(g);
assertEquals([0, 255, 0, 38], sampler.colorAtCoordinate(5, 60));
};
+
+// Tests that custom bars work with log scale.
+CustomBarsTestCase.prototype.testCustomBarsLogScale = function() {
+ var g = new Dygraph(document.getElementById("graph"),
+ [
+ [1, [10, 10, 100]],
+ [5, [15,120, 80]],
+ [9, [10, 50, 100]]
+ ], {
+ width: 500, height: 350,
+ customBars: true,
+ errorBars: true,
+ valueRange: [1, 120],
+ drawXGrid: false,
+ drawYGrid: false,
+ drawXAxis: false,
+ drawYAxis: false,
+ fillAlpha: 1.0,
+ logscale: true,
+ colors: [ '#00FF00' ]
+ });
+
+ // The following assertions describe the sides of the custom bars, which are
+ // drawn in two halves.
+ CanvasAssertions.assertConsecutiveLinesDrawn(
+ g.hidden_ctx_,
+ [[0, 13.329014086362069],
+ [247.5, 29.64240889852502],
+ [247.5, 152.02209814465604],
+ [0, 181.66450704318103]],
+ { fillStyle: "#00ff00" });
+
+ CanvasAssertions.assertConsecutiveLinesDrawn(
+ g.hidden_ctx_,
+ [[247.5, 29.64240889852502],
+ [495, 13.329014086362069],
+ [495, 181.66450704318103],
+ [247.5, 152.02209814465604]],
+ { fillStyle: "#00ff00" });
+};
this.checkForInverses(g);
}
+
+ToDomCoordsTestCase.prototype.testYAxisLabelWidth = function() {
+ var opts = {
+ yAxisLabelWidth: 100,
+ axisTickSize: 0,
+ rightGap: 0,
+ valueRange: [0, 100],
+ dateWindow: [0, 100],
+ width: 500,
+ height: 500
+ }
+
+ var graph = document.getElementById("graph");
+ g = new Dygraph(graph, [ [0,0], [100,100] ], opts);
+
+ assertEquals([100, 0], g.toDomCoords(0, 100));
+ assertEquals([500, 486], g.toDomCoords(100, 0));
+
+ g.updateOptions({ yAxisLabelWidth: 50 });
+ assertEquals([50, 0], g.toDomCoords(0, 100));
+ assertEquals([500, 486], g.toDomCoords(100, 0));
+}
+
+ToDomCoordsTestCase.prototype.testAxisTickSize = function() {
+ var opts = {
+ yAxisLabelWidth: 100,
+ axisTickSize: 0,
+ rightGap: 0,
+ valueRange: [0, 100],
+ dateWindow: [0, 100],
+ width: 500,
+ height: 500
+ }
+
+ var graph = document.getElementById("graph");
+ g = new Dygraph(graph, [ [0,0], [100,100] ], opts);
+
+ assertEquals([100, 0], g.toDomCoords(0, 100));
+ assertEquals([500, 486], g.toDomCoords(100, 0));
+
+ g.updateOptions({ axisTickSize : 50 });
+ assertEquals([200, 0], g.toDomCoords(0, 100));
+ assertEquals([500, 386], g.toDomCoords(100, 0));
+}
var yRange = g.yAxisRange(i);
// TODO(konigsberg): These values should be in |context|.
// In log scale, initialTopValue, dragValueRange and unitsPerPixel are log scale.
- if (axis.logscale) {
+ var logscale = g.attributes_.getForAxis("logscale", i);
+ if (logscale) {
axis_data.initialTopValue = Dygraph.log10(yRange[1]);
axis_data.dragValueRange = Dygraph.log10(yRange[1]) - Dygraph.log10(yRange[0]);
} else {
minValue = maxValue - axis_data.dragValueRange;
}
}
- if (axis.logscale) {
+ var logscale = g.attributes_.getForAxis("logscale", i);
+ if (logscale) {
axis.valueWindow = [ Math.pow(Dygraph.LOG_SCALE, minValue),
Math.pow(Dygraph.LOG_SCALE, maxValue) ];
} else {
if (context.touchDirections.y) {
for (i = 0; i < 1 /*g.axes_.length*/; i++) {
var axis = g.axes_[i];
- if (axis.logscale) {
+ var logscale = g.attributes_.getForAxis("logscale", i);
+ if (logscale) {
// TODO(danvk): implement
} else {
axis.valueWindow = [
}
};
-DygraphLayout._calcYNormal = function(axis, value) {
- if (axis.logscale) {
+DygraphLayout._calcYNormal = function(axis, value, logscale) {
+ if (logscale) {
return 1.0 - ((Dygraph.log10(value) - Dygraph.log10(axis.minyval)) * axis.ylogscale);
} else {
return 1.0 - ((value - axis.minyval) * axis.yscale);
var dataset = this.datasets[setIdx];
var setName = this.setNames[setIdx];
var axis = this.dygraph_.axisPropertiesForSeries(setName);
+ // TODO (konigsberg): use optionsForAxis instead.
+ var logscale = this.dygraph_.attributes_.getForSeries("logscale", setIdx);
// Preallocating the size of points reduces reallocations, and therefore,
// calls to collect garbage.
// Range from 0-1 where 0 represents left and 1 represents right.
var xNormal = (xValue - this.minxval) * this.xscale;
// Range from 0-1 where 0 represents top and 1 represents bottom
- var yNormal = DygraphLayout._calcYNormal(axis, yValue);
+ var yNormal = DygraphLayout._calcYNormal(axis, yValue, logscale);
// TODO(danvk): drop the point in this case, don't null it.
// The nulls create complexity in DygraphCanvasRenderer._drawSeries.
var dataset = this.datasets[setIdx];
var setName = this.setNames[setIdx];
var axis = this.dygraph_.axisPropertiesForSeries(setName);
+ // TODO (konigsberg): use optionsForAxis instead.
+ var logscale = this.dygraph_.attributes_.getForSeries("logscale", setIdx);
+
for (j = 0; j < dataset.length; j++, i++) {
var item = dataset[j];
var xv = DygraphLayout.parseFloat_(item[0]);
var yv_minus = yv - errorMinus;
var yv_plus = yv + errorPlus;
- points[j].y_top = DygraphLayout._calcYNormal(axis, yv_minus);
- points[j].y_bottom = DygraphLayout._calcYNormal(axis, yv_plus);
+ points[j].y_top = DygraphLayout._calcYNormal(axis, yv_minus, logscale);
+ points[j].y_bottom = DygraphLayout._calcYNormal(axis, yv_plus, logscale);
}
}
}
var yRange = this.yAxisRange(axis);
var pct;
- if (!this.axes_[axis].logscale) {
+ var logscale = this.attributes_.getForAxis("logscale", axis);
+ if (!logscale) {
// yRange[1] - y is unit distance from the bottom.
// yRange[1] - yRange[0] is the scale of the range.
// (yRange[1] - y) / (yRange[1] - yRange[0]) is the % from the bottom.
this.axes_[axis] = opts;
}
- // TODO(konigsberg): REMOVE THIS SILLINESS this should just come from DygraphOptions.
- // TODO(konigsberg): Add tests for all of these. Currently just tests for
- // includeZero and logscale.
-
- // all options which could be applied per-axis:
- var axisOptions = [
- 'includeZero',
- 'valueRange',
- 'labelsKMB',
- 'labelsKMG2',
- 'pixelsPerYLabel',
- 'yAxisLabelWidth',
- 'axisLabelFontSize',
- 'axisTickSize',
- 'logscale'
- ];
- // Copy global axis options over to the first axis.
- for (i = 0; i < axisOptions.length; i++) {
- var k = axisOptions[i];
- v = this.attr_(k);
- if (v) this.axes_[0][k] = v;
- }
- // TODO(konigsberg): end of REMOVE THIS SILLINESS
+ // Copy global valueRange option over to the first axis.
+ // NOTE(konigsberg): Are these two statements necessary?
+ // I tried removing it. The automated tests pass, and manually
+ // messing with tests/zoom.html showed no trouble.
+ v = this.attr_('valueRange');
+ if (v) this.axes_[0].valueRange = v;
if (valueWindows !== undefined) {
// Restore valueWindow settings.
// Compute extreme values, a span and tick marks for each axis.
for (var i = 0; i < numAxes; i++) {
var axis = this.axes_[i];
-
+ var logscale = this.attributes_.getForAxis("logscale", i);
+ var includeZero = this.attributes_.getForAxis("includeZero", i);
series = this.attributes_.seriesForAxis(i);
if (series.length == 0) {
maxY = Math.max(extremeMaxY, maxY);
}
}
- if (axis.includeZero && minY > 0) minY = 0;
+ if (includeZero && minY > 0) minY = 0;
// Ensure we have a valid scale, otherwise default to [0, 1] for safety.
if (minY == Infinity) minY = 0;
if (span === 0) { span = maxY; }
var maxAxisY, minAxisY;
- if (axis.logscale) {
+ if (logscale) {
maxAxisY = maxY + 0.1 * span;
minAxisY = minY;
} else {
isDate = true;
}
+ this.setXAxisOptions_(isDate);
+};
+
+Dygraph.prototype.setXAxisOptions_ = function(isDate) {
if (isDate) {
this.attrs_.xValueParser = Dygraph.dateParser;
this.attrs_.axes.x.valueFormatter = Dygraph.dateString_;
this.attrs_.axes.x.ticker = Dygraph.numericLinearTicks;
this.attrs_.axes.x.axisLabelFormatter = this.attrs_.axes.x.valueFormatter;
}
-};
+}
/**
* Parses the value as a floating point number. This is like the parseFloat()
if (Dygraph.isDateLike(data[0][0])) {
// Some intelligent defaults for a date x-axis.
this.attrs_.axes.x.valueFormatter = Dygraph.dateString_;
- this.attrs_.axes.x.axisLabelFormatter = Dygraph.dateAxisFormatter;
this.attrs_.axes.x.ticker = Dygraph.dateTicker;
+ this.attrs_.axes.x.axisLabelFormatter = Dygraph.dateAxisFormatter;
// Assume they're all dates.
var parsedData = Dygraph.clone(data);
// Some intelligent defaults for a numeric x-axis.
/** @private (shut up, jsdoc!) */
this.attrs_.axes.x.valueFormatter = function(x) { return x; };
- this.attrs_.axes.x.axisLabelFormatter = Dygraph.numberAxisLabelFormatter;
this.attrs_.axes.x.ticker = Dygraph.numericLinearTicks;
+ this.attrs_.axes.x.axisLabelFormatter = Dygraph.numberAxisLabelFormatter;
return data;
}
};