From: Robert Konigsberg Date: Sun, 30 Dec 2012 01:49:15 +0000 (-0500) Subject: Merge branch 'master' of https://github.com/danvk/dygraphs into option-consolidation X-Git-Tag: v1.0.0~138^2 X-Git-Url: https://adrianiainlam.tk/git/?a=commitdiff_plain;h=780a5081d29a3c0a3c4f1d126f0992cf4fc14ebd;hp=03d2998b741f48e9d92ecbadfd62201886a19fda;p=dygraphs.git Merge branch 'master' of https://github.com/danvk/dygraphs into option-consolidation --- diff --git a/auto_tests/tests/Util.js b/auto_tests/tests/Util.js index 7fca030..6469bc6 100644 --- a/auto_tests/tests/Util.js +++ b/auto_tests/tests/Util.js @@ -57,3 +57,14 @@ Util.getLegend = function(parent) { 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; +} diff --git a/auto_tests/tests/axis_labels.js b/auto_tests/tests/axis_labels.js index ddb7a0f..2eb7f4d 100644 --- a/auto_tests/tests/axis_labels.js +++ b/auto_tests/tests/axis_labels.js @@ -12,16 +12,12 @@ AxisLabelsTestCase.prototype.setUp = function() { 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; @@ -78,18 +74,18 @@ AxisLabelsTestCase.prototype.testSmallRangeNearZero = function() { 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()); @@ -525,6 +521,28 @@ AxisLabelsTestCase.prototype.testLabelKMG2 = function() { 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. */ @@ -547,3 +565,109 @@ AxisLabelsTestCase.prototype.testIncludeZero = function() { 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); +} +*/ diff --git a/auto_tests/tests/custom_bars.js b/auto_tests/tests/custom_bars.js index 22ffd20..493e86c 100644 --- a/auto_tests/tests/custom_bars.js +++ b/auto_tests/tests/custom_bars.js @@ -6,11 +6,16 @@ */ var CustomBarsTestCase = TestCase("custom-bars"); +var _origFunc = Dygraph.getContext; CustomBarsTestCase.prototype.setUp = function() { document.body.innerHTML = "
"; + 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. @@ -106,3 +111,43 @@ CustomBarsTestCase.prototype.testCustomBarsAtTop = function() { 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" }); +}; diff --git a/auto_tests/tests/to_dom_coords.js b/auto_tests/tests/to_dom_coords.js index 98da7c4..3def1ef 100644 --- a/auto_tests/tests/to_dom_coords.js +++ b/auto_tests/tests/to_dom_coords.js @@ -121,3 +121,47 @@ ToDomCoordsTestCase.prototype.testChartWithAxesAndLabels = function() { 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)); +} diff --git a/dygraph-interaction-model.js b/dygraph-interaction-model.js index d335f15..b5e9ee3 100644 --- a/dygraph-interaction-model.js +++ b/dygraph-interaction-model.js @@ -84,7 +84,8 @@ Dygraph.Interaction.startPan = function(event, g, context) { 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 { @@ -158,7 +159,8 @@ Dygraph.Interaction.movePan = function(event, g, context) { 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 { @@ -479,7 +481,8 @@ Dygraph.Interaction.moveTouch = function(event, g, context) { 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 = [ diff --git a/dygraph-layout.js b/dygraph-layout.js index 9a0ac3d..900db68 100644 --- a/dygraph-layout.js +++ b/dygraph-layout.js @@ -210,8 +210,8 @@ DygraphLayout.prototype._evaluateLimits = function() { } }; -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); @@ -232,6 +232,8 @@ DygraphLayout.prototype._evaluateLineCharts = function() { 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. @@ -245,7 +247,7 @@ DygraphLayout.prototype._evaluateLineCharts = function() { // 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. @@ -322,6 +324,9 @@ DygraphLayout.prototype.evaluateWithError = function() { 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]); @@ -334,8 +339,8 @@ DygraphLayout.prototype.evaluateWithError = function() { 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); } } } diff --git a/dygraph.js b/dygraph.js index 9b53729..1ac7d43 100644 --- a/dygraph.js +++ b/dygraph.js @@ -831,7 +831,8 @@ Dygraph.prototype.toPercentYCoord = function(y, axis) { 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. @@ -2451,30 +2452,13 @@ Dygraph.prototype.computeYAxes_ = function() { 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. @@ -2531,7 +2515,8 @@ Dygraph.prototype.computeYAxisRanges_ = function(extremes) { // 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) { @@ -2557,7 +2542,7 @@ Dygraph.prototype.computeYAxisRanges_ = function(extremes) { 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; @@ -2569,7 +2554,7 @@ Dygraph.prototype.computeYAxisRanges_ = function(extremes) { if (span === 0) { span = maxY; } var maxAxisY, minAxisY; - if (axis.logscale) { + if (logscale) { maxAxisY = maxY + 0.1 * span; minAxisY = minY; } else { @@ -2821,6 +2806,10 @@ Dygraph.prototype.detectTypeFromString_ = function(str) { isDate = true; } + this.setXAxisOptions_(isDate); +}; + +Dygraph.prototype.setXAxisOptions_ = function(isDate) { if (isDate) { this.attrs_.xValueParser = Dygraph.dateParser; this.attrs_.axes.x.valueFormatter = Dygraph.dateString_; @@ -2835,7 +2824,7 @@ Dygraph.prototype.detectTypeFromString_ = function(str) { 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() @@ -3057,8 +3046,8 @@ Dygraph.prototype.parseArray_ = function(data) { 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); @@ -3080,8 +3069,8 @@ Dygraph.prototype.parseArray_ = function(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; } };