diff --git a/auto_tests/tests/select_mode.js b/auto_tests/tests/select_mode.js new file mode 100644 index 000000000..ca11a34f6 --- /dev/null +++ b/auto_tests/tests/select_mode.js @@ -0,0 +1,1454 @@ +/** + * @fileoverview Tests involving issuing XHRs for data. + * + * Note that these tests must be run with an HTTP server. + * XHRs can't be issued from file:/// URLs. + * This can be done with + * + * npm install http-server + * http-server + * open http://localhost:8080/auto_tests/runner.html + * + */ + +import Dygraph from '../../src/dygraph'; +import DygraphOps from './DygraphOps'; +import Util from './Util'; + +// Note that this data contains 2 points with the same +// x value. euclidian selection mode can distinguish them. +var TEST_SERIES = "X,Y1,Y2\n" + + "0,1,3\n" + + "0.5,1,3\n" + + "0.7,4.5,2.5\n" + + "0.7,5,3\n" + + "1,1,4\n"; + +// A version without the duplicate x value, for use with +// stacked graphs (these don't show duplicate x values). +var TEST_SERIES_NODUP = "X,Y1,Y2\n" + + "0,1,3\n" + + "0.5,1,3\n" + + "0.7,4.5,2.5\n" + + "1,1,4\n"; + + + +function lockSeries(graph) { + graph.setSelection(4, 'Y1', true); +} + +function makeGraph(series, options) { + return new Dygraph( + document.getElementById('graph'), + series, + options + ); +} + +describe("select-mode", function() { + +cleanupAfterEach(); + +/** + * Default behaviour: + * + * selectMode: closest-x + * highlightSeriesOpts: no + * stacked: no + * series locked: no + */ +it('default-settings', () => { + + var g = makeGraph(TEST_SERIES, null); + + // Mouse along y=1 + DygraphOps.dispatchMouseMove(g, 0, 1); + assert.equal(0, g.getSelection()); + + DygraphOps.dispatchMouseMove(g, 0.2, 1); + assert.equal(0, g.getSelection()); + + DygraphOps.dispatchMouseMove(g, 0.4, 1); + assert.equal(1, g.getSelection()); + + DygraphOps.dispatchMouseMove(g, 0.6, 1); + assert.equal(1, g.getSelection()); + + DygraphOps.dispatchMouseMove(g, 0.8, 1); + assert.equal(2, g.getSelection()); + + DygraphOps.dispatchMouseMove(g, 1, 1); + assert.equal(4, g.getSelection()); + + // Mouse along y=5 + DygraphOps.dispatchMouseMove(g, 0, 5); + assert.equal(0, g.getSelection()); + + DygraphOps.dispatchMouseMove(g, 0.2, 5); + assert.equal(0, g.getSelection()); + + DygraphOps.dispatchMouseMove(g, 0.4, 5); + assert.equal(1, g.getSelection()); + + DygraphOps.dispatchMouseMove(g, 0.6, 5); + assert.equal(1, g.getSelection()); + + DygraphOps.dispatchMouseMove(g, 0.8, 5); + assert.equal(2, g.getSelection()); + + DygraphOps.dispatchMouseMove(g, 1, 5); + assert.equal(4, g.getSelection()); + + // Mouse up x=0.7 + DygraphOps.dispatchMouseMove(g, 0.7, 1); + assert.equal(2, g.getSelection()); + + DygraphOps.dispatchMouseMove(g, 0.7, 2); + assert.equal(2, g.getSelection()); + + DygraphOps.dispatchMouseMove(g, 0.7, 3); + assert.equal(2, g.getSelection()); + + DygraphOps.dispatchMouseMove(g, 0.7, 4); + assert.equal(2, g.getSelection()); + + DygraphOps.dispatchMouseMove(g, 0.7, 5); + assert.equal(2, g.getSelection()); + +}); + +/** + * Explicitly set closest-x + * + * selectMode: closest-x + * highlightSeriesOpts: no + * stacked: no + * series locked: no + */ +it('closest-x/no highlight/not stacked/no series lock', () => { + + var g = makeGraph(TEST_SERIES, { + selectMode: 'closest-x' + }); + + // Mouse along y=1 + DygraphOps.dispatchMouseMove(g, 0, 1); + assert.equal(0, g.getSelection()); + + DygraphOps.dispatchMouseMove(g, 0.2, 1); + assert.equal(0, g.getSelection()); + + DygraphOps.dispatchMouseMove(g, 0.4, 1); + assert.equal(1, g.getSelection()); + + DygraphOps.dispatchMouseMove(g, 0.6, 1); + assert.equal(1, g.getSelection()); + + DygraphOps.dispatchMouseMove(g, 0.8, 1); + assert.equal(2, g.getSelection()); + + DygraphOps.dispatchMouseMove(g, 1, 1); + assert.equal(4, g.getSelection()); + + // Mouse along y=5 + DygraphOps.dispatchMouseMove(g, 0, 5); + assert.equal(0, g.getSelection()); + + DygraphOps.dispatchMouseMove(g, 0.2, 5); + assert.equal(0, g.getSelection()); + + DygraphOps.dispatchMouseMove(g, 0.4, 5); + assert.equal(1, g.getSelection()); + + DygraphOps.dispatchMouseMove(g, 0.6, 5); + assert.equal(1, g.getSelection()); + + DygraphOps.dispatchMouseMove(g, 0.8, 5); + assert.equal(2, g.getSelection()); + + DygraphOps.dispatchMouseMove(g, 1, 5); + assert.equal(4, g.getSelection()); + + // Mouse up x=0.7 + DygraphOps.dispatchMouseMove(g, 0.7, 1); + assert.equal(2, g.getSelection()); + + DygraphOps.dispatchMouseMove(g, 0.7, 2); + assert.equal(2, g.getSelection()); + + DygraphOps.dispatchMouseMove(g, 0.7, 3); + assert.equal(2, g.getSelection()); + + DygraphOps.dispatchMouseMove(g, 0.7, 4); + assert.equal(2, g.getSelection()); + + DygraphOps.dispatchMouseMove(g, 0.7, 5); + assert.equal(2, g.getSelection()); + +}); + +/** + * selectMode: euclidian + * highlightSeriesOpts: no + * stacked: no + * series locked: no + */ +it('euclidian/no highlight/not stacked/no series lock', () => { + + var g = makeGraph(TEST_SERIES, { + selectMode: 'euclidian' + }); + + // Mouse along y=1 + DygraphOps.dispatchMouseMove(g, 0, 1); + assert.equal(0, g.getSelection()); + + DygraphOps.dispatchMouseMove(g, 0.2, 1); + assert.equal(0, g.getSelection()); + + DygraphOps.dispatchMouseMove(g, 0.4, 1); + assert.equal(1, g.getSelection()); + + DygraphOps.dispatchMouseMove(g, 0.6, 1); + assert.equal(1, g.getSelection()); + + DygraphOps.dispatchMouseMove(g, 0.8, 1); + assert.equal(4, g.getSelection()); + + DygraphOps.dispatchMouseMove(g, 1, 1); + assert.equal(4, g.getSelection()); + + // Mouse along y=5 + DygraphOps.dispatchMouseMove(g, 0, 5); + assert.equal(0, g.getSelection()); + + DygraphOps.dispatchMouseMove(g, 0.2, 5); + assert.equal(0, g.getSelection()); + + DygraphOps.dispatchMouseMove(g, 0.4, 5); + assert.equal(3, g.getSelection()); + + DygraphOps.dispatchMouseMove(g, 0.6, 5); + assert.equal(3, g.getSelection()); + + DygraphOps.dispatchMouseMove(g, 0.8, 5); + assert.equal(3, g.getSelection()); + + DygraphOps.dispatchMouseMove(g, 1, 5); + assert.equal(4, g.getSelection()); + + // Mouse up x=0.7 + DygraphOps.dispatchMouseMove(g, 0.7, 1); + assert.equal(1, g.getSelection()); + + DygraphOps.dispatchMouseMove(g, 0.7, 2); + assert.equal(2, g.getSelection()); + + DygraphOps.dispatchMouseMove(g, 0.7, 3); + assert.equal(3, g.getSelection()); + + DygraphOps.dispatchMouseMove(g, 0.7, 4); + assert.equal(2, g.getSelection()); + + DygraphOps.dispatchMouseMove(g, 0.7, 5); + assert.equal(3, g.getSelection()); + +}); + +/** + * Should behave like euclidian + * + * selectMode: closest-x + * highlightSeriesOpts: yes + * stacked: no + * series locked: no + */ +it('closest-x/with highlight/not stacked/no series lock', () => { + + var g = makeGraph(TEST_SERIES, { + selectMode: 'closest-x', + highlightSeriesOpts: {strokeWidth: 2} + }); + + // Mouse along y=1 + DygraphOps.dispatchMouseMove(g, 0, 1); + assert.equal(0, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.2, 1); + assert.equal(0, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.4, 1); + assert.equal(1, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.6, 1); + assert.equal(1, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.8, 1); + assert.equal(4, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 1, 1); + assert.equal(4, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + // Mouse along y=5 + DygraphOps.dispatchMouseMove(g, 0, 5); + assert.equal(0, g.getSelection()); + assert.equal('Y2', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.2, 5); + assert.equal(0, g.getSelection()); + assert.equal('Y2', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.4, 5); + assert.equal(3, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.6, 5); + assert.equal(3, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.8, 5); + assert.equal(3, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 1, 5); + assert.equal(4, g.getSelection()); + assert.equal('Y2', g.highlightSet_); + + // Mouse up x=0.7 + DygraphOps.dispatchMouseMove(g, 0.7, 1); + assert.equal(1, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.7, 2); + assert.equal(2, g.getSelection()); + assert.equal('Y2', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.7, 3); + assert.equal(3, g.getSelection()); + assert.equal('Y2', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.7, 4); + assert.equal(2, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.7, 5); + assert.equal(3, g.getSelection()); + assert.equal('Y1', g.highlightSet_); +}); + + +/** + * selectMode: euclidian + * highlightSeriesOpts: yes + * stacked: no + * series locked: no + */ +it('euclidian/with highlight/not stacked/no series lock', () => { + + var g = makeGraph(TEST_SERIES, { + selectMode: 'euclidian', + highlightSeriesOpts: {strokeWidth: 2} + }); + + // Mouse along y=1 + DygraphOps.dispatchMouseMove(g, 0, 1); + assert.equal(0, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.2, 1); + assert.equal(0, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.4, 1); + assert.equal(1, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.6, 1); + assert.equal(1, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.8, 1); + assert.equal(4, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 1, 1); + assert.equal(4, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + // Mouse along y=5 + DygraphOps.dispatchMouseMove(g, 0, 5); + assert.equal(0, g.getSelection()); + assert.equal('Y2', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.2, 5); + assert.equal(0, g.getSelection()); + assert.equal('Y2', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.4, 5); + assert.equal(3, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.6, 5); + assert.equal(3, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.8, 5); + assert.equal(3, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 1, 5); + assert.equal(4, g.getSelection()); + assert.equal('Y2', g.highlightSet_); + + // Mouse up x=0.7 + DygraphOps.dispatchMouseMove(g, 0.7, 1); + assert.equal(1, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.7, 2); + assert.equal(2, g.getSelection()); + assert.equal('Y2', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.7, 3); + assert.equal(3, g.getSelection()); + assert.equal('Y2', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.7, 4); + assert.equal(2, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.7, 5); + assert.equal(3, g.getSelection()); + assert.equal('Y1', g.highlightSet_); +}); + +/** + * selectMode: closest-x + * highlightSeriesOpts: no + * stacked: yes + * series locked: no + */ +it('closest-x/no highlight/is stacked/no series lock', () => { + + var g = makeGraph(TEST_SERIES_NODUP, { + selectMode: 'closest-x', + stackedGraph: true + }); + + // Mouse along y=1 + DygraphOps.dispatchMouseMove(g, 0, 1); + assert.equal(0, g.getSelection()); + + DygraphOps.dispatchMouseMove(g, 0.2, 1); + assert.equal(0, g.getSelection()); + + DygraphOps.dispatchMouseMove(g, 0.4, 1); + assert.equal(1, g.getSelection()); + + DygraphOps.dispatchMouseMove(g, 0.6, 1); + assert.equal(1, g.getSelection()); + + DygraphOps.dispatchMouseMove(g, 0.8, 1); + assert.equal(2, g.getSelection()); + + DygraphOps.dispatchMouseMove(g, 1, 1); + assert.equal(3, g.getSelection()); + + // Mouse along y=7 + DygraphOps.dispatchMouseMove(g, 0, 7); + assert.equal(0, g.getSelection()); + + DygraphOps.dispatchMouseMove(g, 0.2, 7); + assert.equal(0, g.getSelection()); + + DygraphOps.dispatchMouseMove(g, 0.4, 7); + assert.equal(1, g.getSelection()); + + DygraphOps.dispatchMouseMove(g, 0.6, 7); + assert.equal(1, g.getSelection()); + + DygraphOps.dispatchMouseMove(g, 0.8, 7); + assert.equal(2, g.getSelection()); + + DygraphOps.dispatchMouseMove(g, 1, 7); + assert.equal(3, g.getSelection()); + + // Mouse up x=0.7 + DygraphOps.dispatchMouseMove(g, 0.7, 1); + assert.equal(2, g.getSelection()); + + DygraphOps.dispatchMouseMove(g, 0.7, 2); + assert.equal(2, g.getSelection()); + + DygraphOps.dispatchMouseMove(g, 0.7, 3); + assert.equal(2, g.getSelection()); + + DygraphOps.dispatchMouseMove(g, 0.7, 4); + assert.equal(2, g.getSelection()); + + DygraphOps.dispatchMouseMove(g, 0.7, 5); + assert.equal(2, g.getSelection()); + +}); + +/** + * selectMode: euclidian + * highlightSeriesOpts: no + * stacked: yes + * series locked: no + */ +it('euclidian/no highlight/is stacked/no series lock', () => { + + var g = makeGraph(TEST_SERIES_NODUP, { + selectMode: 'euclidian', + stackedGraph: true + }); + + // Mouse along y=1 + DygraphOps.dispatchMouseMove(g, 0, 1); + assert.equal(0, g.getSelection()); + + DygraphOps.dispatchMouseMove(g, 0.2, 1); + assert.equal(0, g.getSelection()); + + DygraphOps.dispatchMouseMove(g, 0.4, 1); + assert.equal(1, g.getSelection()); + + DygraphOps.dispatchMouseMove(g, 0.6, 1); + assert.equal(2, g.getSelection()); + + DygraphOps.dispatchMouseMove(g, 0.8, 1); + assert.equal(2, g.getSelection()); + + DygraphOps.dispatchMouseMove(g, 1, 1); + assert.equal(3, g.getSelection()); + + // Mouse along y=7 + DygraphOps.dispatchMouseMove(g, 0, 7); + assert.equal(0, g.getSelection()); + + DygraphOps.dispatchMouseMove(g, 0.2, 7); + assert.equal(0, g.getSelection()); + + DygraphOps.dispatchMouseMove(g, 0.4, 7); + assert.equal(2, g.getSelection()); + + DygraphOps.dispatchMouseMove(g, 0.6, 7); + assert.equal(2, g.getSelection()); + + DygraphOps.dispatchMouseMove(g, 0.8, 7); + assert.equal(2, g.getSelection()); + + DygraphOps.dispatchMouseMove(g, 1, 7); + assert.equal(3, g.getSelection()); + + // Mouse up x=0.7 + DygraphOps.dispatchMouseMove(g, 0.7, 1); + assert.equal(2, g.getSelection()); + + DygraphOps.dispatchMouseMove(g, 0.7, 2); + assert.equal(2, g.getSelection()); + + DygraphOps.dispatchMouseMove(g, 0.7, 3); + assert.equal(2, g.getSelection()); + + DygraphOps.dispatchMouseMove(g, 0.7, 4); + assert.equal(2, g.getSelection()); + + DygraphOps.dispatchMouseMove(g, 0.7, 5); + assert.equal(2, g.getSelection()); +}); + +/** + * selectMode: closest-x + * highlightSeriesOpts: yes + * stacked: yes + * series locked: no + */ +it('closest-x/with highlight/is stacked/no series lock', () => { + + var g = makeGraph(TEST_SERIES_NODUP, { + selectMode: 'closest-x', + stackedGraph: true, + highlightSeriesOpts: {strokeWidth: 2} + }); + + // Mouse along y=1 + DygraphOps.dispatchMouseMove(g, 0, 1); + assert.equal(0, g.getSelection()); + assert.equal('Y2', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.2, 1); + assert.equal(0, g.getSelection()); + assert.equal('Y2', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.4, 1); + assert.equal(1, g.getSelection()); + assert.equal('Y2', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.6, 1); + assert.equal(1, g.getSelection()); + assert.equal('Y2', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.8, 1); + assert.equal(2, g.getSelection()); + assert.equal('Y2', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 1, 1); + assert.equal(3, g.getSelection()); + assert.equal('Y2', g.highlightSet_); + + // Mouse along y=7 + DygraphOps.dispatchMouseMove(g, 0, 7); + assert.equal(0, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.2, 7); + assert.equal(0, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.4, 7); + assert.equal(1, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.6, 7); + assert.equal(1, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.8, 7); + assert.equal(2, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 1, 7); + assert.equal(3, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + // Mouse up x=0.7 + DygraphOps.dispatchMouseMove(g, 0.7, 1); + assert.equal(2, g.getSelection()); + assert.equal('Y2', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.7, 2); + assert.equal(2, g.getSelection()); + assert.equal('Y2', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.7, 3); + assert.equal(2, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.7, 4); + assert.equal(2, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.7, 5); + assert.equal(2, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + +}); + +/** + * selectMode: euclidian + * highlightSeriesOpts: yes + * stacked: yes + * series locked: no + */ +it('euclidian/with highlight/is stacked/no series lock', () => { + + var g = makeGraph(TEST_SERIES_NODUP, { + selectMode: 'euclidian', + stackedGraph: true, + highlightSeriesOpts: {strokeWidth: 2} + }); + + // Mouse along y=1 + DygraphOps.dispatchMouseMove(g, 0, 1); + assert.equal(0, g.getSelection()); + assert.equal('Y2', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.2, 1); + assert.equal(0, g.getSelection()); + assert.equal('Y2', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.4, 1); + assert.equal(1, g.getSelection()); + assert.equal('Y2', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.6, 1); + assert.equal(2, g.getSelection()); + assert.equal('Y2', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.8, 1); + assert.equal(2, g.getSelection()); + assert.equal('Y2', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 1, 1); + assert.equal(3, g.getSelection()); + assert.equal('Y2', g.highlightSet_); + + // Mouse along y=7 + DygraphOps.dispatchMouseMove(g, 0, 7); + assert.equal(0, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.2, 7); + assert.equal(0, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.4, 7); + assert.equal(2, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.6, 7); + assert.equal(2, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.8, 7); + assert.equal(2, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 1, 7); + assert.equal(3, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + // Mouse up x=0.7 + DygraphOps.dispatchMouseMove(g, 0.7, 1); + assert.equal(2, g.getSelection()); + assert.equal('Y2', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.7, 2); + assert.equal(2, g.getSelection()); + assert.equal('Y2', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.7, 3); + assert.equal(1, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.7, 4); + assert.equal(1, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.7, 5); + assert.equal(2, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + +}); + +/** + * selectMode: closest-x + * highlightSeriesOpts: no + * stacked: no + * series locked: yes + */ +it('closest-x/no highlight/not stacked/with series lock', () => { + + var g = makeGraph(TEST_SERIES, { + selectMode: 'closest-x', + }); + + // Lock the series + g.setSelection(0, 'Y1', true); + + // Mouse along y=1 + DygraphOps.dispatchMouseMove(g, 0, 1); + assert.equal(0, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.2, 1); + assert.equal(0, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.4, 1); + assert.equal(1, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.6, 1); + assert.equal(1, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.8, 1); + assert.equal(2, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 1, 1); + assert.equal(4, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + // Mouse along y=5 + DygraphOps.dispatchMouseMove(g, 0, 5); + assert.equal(0, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.2, 5); + assert.equal(0, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.4, 5); + assert.equal(1, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.6, 5); + assert.equal(1, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.8, 5); + assert.equal(2, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 1, 5); + assert.equal(4, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + // Mouse up x=0.7 + DygraphOps.dispatchMouseMove(g, 0.7, 1); + assert.equal(2, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.7, 2); + assert.equal(2, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.7, 3); + assert.equal(2, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.7, 4); + assert.equal(2, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.7, 5); + assert.equal(2, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + +}); + +/** + * selectMode: euclidian + * highlightSeriesOpts: no + * stacked: no + * series locked: yes + */ +it('euclidian/no highlight/not stacked/with series lock', () => { + + var g = makeGraph(TEST_SERIES, { + selectMode: 'euclidian', + }); + + // Lock the series + g.setSelection(0, 'Y1', true); + + // Mouse along y=1 + DygraphOps.dispatchMouseMove(g, 0, 1); + assert.equal(0, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.2, 1); + assert.equal(0, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.4, 1); + assert.equal(1, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.6, 1); + assert.equal(1, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.8, 1); + assert.equal(4, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 1, 1); + assert.equal(4, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + // Mouse along y=5 + DygraphOps.dispatchMouseMove(g, 0, 5); + assert.equal(0, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.2, 5); + assert.equal(3, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.4, 5); + assert.equal(3, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.6, 5); + assert.equal(3, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.8, 5); + assert.equal(3, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 1, 5); + assert.equal(3, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + // Mouse up x=0.7 + DygraphOps.dispatchMouseMove(g, 0.7, 1); + assert.equal(1, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.7, 2); + assert.equal(1, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.7, 3); + assert.equal(2, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.7, 4); + assert.equal(2, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.7, 5); + assert.equal(3, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + +}); + +/** + * selectMode: closest-x + * highlightSeriesOpts: yes + * stacked: no + * series locked: yes + */ +it('closest-x/with highlight/not stacked/with series lock', () => { + + var g = makeGraph(TEST_SERIES, { + selectMode: 'closest-x', + highlightSeriesOpts: {strokeWidth: 2} + }); + + // Lock the series + g.setSelection(0, 'Y1', true); + + // Mouse along y=1 + DygraphOps.dispatchMouseMove(g, 0, 1); + assert.equal(0, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.2, 1); + assert.equal(0, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.4, 1); + assert.equal(1, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.6, 1); + assert.equal(1, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.8, 1); + assert.equal(2, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 1, 1); + assert.equal(4, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + // Mouse along y=5 + DygraphOps.dispatchMouseMove(g, 0, 5); + assert.equal(0, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.2, 5); + assert.equal(0, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.4, 5); + assert.equal(1, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.6, 5); + assert.equal(1, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.8, 5); + assert.equal(2, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 1, 5); + assert.equal(4, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + // Mouse up x=0.7 + DygraphOps.dispatchMouseMove(g, 0.7, 1); + assert.equal(2, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.7, 2); + assert.equal(2, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.7, 3); + assert.equal(2, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.7, 4); + assert.equal(2, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.7, 5); + assert.equal(2, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + +}); + +/** + * selectMode: euclidian + * highlightSeriesOpts: yes + * stacked: no + * series locked: yes + */ +it('euclidian/with highlight/not stacked/with series lock', () => { + + var g = makeGraph(TEST_SERIES, { + selectMode: 'euclidian', + highlightSeriesOpts: {strokeWidth: 2} + }); + + // Lock the series + g.setSelection(0, 'Y1', true); + + // Mouse along y=1 + DygraphOps.dispatchMouseMove(g, 0, 1); + assert.equal(0, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.2, 1); + assert.equal(0, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.4, 1); + assert.equal(1, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.6, 1); + assert.equal(1, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.8, 1); + assert.equal(4, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 1, 1); + assert.equal(4, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + // Mouse along y=5 + DygraphOps.dispatchMouseMove(g, 0, 5); + assert.equal(0, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.2, 5); + assert.equal(3, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.4, 5); + assert.equal(3, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.6, 5); + assert.equal(3, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.8, 5); + assert.equal(3, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 1, 5); + assert.equal(3, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + // Mouse up x=0.7 + DygraphOps.dispatchMouseMove(g, 0.7, 1); + assert.equal(1, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.7, 2); + assert.equal(1, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.7, 3); + assert.equal(2, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.7, 4); + assert.equal(2, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.7, 5); + assert.equal(3, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + +}); + +/** + * selectMode: closest-x + * highlightSeriesOpts: no + * stacked: yes + * series locked: yes + */ +it('closest-x/no highlight/is stacked/with series lock', () => { + + var g = makeGraph(TEST_SERIES_NODUP, { + selectMode: 'closest-x', + stackedGraph: true + }); + + // Lock the series + g.setSelection(0, 'Y1', true); + + // Mouse along y=1 + DygraphOps.dispatchMouseMove(g, 0, 1); + assert.equal(0, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.2, 1); + assert.equal(0, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.4, 1); + assert.equal(1, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.6, 1); + assert.equal(1, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.8, 1); + assert.equal(2, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 1, 1); + assert.equal(3, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + // Mouse along y=5 + DygraphOps.dispatchMouseMove(g, 0, 5); + assert.equal(0, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.2, 5); + assert.equal(0, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.4, 5); + assert.equal(1, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.6, 5); + assert.equal(1, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.8, 5); + assert.equal(2, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 1, 5); + assert.equal(3, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + // Mouse up x=0.7 + DygraphOps.dispatchMouseMove(g, 0.7, 1); + assert.equal(2, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.7, 2); + assert.equal(2, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.7, 3); + assert.equal(2, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.7, 4); + assert.equal(2, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.7, 5); + assert.equal(2, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + +}); + +/** + * selectMode: euclidian + * highlightSeriesOpts: no + * stacked: yes + * series locked: yes + */ +it('euclidian/no highlight/is stacked/with series lock', () => { + + var g = makeGraph(TEST_SERIES_NODUP, { + selectMode: 'euclidian', + stackedGraph: true + }); + + // Lock the series + g.setSelection(0, 'Y1', true); + + // Mouse along y=1 + DygraphOps.dispatchMouseMove(g, 0, 1); + assert.equal(0, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.2, 1); + assert.equal(0, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.4, 1); + assert.equal(1, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.6, 1); + assert.equal(1, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.8, 1); + assert.equal(1, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 1, 1); + assert.equal(3, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + // Mouse along y=5 + DygraphOps.dispatchMouseMove(g, 0, 5); + assert.equal(0, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.2, 5); + assert.equal(0, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.4, 5); + assert.equal(1, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.6, 5); + assert.equal(1, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.8, 5); + assert.equal(3, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 1, 5); + assert.equal(3, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + // Mouse up x=0.7 + DygraphOps.dispatchMouseMove(g, 0.7, 1); + assert.equal(1, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.7, 2); + assert.equal(1, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.7, 3); + assert.equal(1, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.7, 4); + assert.equal(1, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.7, 5); + assert.equal(2, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + +}); + +/** + * selectMode: closest-x + * highlightSeriesOpts: yes + * stacked: yes + * series locked: yes + */ +it('closest-x/with highlight/is stacked/with series lock', () => { + + var g = makeGraph(TEST_SERIES_NODUP, { + selectMode: 'closest-x', + stackedGraph: true, + highlightSeriesOpts: {strokeWidth: 2} + }); + + // Lock the series + g.setSelection(0, 'Y1', true); + + // Mouse along y=1 + DygraphOps.dispatchMouseMove(g, 0, 1); + assert.equal(0, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.2, 1); + assert.equal(0, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.4, 1); + assert.equal(1, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.6, 1); + assert.equal(1, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.8, 1); + assert.equal(2, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 1, 1); + assert.equal(3, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + // Mouse along y=5 + DygraphOps.dispatchMouseMove(g, 0, 5); + assert.equal(0, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.2, 5); + assert.equal(0, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.4, 5); + assert.equal(1, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.6, 5); + assert.equal(1, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.8, 5); + assert.equal(2, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 1, 5); + assert.equal(3, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + // Mouse up x=0.7 + DygraphOps.dispatchMouseMove(g, 0.7, 1); + assert.equal(2, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.7, 2); + assert.equal(2, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.7, 3); + assert.equal(2, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.7, 4); + assert.equal(2, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.7, 5); + assert.equal(2, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + +}); + +/** + * selectMode: euclidian + * highlightSeriesOpts: yes + * stacked: yes + * series locked: yes + */ +it('euclidian/with highlight/is stacked/with series lock', () => { + + var g = makeGraph(TEST_SERIES_NODUP, { + selectMode: 'euclidian', + stackedGraph: true, + highlightSeriesOpts: {strokeWidth: 2} + }); + + // Lock the series + g.setSelection(0, 'Y1', true); + + // Mouse along y=1 + DygraphOps.dispatchMouseMove(g, 0, 1); + assert.equal(0, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.2, 1); + assert.equal(0, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.4, 1); + assert.equal(1, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.6, 1); + assert.equal(1, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.8, 1); + assert.equal(1, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 1, 1); + assert.equal(3, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + // Mouse along y=5 + DygraphOps.dispatchMouseMove(g, 0, 5); + assert.equal(0, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.2, 5); + assert.equal(0, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.4, 5); + assert.equal(1, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.6, 5); + assert.equal(1, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.8, 5); + assert.equal(3, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 1, 5); + assert.equal(3, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + // Mouse up x=0.7 + DygraphOps.dispatchMouseMove(g, 0.7, 1); + assert.equal(1, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.7, 2); + assert.equal(1, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.7, 3); + assert.equal(1, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.7, 4); + assert.equal(1, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + + DygraphOps.dispatchMouseMove(g, 0.7, 5); + assert.equal(2, g.getSelection()); + assert.equal('Y1', g.highlightSet_); + +}); +}); diff --git a/src/dygraph-default-attrs.js b/src/dygraph-default-attrs.js index 5ab35d463..3e889d830 100644 --- a/src/dygraph-default-attrs.js +++ b/src/dygraph-default-attrs.js @@ -86,6 +86,8 @@ var DEFAULT_ATTRS = { rangeSelectorAlpha: 0.6, showInRangeSelector: null, + selectMode: 'closest-x', + // The ordering here ensures that central lines always appear above any // fill bars/error bars. plotter: [ diff --git a/src/dygraph-options-reference.js b/src/dygraph-options-reference.js index f286acf91..66c88bf14 100644 --- a/src/dygraph-options-reference.js +++ b/src/dygraph-options-reference.js @@ -849,7 +849,13 @@ OPTIONS_REFERENCE = // "default": "(depends on data)", "labels": ["Data"], "type": "Dygraph.DataHandler", - "description": "Custom DataHandler. This is an advanced customisation. See docs/datahandler-proposal.pdf." + "description": "Custom DataHandler. This is an advanced customization.See docs/datahandler-proposal.pdf." + }, + "selectMode": { + "default": "closest-x", + "labels": ["Interactive Elements"], + "type": "string", + "description": "Defines how points are selected. Valid values are 'closest-x' and 'euclidian'. 'closest-x' selects the nearest point along the X axis, while 'euclidian' selects the closest point in any direction. If highlightSeriesOpts is set, this has no effect." } } ; // diff --git a/src/dygraph.js b/src/dygraph.js index 57da88ee4..bd7337e21 100644 --- a/src/dygraph.js +++ b/src/dygraph.js @@ -1519,14 +1519,18 @@ Dygraph.prototype.eventToDomCoords = function(event) { /** * Given a canvas X coordinate, find the closest row. * @param {number} domX graph-relative DOM X coordinate + * @param {seriesName} optional Restrict the search to the named series * Returns {number} row number. * @private */ -Dygraph.prototype.findClosestRow = function(domX) { +Dygraph.prototype.findClosestRow = function(domX, seriesName) { var minDistX = Infinity; var closestRow = -1; var sets = this.layout_.points; for (var i = 0; i < sets.length; i++) { + if (seriesName !== undefined && + this.layout_.setNames[i] != seriesName) continue; + var points = sets[i]; var len = points.length; for (var j = 0; j < len; j++) { @@ -1552,13 +1556,17 @@ Dygraph.prototype.findClosestRow = function(domX) { * * @param {number} domX graph-relative DOM X coordinate * @param {number} domY graph-relative DOM Y coordinate + * @param {seriesName} optional Restrict the search to the named series * Returns: {row, seriesName, point} * @private */ -Dygraph.prototype.findClosestPoint = function(domX, domY) { +Dygraph.prototype.findClosestPoint = function(domX, domY, seriesName) { var minDist = Infinity; var dist, dx, dy, point, closestPoint, closestSeries, closestRow; for ( var setIdx = this.layout_.points.length - 1 ; setIdx >= 0 ; --setIdx ) { + if (seriesName !== undefined && + this.layout_.setNames[setIdx] != seriesName) continue; + var points = this.layout_.points[setIdx]; for (var i = 0; i < points.length; ++i) { point = points[i]; @@ -1656,19 +1664,49 @@ Dygraph.prototype.mouseMove_ = function(event) { var canvasx = canvasCoords[0]; var canvasy = canvasCoords[1]; - var highlightSeriesOpts = this.getOption("highlightSeriesOpts"); var selectionChanged = false; - if (highlightSeriesOpts && !this.isSeriesLocked()) { - var closest; - if (this.getBooleanOption("stackedGraph")) { - closest = this.findStackedPoint(canvasx, canvasy); - } else { - closest = this.findClosestPoint(canvasx, canvasy); - } - selectionChanged = this.setSelection(closest.row, closest.seriesName); + + var searchMode = this.getOption("selectMode"); + var searchSeries = undefined; + var highlightSeries = undefined; + + // If the series is locked, we can only search and highlight + // that series + if (this.isSeriesLocked()) { + searchSeries = this.highlightSet_; + if (this.getOption("highlightSeriesOpts")) { + highlightSeries = searchSeries; + } + + // If the graph is stacked AND we want to highlight the + // series, the selection will be based on the area + // of the graph under each series. Otherwise + // stacked graphs behave the same as non-stacked + } else if (this.getBooleanOption("stackedGraph") && + this.getOption("highlightSeriesOpts")) { + + searchSeries = this.findStackedPoint(canvasx, canvasy).seriesName; + highlightSeries = searchSeries; + + // If series highlight is set on its own, we switch to + // euclidian mode since we want to highlight the closest + // series to the mouse + } else if (this.getOption("highlightSeriesOpts")) { + searchMode = 'euclidian'; + } + + if (searchMode == 'euclidian') { + var closestPoint = this.findClosestPoint(canvasx, canvasy, searchSeries); + if (this.getOption("highlightSeriesOpts")) { + highlightSeries = closestPoint.seriesName; + } + + selectionChanged = this.setSelection(closestPoint.row, highlightSeries); } else { - var idx = this.findClosestRow(canvasx); - selectionChanged = this.setSelection(idx); + selectionChanged = this.setSelection( + this.findClosestRow(canvasx, searchSeries), + highlightSeries + ); } var callback = this.getFunctionOption("highlightCallback"); @@ -1943,17 +1981,9 @@ Dygraph.prototype.clearSelection = function() { Dygraph.prototype.getSelection = function() { if (!this.selPoints_ || this.selPoints_.length < 1) { return -1; + } else { + return this.selPoints_[0].idx; } - - for (var setIdx = 0; setIdx < this.layout_.points.length; setIdx++) { - var points = this.layout_.points[setIdx]; - for (var row = 0; row < points.length; row++) { - if (points[row].x == this.selPoints_[0].x) { - return points[row].idx; - } - } - } - return -1; }; /**