From 2afb476ee3c7c8b866b4ae36cb3c4c57f5b25853 Mon Sep 17 00:00:00 2001 From: archmoj Date: Thu, 6 May 2021 18:12:29 -0400 Subject: [PATCH 1/2] set default hovermode to closest --- src/components/fx/hovermode_defaults.js | 36 +++---------------------- src/components/fx/layout_attributes.js | 10 ++----- src/components/fx/layout_defaults.js | 4 +-- src/plots/cartesian/layout_defaults.js | 2 +- 4 files changed, 8 insertions(+), 44 deletions(-) diff --git a/src/components/fx/hovermode_defaults.js b/src/components/fx/hovermode_defaults.js index 15071ddcfb9..e9a038bc19e 100644 --- a/src/components/fx/hovermode_defaults.js +++ b/src/components/fx/hovermode_defaults.js @@ -3,7 +3,7 @@ var Lib = require('../../lib'); var layoutAttributes = require('./layout_attributes'); -module.exports = function handleHoverModeDefaults(layoutIn, layoutOut, fullData) { +module.exports = function handleHoverModeDefaults(layoutIn, layoutOut) { function coerce(attr, dflt) { // don't coerce if it is already coerced in other place e.g. in cartesian defaults if(layoutOut[attr] !== undefined) return layoutOut[attr]; @@ -11,36 +11,6 @@ module.exports = function handleHoverModeDefaults(layoutIn, layoutOut, fullData) return Lib.coerce(layoutIn, layoutOut, layoutAttributes, attr, dflt); } - var clickmode = coerce('clickmode'); - - var hovermodeDflt; - if(layoutOut._has('cartesian')) { - if(clickmode.indexOf('select') > -1) { - hovermodeDflt = 'closest'; - } else { - // flag for 'horizontal' plots: - // determines the state of the mode bar 'compare' hovermode button - layoutOut._isHoriz = isHoriz(fullData, layoutOut); - hovermodeDflt = layoutOut._isHoriz ? 'y' : 'x'; - } - } else hovermodeDflt = 'closest'; - - return coerce('hovermode', hovermodeDflt); + coerce('clickmode'); + return coerce('hovermode'); }; - -function isHoriz(fullData, fullLayout) { - var stackOpts = fullLayout._scatterStackOpts || {}; - - for(var i = 0; i < fullData.length; i++) { - var trace = fullData[i]; - var subplot = trace.xaxis + trace.yaxis; - var subplotStackOpts = stackOpts[subplot] || {}; - var groupOpts = subplotStackOpts[trace.stackgroup] || {}; - - if(trace.orientation !== 'h' && groupOpts.orientation !== 'h') { - return false; - } - } - - return true; -} diff --git a/src/components/fx/layout_attributes.js b/src/components/fx/layout_attributes.js index 756e5f79435..38e068c441f 100644 --- a/src/components/fx/layout_attributes.js +++ b/src/components/fx/layout_attributes.js @@ -60,6 +60,7 @@ module.exports = { hovermode: { valType: 'enumerated', values: ['x', 'y', 'closest', false, 'x unified', 'y unified'], + dflt: 'closest', editType: 'modebar', description: [ 'Determines the mode of hover interactions.', @@ -72,14 +73,7 @@ module.exports = { 'multiple points at the closest x- (or y-) coordinate within the `hoverdistance`', 'with the caveat that no more than one hoverlabel will appear per trace.', 'In this mode, spikelines are enabled by default perpendicular to the specified axis.', - 'If false, hover interactions are disabled.', - 'If `clickmode` includes the *select* flag,', - '`hovermode` defaults to *closest*.', - 'If `clickmode` lacks the *select* flag,', - 'it defaults to *x* or *y* (depending on the trace\'s', - '`orientation` value) for plots based on', - 'cartesian coordinates. For anything else the default', - 'value is *closest*.', + 'If false, hover interactions are disabled.' ].join(' ') }, hoverdistance: { diff --git a/src/components/fx/layout_defaults.js b/src/components/fx/layout_defaults.js index 1d28e242400..c011d4bd0a6 100644 --- a/src/components/fx/layout_defaults.js +++ b/src/components/fx/layout_defaults.js @@ -6,12 +6,12 @@ var layoutAttributes = require('./layout_attributes'); var handleHoverModeDefaults = require('./hovermode_defaults'); var handleHoverLabelDefaults = require('./hoverlabel_defaults'); -module.exports = function supplyLayoutDefaults(layoutIn, layoutOut, fullData) { +module.exports = function supplyLayoutDefaults(layoutIn, layoutOut) { function coerce(attr, dflt) { return Lib.coerce(layoutIn, layoutOut, layoutAttributes, attr, dflt); } - var hoverMode = handleHoverModeDefaults(layoutIn, layoutOut, fullData); + var hoverMode = handleHoverModeDefaults(layoutIn, layoutOut); if(hoverMode) { coerce('hoverdistance'); coerce('spikedistance', isUnifiedHover(hoverMode) ? -1 : undefined); diff --git a/src/plots/cartesian/layout_defaults.js b/src/plots/cartesian/layout_defaults.js index c500997541b..f69d3ef04d3 100644 --- a/src/plots/cartesian/layout_defaults.js +++ b/src/plots/cartesian/layout_defaults.js @@ -200,7 +200,7 @@ module.exports = function supplyLayoutDefaults(layoutIn, layoutOut, fullData) { } } - var hovermode = handleHoverModeDefaults(layoutIn, layoutOut, fullData); + var hovermode = handleHoverModeDefaults(layoutIn, layoutOut); var unifiedHover = isUnifiedHover(hovermode); // first pass creates the containers, determines types, and handles most of the settings From cdb8d9e92d35424260bf04e4a00820d7f5f7733a Mon Sep 17 00:00:00 2001 From: archmoj Date: Sat, 8 May 2021 21:08:47 -0400 Subject: [PATCH 2/2] adjust jasmine tests with closest hovermode by default --- test/jasmine/tests/axes_test.js | 2 + test/jasmine/tests/bar_test.js | 1 + test/jasmine/tests/box_test.js | 29 +++--- test/jasmine/tests/cartesian_interact_test.js | 1 + test/jasmine/tests/finance_test.js | 1 + test/jasmine/tests/funnel_test.js | 3 + test/jasmine/tests/fx_test.js | 17 ++-- test/jasmine/tests/gl2d_click_test.js | 1 + test/jasmine/tests/hover_label_test.js | 90 ++++++++----------- test/jasmine/tests/hover_spikeline_test.js | 1 + test/jasmine/tests/modebar_test.js | 16 ++-- test/jasmine/tests/plot_api_react_test.js | 2 +- test/jasmine/tests/scatter_test.js | 1 + test/jasmine/tests/splom_test.js | 13 +-- test/jasmine/tests/violin_test.js | 24 ++--- test/jasmine/tests/waterfall_test.js | 4 +- 16 files changed, 102 insertions(+), 104 deletions(-) diff --git a/test/jasmine/tests/axes_test.js b/test/jasmine/tests/axes_test.js index f3e3e7968d2..0c336d948fa 100644 --- a/test/jasmine/tests/axes_test.js +++ b/test/jasmine/tests/axes_test.js @@ -6645,6 +6645,7 @@ describe('Test tickformatstops:', function() { beforeEach(function() { gd = createGraphDiv(); mockCopy = Lib.extendDeep({}, mock); + mockCopy.layout.hovermode = 'x'; }); afterEach(destroyGraphDiv); @@ -6951,6 +6952,7 @@ describe('category preservation tests on gd passed to Plotly.react()', function( x: ['a', 'b', 'c', 'd'] }], layout: { + hovermode: 'x', width: 500, height: 500 } diff --git a/test/jasmine/tests/bar_test.js b/test/jasmine/tests/bar_test.js index 41d826f93c0..860a0391110 100644 --- a/test/jasmine/tests/bar_test.js +++ b/test/jasmine/tests/bar_test.js @@ -2416,6 +2416,7 @@ describe('bar hover', function() { t.type = 'bar'; t.hovertemplate = '%{y}'; }); + mock.layout.hovermode = 'x'; function _hover() { var evt = { xpx: 125, ypx: 150 }; diff --git a/test/jasmine/tests/box_test.js b/test/jasmine/tests/box_test.js index 90ea550a3f8..ac271d4df97 100644 --- a/test/jasmine/tests/box_test.js +++ b/test/jasmine/tests/box_test.js @@ -739,6 +739,10 @@ describe('Test box hover:', function() { [{ desc: 'base', + patch: function(fig) { + fig.layout.hovermode = 'x'; + return fig; + }, nums: ['median: 0.55', 'min: 0', 'q1: 0.3', 'q3: 0.6', 'max: 0.7'], name: ['radishes', '', '', '', ''], axis: 'day 1' @@ -748,6 +752,7 @@ describe('Test box hover:', function() { fig.data.forEach(function(trace) { trace.boxmean = true; }); + fig.layout.hovermode = 'x'; return fig; }, nums: ['median: 0.55', 'min: 0', 'q1: 0.3', 'q3: 0.6', 'max: 0.7', 'mean: 0.45'], @@ -759,6 +764,7 @@ describe('Test box hover:', function() { fig.data.forEach(function(trace) { trace.boxmean = 'sd'; }); + fig.layout.hovermode = 'x'; return fig; }, nums: [ @@ -770,6 +776,10 @@ describe('Test box hover:', function() { }, { desc: 'with boxpoints fences', mock: require('@mocks/boxplots_outliercolordflt.json'), + patch: function(fig) { + fig.layout.hovermode = 'x'; + return fig; + }, pos: [350, 200], nums: [ 'median: 8.15', 'min: 0.75', 'q1: 6.8', @@ -780,6 +790,7 @@ describe('Test box hover:', function() { }, { desc: 'with overlaid boxes', patch: function(fig) { + fig.layout.hovermode = 'x'; fig.layout.boxmode = 'overlay'; return fig; }, @@ -799,7 +810,6 @@ describe('Test box hover:', function() { trace.boxpoints = 'all'; trace.hoveron = 'points'; }); - fig.layout.hovermode = 'closest'; fig.layout.xaxis = {range: [-0.565, 1.5]}; return fig; }, @@ -856,7 +866,6 @@ describe('Test box hover:', function() { trace.hoveron = 'points'; trace.text = trace.y.map(function(v) { return 'look:' + v; }); }); - fig.layout.hovermode = 'closest'; fig.layout.xaxis = {range: [-0.565, 1.5]}; return fig; }, @@ -871,7 +880,6 @@ describe('Test box hover:', function() { trace.text = trace.y.map(function(v) { return 'look:' + v; }); trace.hoverinfo = 'text'; }); - fig.layout.hovermode = 'closest'; fig.layout.xaxis = {range: [-0.565, 1.5]}; return fig; }, @@ -887,7 +895,6 @@ describe('Test box hover:', function() { trace.hovertext = trace.y.map(function(v) { return 'look:' + v; }); trace.hoverinfo = 'text'; }); - fig.layout.hovermode = 'closest'; fig.layout.xaxis = {range: [-0.565, 1.5]}; return fig; }, @@ -896,6 +903,10 @@ describe('Test box hover:', function() { }, { desc: 'orientation:h | hovermode:y', mock: require('@mocks/box_grouped_horz.json'), + patch: function(fig) { + fig.layout.hovermode = 'y'; + return fig; + }, pos: [430, 130], nums: [ 'max: 1', 'mean ± σ: 0.6833333 ± 0.2409472', 'min: 0.3', @@ -906,10 +917,6 @@ describe('Test box hover:', function() { }, { desc: 'orientation:h | hovermode:closest', mock: require('@mocks/box_grouped_horz.json'), - patch: function(fig) { - fig.layout.hovermode = 'closest'; - return fig; - }, pos: [430, 130], nums: [ '(max: 1, day 2)', '(mean ± σ: 0.6833333 ± 0.2409472, day 2)', '(min: 0.3, day 2)', @@ -927,7 +934,6 @@ describe('Test box hover:', function() { y: [13.1, 14.2, 14, 13, 13.3] }], layout: { - hovermode: 'closest', xaxis: {range: [1.3775, 2.5]} } }, @@ -942,7 +948,6 @@ describe('Test box hover:', function() { trace.hoveron = 'points'; trace.hovertemplate = '%{y}pt #%{pointNumber}'; }); - fig.layout.hovermode = 'closest'; return fig; }, nums: '0.6', @@ -955,6 +960,7 @@ describe('Test box hover:', function() { y: [1, 2, 2, 3] }], layout: { + hovermode: 'x', yaxis: {range: [1.6, 2.4]}, width: 400, height: 400 @@ -975,6 +981,7 @@ describe('Test box hover:', function() { q3: [3] }], layout: { + hovermode: 'x', width: 400, height: 400 } @@ -997,6 +1004,7 @@ describe('Test box hover:', function() { pointpos: 0 }], layout: { + hovermode: 'x', width: 400, height: 400, margin: {l: 0, t: 0, b: 0, r: 0} @@ -1021,6 +1029,7 @@ describe('Test box hover:', function() { hovertemplate: '%{x} | %{y}%{pointNumber[0]} | %{pointNumber[1]}' }], layout: { + hovermode: 'x', width: 400, height: 400, margin: {l: 0, t: 0, b: 0, r: 0} diff --git a/test/jasmine/tests/cartesian_interact_test.js b/test/jasmine/tests/cartesian_interact_test.js index 8ca5c3a5e7d..9c972bee260 100644 --- a/test/jasmine/tests/cartesian_interact_test.js +++ b/test/jasmine/tests/cartesian_interact_test.js @@ -2300,6 +2300,7 @@ describe('Event data:', function() { } } }], { + hovermode: 'x', width: 500, height: 500 }) diff --git a/test/jasmine/tests/finance_test.js b/test/jasmine/tests/finance_test.js index 6bc3bcbc6d2..2a764d86ead 100644 --- a/test/jasmine/tests/finance_test.js +++ b/test/jasmine/tests/finance_test.js @@ -1321,6 +1321,7 @@ describe('finance trace hover via Fx.hover():', function() { y: [1, 2, 3, 4], type: 'bar' }], { + hovermode: 'x', xaxis: { rangeslider: {visible: false} }, width: 500, height: 500 diff --git a/test/jasmine/tests/funnel_test.js b/test/jasmine/tests/funnel_test.js index c7d10c7c3b5..32c076f005e 100644 --- a/test/jasmine/tests/funnel_test.js +++ b/test/jasmine/tests/funnel_test.js @@ -1423,6 +1423,7 @@ describe('funnel hover', function() { t.orientation = 'v'; t.hoverinfo = 'all'; }); + mock.layout.hovermode = 'x'; function _hover() { var evt = { xpx: 125, ypx: 150 }; @@ -1454,6 +1455,7 @@ describe('funnel hover', function() { t.orientation = 'v'; t.hovertemplate = 'Value: %{y}
Total percentage: %{percentTotal}
Initial percentage: %{percentInitial}
Previous percentage: %{percentPrevious}'; }); + mock.layout.hovermode = 'x'; function _hover() { var evt = { xpx: 125, ypx: 150 }; @@ -1488,6 +1490,7 @@ describe('funnel hover', function() { type: 'funnel' }], layout: { + hovermode: 'x', yaxis: { visible: false, tickprefix: '$', diff --git a/test/jasmine/tests/fx_test.js b/test/jasmine/tests/fx_test.js index 7caf1c10037..add55a20bee 100644 --- a/test/jasmine/tests/fx_test.js +++ b/test/jasmine/tests/fx_test.js @@ -26,11 +26,7 @@ describe('Fx defaults', function() { it('should default (blank version)', function() { var layoutOut = _supply().layout; - // we get a blank cartesian subplot that has no traces... - // so all traces are horizontal -> hovermode defaults to y - // we could add a special case to push this back to x, but - // it seems like it has no practical consequence. - expect(layoutOut.hovermode).toBe('y', 'hovermode to y'); + expect(layoutOut.hovermode).toBe('closest', 'hovermode to closest'); expect(layoutOut.dragmode).toBe('zoom', 'dragmode to zoom'); }); @@ -41,9 +37,8 @@ describe('Fx defaults', function() { }]) .layout; - expect(layoutOut.hovermode).toBe('x', 'hovermode to x'); + expect(layoutOut.hovermode).toBe('closest', 'hovermode to closest'); expect(layoutOut.dragmode).toBe('zoom', 'dragmode to zoom'); - expect(layoutOut._isHoriz).toBe(false, 'isHoriz to false'); }); it('should default (cartesian horizontal version)', function() { @@ -55,9 +50,8 @@ describe('Fx defaults', function() { }]) .layout; - expect(layoutOut.hovermode).toBe('y', 'hovermode to y'); + expect(layoutOut.hovermode).toBe('closest', 'hovermode to closest'); expect(layoutOut.dragmode).toBe('zoom', 'dragmode to zoom'); - expect(layoutOut._isHoriz).toBe(true, 'isHoriz to true'); }); it('should default (cartesian horizontal version, stacked scatter)', function() { @@ -73,9 +67,8 @@ describe('Fx defaults', function() { }]) .layout; - expect(layoutOut.hovermode).toBe('y', 'hovermode to y'); + expect(layoutOut.hovermode).toBe('closest', 'hovermode to closest'); expect(layoutOut.dragmode).toBe('zoom', 'dragmode to zoom'); - expect(layoutOut._isHoriz).toBe(true, 'isHoriz to true'); }); it('should default (gl3d version)', function() { @@ -115,7 +108,7 @@ describe('Fx defaults', function() { }]) .layout; - expect(layoutOut.hovermode).toBe('x', 'hovermode to x'); + expect(layoutOut.hovermode).toBe('closest', 'hovermode to closest'); expect(layoutOut.dragmode).toBe('zoom', 'dragmode to zoom'); }); diff --git a/test/jasmine/tests/gl2d_click_test.js b/test/jasmine/tests/gl2d_click_test.js index c615e191e41..c7f72916244 100644 --- a/test/jasmine/tests/gl2d_click_test.js +++ b/test/jasmine/tests/gl2d_click_test.js @@ -416,6 +416,7 @@ describe('Test hover and click interactions', function() { it('@gl scattergl should propagate marker colors to hover labels', function(done) { var _mock = Lib.extendDeep({}, mock0); + _mock.layout.hovermode = 'x'; _mock.layout.width = 800; _mock.layout.height = 600; diff --git a/test/jasmine/tests/hover_label_test.js b/test/jasmine/tests/hover_label_test.js index b875369975d..eebd0583df8 100644 --- a/test/jasmine/tests/hover_label_test.js +++ b/test/jasmine/tests/hover_label_test.js @@ -585,6 +585,7 @@ describe('hover info', function() { {y: [1, 0, 1], type: 'bar', name: 'c'}, {y: [2, 1, 0], type: 'bar', name: 'd'} ], { + hovermode: 'x', width: 500, height: 400, margin: {l: 0, t: 0, r: 0, b: 0}, @@ -623,6 +624,7 @@ describe('hover info', function() { {x: [1, 0, 1], type: 'bar', name: 'c', orientation: 'h'}, {x: [2, 1, 0], type: 'bar', name: 'd', orientation: 'h'} ], { + hovermode: 'y', width: 500, height: 400, margin: {l: 0, t: 0, r: 0, b: 0}, @@ -892,8 +894,10 @@ describe('hover info', function() { it('should get the right content and color for contour constraints', function(done) { var contourConstraints = require('@mocks/contour_constraints.json'); + var fig = Lib.extendDeep({}, contourConstraints); + fig.layout.hovermode = 'x'; - Plotly.newPlot(gd, contourConstraints) + Plotly.newPlot(gd, fig) .then(function() { _hover(gd, 250, 250); assertHoverLabelContent({ @@ -976,6 +980,7 @@ describe('hover info', function() { name: 'two', showscale: false }], { + hovermode: 'x', width: 500, height: 400, margin: {l: 0, t: 0, r: 0, b: 0} @@ -1068,6 +1073,7 @@ describe('hover info', function() { var gd = createGraphDiv(); Plotly.newPlot(gd, [{x: [1, 2, 3], y: [1, -5, 10]}], { + hovermode: 'x', yaxis: {type: 'log'}, width: 500, height: 400, @@ -1093,6 +1099,7 @@ describe('hover info', function() { xbins: {start: -0.5, end: 8.5, size: 3}, type: 'histogram' }], { + hovermode: 'x', width: 500, height: 400, margin: {l: 0, t: 0, r: 0, b: 0} @@ -1156,6 +1163,7 @@ describe('hover info', function() { xbins: {start: -0.5, end: 8.5, size: 3}, type: 'histogram' }], { + hovermode: 'x', width: 500, height: 400, margin: {l: 0, t: 0, r: 0, b: 0} @@ -1191,6 +1199,7 @@ describe('hover info', function() { xbins: {start: -0.5, end: 8.5, size: 3}, type: 'histogram' }], { + hovermode: 'x', width: 500, height: 400, margin: {l: 0, t: 0, r: 0, b: 0} @@ -1221,6 +1230,7 @@ describe('hover info', function() { close: [0, 3, 2] }, traceUpdates || {})], layout: Lib.extendDeep({}, { + hovermode: 'x', width: 400, height: 400, margin: {l: 50, r: 50, t: 50, b: 50} @@ -1328,7 +1338,7 @@ describe('hover info', function() { .then(done, done.fail); }); - it('shows text iff text is in hoverinfo', function(done) { + it('shows text if text is in hoverinfo', function(done) { Plotly.newPlot(gd, financeMock({text: ['A', 'B', 'C']})) .then(function() { _hover(gd, 150, 150); @@ -1366,6 +1376,7 @@ describe('hover info', function() { y: [0.12345, 0.23456, 0.34567] }]; var layout = { + hovermode: 'x', yaxis: { showticklabels: true, hoverformat: ',.2r' }, width: 600, height: 400 @@ -1600,7 +1611,7 @@ describe('hover info', function() { text: ['San Francisco'] }; var data = [trace1, trace2]; - var layout = {width: 600, height: 300, barmode: 'stack'}; + var layout = {width: 600, height: 300, barmode: 'stack', hovermode: 'x'}; Plotly.newPlot(gd, data, layout) .then(function() { _hover(gd, 300, 150); }) @@ -1635,7 +1646,7 @@ describe('hover info', function() { text: ['New York'] }; var data = [trace1, trace2, trace3]; - var layout = {width: 600, height: 300}; + var layout = {width: 600, height: 300, hovermode: 'x'}; Plotly.newPlot(gd, data, layout) .then(function() { _hover(gd, 300, 150); }) @@ -1675,6 +1686,7 @@ describe('hover info', function() { hoverinfo: 'x+y+name', hoverlabel: {namelength: -1} }], { + hovermode: 'x', width: 600, height: 300 }) @@ -1709,6 +1721,7 @@ describe('hover info', function() { {name: 'B', x: [8, 9], y: [9, 10]}, {name: 'C', x: [9, 10], y: [10, 11]} ], { + hovermode: 'x', xaxis: {range: [0, 100]}, yaxis: {range: [0, 100]}, width: 700, @@ -1768,6 +1781,7 @@ describe('hover info', function() { x: ['2019-01-01', '2019-06-01', '2020-01-01'], y: [2, 5, 10] }], { + hovermode: 'x', xaxis: {range: ['2019-02-06', '2019-12-01']}, margin: {l: 0, r: 0}, width: 400, @@ -1828,6 +1842,7 @@ describe('hover info', function() { y: ['Looong label', 'Loooooger label', 'Waay loooong label', 'a'], x: [2, 5, 10, 2] }], { + hovermode: 'y', width: 400, height: 400 }) @@ -2065,6 +2080,7 @@ describe('hover info', function() { }, { y: [1] }], { + hovermode: 'x', meta: ['yo!'], width: 400, height: 400 @@ -2211,6 +2227,7 @@ describe('hover info on stacked subplots', function() { // This was the problem in #2370 {}, {y: [100, 120, 100]} ]}); + mock.layout.hovermode = 'x'; var gd; @@ -2343,6 +2360,7 @@ describe('hover on many lines+bars', function() { {y: values2}, {y: values, type: 'bar'} ], { + hovermode: 'x', width: 400, height: 400, margin: {l: 100, r: 100, t: 100, b: 100} @@ -2366,6 +2384,7 @@ describe('hover info on overlaid subplots', function() { it('should respond to hover', function(done) { var mock = require('@mocks/autorange-tozero-rangemode.json'); + mock.layout.hovermode = 'x'; Plotly.newPlot(createGraphDiv(), mock.data, mock.layout).then(function() { mouseEvent('mousemove', 768, 345); @@ -2408,7 +2427,7 @@ describe('hover after resizing', function() { gd = createGraphDiv(); var data = [{ y: [2, 1, 2] }]; - var layout = { width: 600, height: 500 }; + var layout = { width: 600, height: 500, hovermode: 'x' }; var pos0 = [305, 403]; var pos1 = [401, 122]; @@ -2468,6 +2487,7 @@ describe('hover on fill', function() { it('should always show one label in the right place', function(done) { var mock = Lib.extendDeep({}, require('@mocks/scatter_fill_self_next.json')); mock.data.forEach(function(trace) { trace.hoveron = 'fills'; }); + mock.layout.hovermode = 'x'; Plotly.newPlot(createGraphDiv(), mock.data, mock.layout).then(function() { assertLabelsCorrect([242, 142], [252, 133.8], 'trace 2'); @@ -2486,6 +2506,7 @@ describe('hover on fill', function() { fill: 'tonext', hoveron: 'fills' }], { + hovermode: 'x', width: 500, height: 500, margin: {l: 50, t: 50, r: 50, b: 50} @@ -2543,6 +2564,7 @@ describe('hover on fill', function() { it('should act like closest mode on ternary when cartesian is in compare mode', function(done) { var mock = Lib.extendDeep({}, require('@mocks/ternary_fill.json')); + mock.layout.hovermode = 'x'; var gd = createGraphDiv(); mock.data.push({y: [7, 8, 9]}); @@ -2589,6 +2611,7 @@ describe('Hover on multicategory axes', function() { x: [['2018', '2018', '2019', '2019'], ['a', 'b', 'a', 'b']], y: [1, 2, -1, 3] }], { + hovermode: 'x', bargap: 0, width: 400, height: 400 @@ -3495,6 +3518,7 @@ describe('hover updates', function() { {x: [0], y: [0], showlegend: false}, ], layout: { + hovermode: 'x', margin: {t: 0, r: 0, b: 0, l: 0}, width: 200, height: 200, @@ -3554,7 +3578,7 @@ describe('hover updates', function() { size: 16, color: colors0.slice() } - }], { width: 700, height: 450 }) + }], { width: 700, height: 450, hovermode: 'x' }) .then(function() { gd.on('plotly_hover', function(eventData) { hoverCnt++; @@ -3597,6 +3621,7 @@ describe('hover updates', function() { ]; var layout = { + hovermode: 'x', xaxis: {domain: [0, 0.5]}, xaxis2: {anchor: 'y2', domain: [0.5, 1]}, yaxis2: {anchor: 'x2'}, @@ -4240,7 +4265,7 @@ describe('hover distance', function() { var x = [0, 1, 2]; var mock = { data: [{type: 'bar', x: x, y: [4, 5, 6]}, {x: x, y: [5, 6, 7]}], - layout: {width: 400, height: 400, xaxis: {type: 'linear'}} + layout: {width: 400, height: 400, xaxis: {type: 'linear'}, hovermode: 'x'} }; Plotly.newPlot(gd, mock) @@ -4256,7 +4281,7 @@ describe('hover distance', function() { var x = [0, 1, 2]; var mock = { data: [{type: 'bar', x: x, y: [4, 5, 6]}, {x: x, y: [5, 6, 7]}], - layout: {width: 400, height: 400, xaxis: {type: 'log'}} + layout: {width: 400, height: 400, xaxis: {type: 'log'}, hovermode: 'x'} }; Plotly.newPlot(gd, mock) @@ -4272,7 +4297,7 @@ describe('hover distance', function() { var x = ['a', 'b', 'c']; var mock = { data: [{type: 'bar', x: x, y: [4, 5, 6]}, {x: x, y: [5, 6, 7]}], - layout: {width: 400, height: 400, xaxis: {type: 'category'}} + layout: {width: 400, height: 400, xaxis: {type: 'category'}, hovermode: 'x'} }; Plotly.newPlot(gd, mock) @@ -4288,7 +4313,7 @@ describe('hover distance', function() { var x = ['2018', '2019', '2020']; var mock = { data: [{type: 'bar', x: x, y: [4, 5, 6]}, {x: x, y: [5, 6, 7]}], - layout: {width: 400, height: 400, xaxis: {type: 'date'}} + layout: {width: 400, height: 400, xaxis: {type: 'date'}, hovermode: 'x'} }; Plotly.newPlot(gd, mock) @@ -4407,51 +4432,6 @@ describe('hover label rotation:', function() { }); }); -describe('hovermode defaults to', function() { - var gd; - - beforeEach(function() { - gd = createGraphDiv(); - }); - - afterEach(destroyGraphDiv); - - it('\'closest\' for cartesian plots if clickmode includes \'select\'', function(done) { - Plotly.newPlot(gd, [{ x: [1, 2, 3], y: [4, 5, 6] }], { clickmode: 'event+select' }) - .then(function() { - expect(gd._fullLayout.hovermode).toBe('closest'); - }) - .then(done, done.fail); - }); - - it('\'x\' for horizontal cartesian plots if clickmode lacks \'select\'', function(done) { - Plotly.newPlot(gd, [{ x: [1, 2, 3], y: [4, 5, 6], type: 'bar', orientation: 'h' }], { clickmode: 'event' }) - .then(function() { - expect(gd._fullLayout.hovermode).toBe('y'); - }) - .then(done, done.fail); - }); - - it('\'y\' for vertical cartesian plots if clickmode lacks \'select\'', function(done) { - Plotly.newPlot(gd, [{ x: [1, 2, 3], y: [4, 5, 6], type: 'bar', orientation: 'v' }], { clickmode: 'event' }) - .then(function() { - expect(gd._fullLayout.hovermode).toBe('x'); - }) - .then(done, done.fail); - }); - - it('\'closest\' for a non-cartesian plot', function(done) { - var mock = require('@mocks/polar_scatter.json'); - expect(mock.layout.hovermode).toBeUndefined(); - - Plotly.newPlot(gd, mock.data, mock.layout) - .then(function() { - expect(gd._fullLayout.hovermode).toBe('closest'); - }) - .then(done, done.fail); - }); -}); - describe('hover labels z-position', function() { var gd; diff --git a/test/jasmine/tests/hover_spikeline_test.js b/test/jasmine/tests/hover_spikeline_test.js index ead962676d2..8bd5dbac12c 100644 --- a/test/jasmine/tests/hover_spikeline_test.js +++ b/test/jasmine/tests/hover_spikeline_test.js @@ -717,6 +717,7 @@ describe('spikeline hover', function() { {y: [5, 7, 9, 6, 4, 3]}, {y: [5, 7, 9, 6, 4, 3], marker: {color: 'red'}} ], { + hovermode: 'x', xaxis: {showspikes: true}, yaxis: {showspikes: true}, spikedistance: -1, diff --git a/test/jasmine/tests/modebar_test.js b/test/jasmine/tests/modebar_test.js index a6b52bd45b1..674a5a8eb55 100644 --- a/test/jasmine/tests/modebar_test.js +++ b/test/jasmine/tests/modebar_test.js @@ -1199,27 +1199,27 @@ describe('ModeBar', function() { describe('buttons hoverCompareCartesian and hoverClosestCartesian ', function() { it('should update layout hovermode', function() { - expect(gd._fullLayout.hovermode).toBe('x'); - assertActive(hovermodeButtons, buttonCompare); - - buttonClosest.click(); expect(gd._fullLayout.hovermode).toBe('closest'); assertActive(hovermodeButtons, buttonClosest); buttonCompare.click(); expect(gd._fullLayout.hovermode).toBe('x'); assertActive(hovermodeButtons, buttonCompare); + + buttonClosest.click(); + expect(gd._fullLayout.hovermode).toBe('closest'); + assertActive(hovermodeButtons, buttonClosest); }); }); describe('button toggleSpikelines', function() { it('should not change layout hovermode', function() { - expect(gd._fullLayout.hovermode).toBe('x'); - assertActive(hovermodeButtons, buttonCompare); + expect(gd._fullLayout.hovermode).toBe('closest'); + assertActive(hovermodeButtons, buttonClosest); buttonToggle.click(); - expect(gd._fullLayout.hovermode).toBe('x'); - assertActive(hovermodeButtons, buttonCompare); + expect(gd._fullLayout.hovermode).toBe('closest'); + assertActive(hovermodeButtons, buttonClosest); }); it('should makes spikelines visible', function() { diff --git a/test/jasmine/tests/plot_api_react_test.js b/test/jasmine/tests/plot_api_react_test.js index 9006f754f71..611873a6959 100644 --- a/test/jasmine/tests/plot_api_react_test.js +++ b/test/jasmine/tests/plot_api_react_test.js @@ -178,7 +178,7 @@ describe('@noCIdep Plotly.react', function() { it('picks up partial redraws', function(done) { var data = [{y: [1, 2, 3], mode: 'markers'}]; - var layout = {}; + var layout = {hovermode: 'x'}; Plotly.newPlot(gd, data, layout) .then(countPlots) diff --git a/test/jasmine/tests/scatter_test.js b/test/jasmine/tests/scatter_test.js index 80c7ff97e53..432b2103437 100644 --- a/test/jasmine/tests/scatter_test.js +++ b/test/jasmine/tests/scatter_test.js @@ -1983,6 +1983,7 @@ describe('Test scatter *clipnaxis*:', function() { describe('event data', function() { var mock = require('@mocks/scatter-colorscale-colorbar'); var mockCopy = Lib.extendDeep({}, mock); + mockCopy.layout.hovermode = 'x'; var marker = mockCopy.data[0].marker; marker.opacity = []; diff --git a/test/jasmine/tests/splom_test.js b/test/jasmine/tests/splom_test.js index b2136f801cf..5727394eba7 100644 --- a/test/jasmine/tests/splom_test.js +++ b/test/jasmine/tests/splom_test.js @@ -1398,16 +1398,16 @@ describe('Test splom hover:', function() { var specs = [{ desc: 'basic', + patch: function(fig) { + fig.layout.hovermode = 'x'; + return fig; + }, nums: '7.7', name: 'Virginica', axis: '2.6', evtPts: [{x: 2.6, y: 7.7, pointNumber: 18, curveNumber: 2}] }, { desc: 'hovermode closest', - patch: function(fig) { - fig.layout.hovermode = 'closest'; - return fig; - }, nums: '(2.6, 7.7)', name: 'Virginica', evtPts: [{x: 2.6, y: 7.7, pointNumber: 18, curveNumber: 2}] @@ -1415,6 +1415,7 @@ describe('Test splom hover:', function() { desc: 'skipping over visible false dims', patch: function(fig) { fig.data[0].dimensions[0].visible = false; + fig.layout.hovermode = 'x'; return fig; }, nums: '7.7', @@ -1428,6 +1429,7 @@ describe('Test splom hover:', function() { fig.layout.margin = {t: 0, l: 0, b: 0, r: 0}; fig.layout.width = 400; fig.layout.height = 400; + fig.layout.hovermode = 'x'; return fig; }, pos: [20, 380], @@ -1439,6 +1441,7 @@ describe('Test splom hover:', function() { mock: require('@mocks/splom_dates.json'), patch: function(fig) { fig.layout = { + hovermode: 'x', margin: {t: 0, l: 0, b: 0, r: 0}, width: 400, height: 400 @@ -1456,7 +1459,6 @@ describe('Test splom hover:', function() { t.hovertext = 'LOOK'; t.text = 'NOP'; }); - fig.layout.hovermode = 'closest'; return fig; }, nums: '(2.6, 7.7)\nLOOK', @@ -1468,7 +1470,6 @@ describe('Test splom hover:', function() { fig.data.forEach(function(t) { t.hovertemplate = '%{x}|%{y}pt %{pointNumber}'; }); - fig.layout.hovermode = 'closest'; return fig; }, nums: '2.6|7.7', diff --git a/test/jasmine/tests/violin_test.js b/test/jasmine/tests/violin_test.js index 54298aaba03..4b111891583 100644 --- a/test/jasmine/tests/violin_test.js +++ b/test/jasmine/tests/violin_test.js @@ -361,6 +361,10 @@ describe('Test violin hover:', function() { [{ desc: 'base', + patch: function(fig) { + fig.layout.hovermode = 'x'; + return fig; + }, nums: [ 'median: 0.55', 'min: 0', 'q1: 0.3', 'q3: 0.6', 'max: 0.7', 'y: 0.9266848, kde: 0.182' @@ -373,6 +377,7 @@ describe('Test violin hover:', function() { fig.data.forEach(function(trace) { trace.meanline = {visible: true}; }); + fig.layout.hovermode = 'x'; return fig; }, nums: [ @@ -385,6 +390,7 @@ describe('Test violin hover:', function() { desc: 'with overlaid violins', patch: function(fig) { fig.layout.violinmode = 'overlay'; + fig.layout.hovermode = 'x'; return fig; }, nums: [ @@ -404,7 +410,6 @@ describe('Test violin hover:', function() { trace.points = 'all'; trace.hoveron = 'points'; }); - fig.layout.hovermode = 'closest'; return fig; }, pos: [220, 200], @@ -460,7 +465,6 @@ describe('Test violin hover:', function() { trace.hoveron = 'points'; trace.text = trace.y.map(function(v) { return 'look:' + v; }); }); - fig.layout.hovermode = 'closest'; return fig; }, pos: [180, 240], @@ -475,7 +479,6 @@ describe('Test violin hover:', function() { trace.text = trace.y.map(function(v) { return 'look:' + v; }); trace.hoverinfo = 'text'; }); - fig.layout.hovermode = 'closest'; return fig; }, pos: [180, 240], @@ -491,7 +494,6 @@ describe('Test violin hover:', function() { trace.text = trace.y.map(function(v) { return 'NOT THIS:' + v; }); trace.hoverinfo = 'text'; }); - fig.layout.hovermode = 'closest'; return fig; }, pos: [180, 240], @@ -500,7 +502,6 @@ describe('Test violin hover:', function() { }, { desc: 'one-sided violin under hovermode closest', // hoveron: 'kde+points' - // hovermode: 'closest' // width: 400 // height: 700 mock: require('@mocks/violin_side-by-side.json'), @@ -542,6 +543,10 @@ describe('Test violin hover:', function() { }, { desc: 'single horizontal violin', mock: require('@mocks/violin_non-linear.json'), + patch: function(fig) { + fig.layout.hovermode = 'y'; + return fig; + }, pos: [310, 160], nums: ['median: C', 'min: A', 'q1: B', 'q3: D', 'max: G', 'upper fence: D', 'x: C, kde: 1.005'], name: ['categories', '', '', '', '', '', ''], @@ -557,6 +562,7 @@ describe('Test violin hover:', function() { t.hoveron = 'violins'; }); fig.layout.violinmode = 'group'; + fig.layout.hovermode = 'y'; return fig; }, nums: ['median: 0.4', 'min: 0.1', 'q1: 0.2', 'q3: 0.7', 'max: 0.9'], @@ -573,7 +579,6 @@ describe('Test violin hover:', function() { t.hoveron = 'violins'; }); fig.layout.violinmode = 'group'; - fig.layout.hovermode = 'closest'; return fig; }, pos: [200, 175], @@ -591,7 +596,6 @@ describe('Test violin hover:', function() { fig.data[0].x = fig.data[0].y; delete fig.data[0].y; fig.layout = { - hovermode: 'closest', yaxis: {range: [-0.696, 0.5]} }; return fig; @@ -608,6 +612,7 @@ describe('Test violin hover:', function() { fig.data.forEach(function(t) { t.hoveron = 'violins'; }); + fig.layout.hovermode = 'y'; return fig; }, pos: [430, 130], @@ -623,7 +628,6 @@ describe('Test violin hover:', function() { fig.data.forEach(function(t) { t.hoveron = 'violins'; }); - fig.layout.hovermode = 'closest'; return fig; }, pos: [430, 130], @@ -644,8 +648,7 @@ describe('Test violin hover:', function() { orientation: 'h', y: [2, 2, 2, 2, 2], x: [13.1, 14.2, 14, 13, 13.3] - }], - layout: {hovermode: 'closest'} + }] }, pos: [417, 309], nums: '(14, 2)', @@ -658,7 +661,6 @@ describe('Test violin hover:', function() { trace.hoveron = 'points'; trace.hovertemplate = 'Sample pt %{pointNumber}: %{y:.3f}'; }); - fig.layout.hovermode = 'closest'; return fig; }, pos: [220, 200], diff --git a/test/jasmine/tests/waterfall_test.js b/test/jasmine/tests/waterfall_test.js index 1c36a912650..793eac39d7f 100644 --- a/test/jasmine/tests/waterfall_test.js +++ b/test/jasmine/tests/waterfall_test.js @@ -1469,6 +1469,7 @@ describe('waterfall hover', function() { t.base = 1000; t.hoverinfo = 'all'; }); + mock.layout.hovermode = 'x'; function _hover() { var evt = { xpx: 125, ypx: 150 }; @@ -1499,6 +1500,7 @@ describe('waterfall hover', function() { t.type = 'waterfall'; t.hovertemplate = 'Value: %{y}
SUM: %{final}
START: %{initial}
DIFF: %{delta}'; }); + mock.layout.hovermode = 'x'; function _hover() { var evt = { xpx: 125, ypx: 150 }; @@ -1530,7 +1532,7 @@ describe('waterfall hover', function() { y: [0, -1.1, 2.2, -3.3, 4.4], type: 'waterfall' }], - layout: {width: 400, height: 400} + layout: {width: 400, height: 400, hovermode: 'x'} }) .then(function() { var evt = { xpx: 200, ypx: 350 };