From f91cfe5a336dc0153bea9ccf1f4faab741d940ee Mon Sep 17 00:00:00 2001 From: Dan Vanderkam Date: Sat, 13 Dec 2014 11:30:54 -0500 Subject: [PATCH] Set `this` to the Dygraph for formatting callbacks. --- auto_tests/tests/axis_labels.js | 85 ++++++++++++++++++++++++++++++++++++++--- dygraph-tickers.js | 6 +-- dygraph.js | 2 +- extras/super-annotations.js | 6 +-- plugins/legend.js | 4 +- 5 files changed, 89 insertions(+), 14 deletions(-) diff --git a/auto_tests/tests/axis_labels.js b/auto_tests/tests/axis_labels.js index 13de031..0c1690d 100644 --- a/auto_tests/tests/axis_labels.js +++ b/auto_tests/tests/axis_labels.js @@ -243,22 +243,28 @@ AxisLabelsTestCase.prototype.testValueFormatter = function () { var opts = { width: 480, height: 320, - axes : { - x : { - valueFormatter: function(x, opts, series_name, dg) { + axes: { + x: { + valueFormatter: function(x, opts, series_name, dg, row, col) { assertEquals('number', typeof(x)); assertEquals('function', typeof(opts)); assertEquals('string', typeof(series_name)); assertEquals('[Dygraph graph]', dg.toString()); + assertEquals('number', typeof(row)); + assertEquals('number', typeof(col)); + assertEquals(dg, this); return 'x' + x; } }, - y : { - valueFormatter: function(y, opts, series_name, dg) { + y: { + valueFormatter: function(y, opts, series_name, dg, row, col) { assertEquals('number', typeof(y)); assertEquals('function', typeof(opts)); assertEquals('string', typeof(series_name)); assertEquals('[Dygraph graph]', dg.toString()); + assertEquals('number', typeof(row)); + assertEquals('number', typeof(col)); + assertEquals(dg, this); return 'y' + y; } } @@ -294,6 +300,9 @@ AxisLabelsTestCase.prototype.testDateValueFormatter = function () { assertEquals('function', typeof(opts)); assertEquals('string', typeof(series_name)); assertEquals('[Dygraph graph]', dg.toString()); + assertEquals('number', typeof(row)); + assertEquals('number', typeof(col)); + assertEquals(dg, this); return 'x' + Util.formatDate(x); } }, @@ -303,6 +312,9 @@ AxisLabelsTestCase.prototype.testDateValueFormatter = function () { assertEquals('function', typeof(opts)); assertEquals('string', typeof(series_name)); assertEquals('[Dygraph graph]', dg.toString()); + assertEquals('number', typeof(row)); + assertEquals('number', typeof(col)); + assertEquals(dg, this); return 'y' + y; } } @@ -335,17 +347,21 @@ AxisLabelsTestCase.prototype.testAxisLabelFormatterPrecedence = function () { axes : { x : { valueFormatter: function(x) { + assertEquals('[Dygraph graph]', this.toString()); return 'xvf' + x; }, axisLabelFormatter: function(x, granularity) { + assertEquals('[Dygraph graph]', this.toString()); return 'x' + x; } }, y : { valueFormatter: function(y) { + assertEquals('[Dygraph graph]', this.toString()); return 'yvf' + y; }, axisLabelFormatter: function(y) { + assertEquals('[Dygraph graph]', this.toString()); return 'y' + y; } } @@ -430,9 +446,11 @@ AxisLabelsTestCase.prototype.testGlobalFormatters = function() { height: 320, labels: ['x', 'y'], valueFormatter: function(x) { + assertEquals('[Dygraph graph]', this); return 'vf' + x; }, axisLabelFormatter: function(x) { + assertEquals('[Dygraph graph]', this); return 'alf' + x; } }; @@ -450,6 +468,63 @@ AxisLabelsTestCase.prototype.testGlobalFormatters = function() { assertEquals("vf9: y: vf18", Util.getLegend()); }; +AxisLabelsTestCase.prototype.testValueFormatterParameters = function() { + var calls = []; + // change any functions in list to 'fn' -- functions can't be asserted. + var killFunctions = function(list) { + var out = []; + for (var i = 0; i < list.length; i++) { + if (typeof(list[i]) == 'function') { + out[i] = 'fn'; + } else { + out[i] = list[i]; + } + } + return out; + }; + var taggedRecorder = function(tag) { + return function() { + calls.push([tag].concat([this], killFunctions(arguments))); + return ''; + } + }; + var opts = { + axes: { + x: { valueFormatter: taggedRecorder('x') }, + y: { valueFormatter: taggedRecorder('y') }, + y2: { valueFormatter: taggedRecorder('y2') } + }, + series: { + 'y1': { axis: 'y1'}, + 'y2': { axis: 'y2'} + }, + labels: ['x', 'y1', 'y2'] + }; + var data = [ + [0, 1, 2], + [1, 3, 4] + ]; + var graph = document.getElementById('graph'); + var g = new Dygraph(graph, data, opts); + + assertEquals([], calls); + g.setSelection(0); + assertEquals([ + // num or millis, opts, series, dygraph, row, col + [ 'x', g, 0, 'fn', 'x', g, 0, 0], + [ 'y', g, 1, 'fn', 'y1', g, 0, 1], + ['y2', g, 2, 'fn', 'y2', g, 0, 2] + ], calls); + + calls = []; + g.setSelection(1); + assertEquals([ + [ 'x', g, 1, 'fn', 'x', g, 1, 0], + [ 'y', g, 3, 'fn', 'y1', g, 1, 1], + ['y2', g, 4, 'fn', 'y2', g, 1, 2] + ], calls); +}; + AxisLabelsTestCase.prototype.testSeriesOrder = function() { var opts = { width: 480, diff --git a/dygraph-tickers.js b/dygraph-tickers.js index 35cd75a..0f6b1ab 100644 --- a/dygraph-tickers.js +++ b/dygraph-tickers.js @@ -198,7 +198,7 @@ Dygraph.numericTicks = function(a, b, pixels, opts, dygraph, vals) { for (i = 0; i < ticks.length; i++) { if (ticks[i].label !== undefined) continue; // Use current label. // TODO(danvk): set granularity to something appropriate here. - ticks[i].label = formatter(ticks[i].v, 0, opts, dygraph); + ticks[i].label = formatter.call(dygraph, ticks[i].v, 0, opts, dygraph); } return ticks; @@ -414,7 +414,7 @@ Dygraph.getDateAxis = function(start_time, end_time, granularity, opts, dg) { } while (tick_time <= end_time) { ticks.push({ v: tick_time, - label: formatter(tick_date, granularity, opts, dg) + label: formatter.call(dg, tick_date, granularity, opts, dg) }); tick_time += spacing; tick_date = new Date(tick_time); @@ -429,7 +429,7 @@ Dygraph.getDateAxis = function(start_time, end_time, granularity, opts, dg) { if (granularity >= Dygraph.DAILY || accessors.getHours(tick_date) % step === 0) { ticks.push({ v: tick_time, - label: formatter(tick_date, granularity, opts, dg) + label: formatter.call(dg, tick_date, granularity, opts, dg) }); } date_array[datefield] += step; diff --git a/dygraph.js b/dygraph.js index 6a57d78..f337385 100644 --- a/dygraph.js +++ b/dygraph.js @@ -190,7 +190,7 @@ Dygraph.numberValueFormatter = function(x, opts) { * @private */ Dygraph.numberAxisLabelFormatter = function(x, granularity, opts) { - return Dygraph.numberValueFormatter(x, opts); + return Dygraph.numberValueFormatter.call(this, x, opts); }; /** diff --git a/extras/super-annotations.js b/extras/super-annotations.js index 7697beb..b8b10c6 100644 --- a/extras/super-annotations.js +++ b/extras/super-annotations.js @@ -317,9 +317,9 @@ annotations.prototype.getTemplateHTML = function(div, a) { var yOptView = g.optionsViewForAxis_('y1'); // TODO: support secondary, too var xvf = g.getOptionForAxis('valueFormatter', 'x'); - var x = xvf(a.xval); - var y = g.getOption('valueFormatter', a.series)( - g.getValue(row, col), yOptView); + var x = xvf.call(g, a.xval); + var y = g.getOption('valueFormatter', a.series).call( + g, g.getValue(row, col), yOptView); var displayAnnotation = this.createPublicAnnotation_(a, {x:x, y:y}); var html = div.innerHTML; diff --git a/plugins/legend.js b/plugins/legend.js index 65ee671..c9f9d72 100644 --- a/plugins/legend.js +++ b/plugins/legend.js @@ -252,7 +252,7 @@ legend.generateLegendHTML = function(g, x, sel_points, oneEmWidth) { // TODO(danvk): remove this use of a private API var xOptView = g.optionsViewForAxis_('x'); var xvf = xOptView('valueFormatter'); - html = xvf(x, xOptView, labels[0], g); + html = xvf.call(g, x, xOptView, labels[0], g, row, 0); if (html !== '') { html += ':'; } @@ -275,7 +275,7 @@ legend.generateLegendHTML = function(g, x, sel_points, oneEmWidth) { var series = g.getPropertiesForSeries(pt.name); var yOptView = yOptViews[series.axis - 1]; var fmtFunc = yOptView('valueFormatter'); - var yval = fmtFunc(pt.yval, yOptView, pt.name, g); + var yval = fmtFunc.call(g, pt.yval, yOptView, pt.name, g, row, labels.indexOf(pt.name)); var cls = (pt.name == highlightSeries) ? " class='highlight'" : ""; -- 2.7.4