diff --git a/src/components/modebar/manage.js b/src/components/modebar/manage.js index 042be085ebe..1e4f9f8fc50 100644 --- a/src/components/modebar/manage.js +++ b/src/components/modebar/manage.js @@ -170,19 +170,50 @@ function getButtonGroups(gd) { dragModeGroup.push('select2d', 'lasso2d'); } - // accept pre-defined buttons as string + var enabledHoverGroup = []; + var enableHover = function(a) { + // return if already added + if(enabledHoverGroup.indexOf(a) !== -1) return; + // should be in hoverGroup + if(hoverGroup.indexOf(a) !== -1) { + enabledHoverGroup.push(a); + } + }; if(Array.isArray(buttonsToAdd)) { var newList = []; for(var i = 0; i < buttonsToAdd.length; i++) { var b = buttonsToAdd[i]; if(typeof b === 'string') { + b = b.toLowerCase(); + if(DRAW_MODES.indexOf(b) !== -1) { + // accept pre-defined drag modes i.e. shape drawing features as string if( fullLayout._has('mapbox') || // draw shapes in paper coordinate (could be improved in future to support data coordinate, when there is no pitch) fullLayout._has('cartesian') // draw shapes in data coordinate ) { dragModeGroup.push(b); } + } else if(b === 'togglespikelines') { + enableHover('toggleSpikelines'); + } else if(b === 'togglehover') { + enableHover('toggleHover'); + } else if(b === 'hovercompare') { + enableHover('hoverCompareCartesian'); + } else if(b === 'hoverclosest') { + enableHover('hoverClosestCartesian'); + enableHover('hoverClosestGeo'); + enableHover('hoverClosest3d'); + enableHover('hoverClosestGl2d'); + enableHover('hoverClosestPie'); + } else if(b === 'v1hovermode') { + enableHover('toggleHover'); + enableHover('hoverClosestCartesian'); + enableHover('hoverCompareCartesian'); + enableHover('hoverClosestGeo'); + enableHover('hoverClosest3d'); + enableHover('hoverClosestGl2d'); + enableHover('hoverClosestPie'); } } else newList.push(b); } @@ -191,7 +222,7 @@ function getButtonGroups(gd) { addGroup(dragModeGroup); addGroup(zoomGroup.concat(resetGroup)); - addGroup(hoverGroup); + addGroup(enabledHoverGroup); return appendButtonsToGroups(groups, buttonsToAdd); } diff --git a/test/jasmine/tests/gl3d_plot_interact_test.js b/test/jasmine/tests/gl3d_plot_interact_test.js index 92913a5c769..d8bcef9bb21 100644 --- a/test/jasmine/tests/gl3d_plot_interact_test.js +++ b/test/jasmine/tests/gl3d_plot_interact_test.js @@ -455,6 +455,9 @@ describe('Test gl3d modebar handlers - perspective case', function() { }, aspectratio: { x: 3, y: 2, z: 1 } } + }, + config: { + modeBarButtonsToAdd: ['hoverclosest'] } }; @@ -534,7 +537,7 @@ describe('Test gl3d modebar handlers - perspective case', function() { expect(buttonOrbit.isActive()).toBe(false); }); - it('@gl button hoverClosest3d should update the scene hovermode and spikes', function() { + it('@gl button hoverClosest should update the scene hovermode and spikes', function() { var buttonHover = selectButton(modeBar, 'hoverClosest3d'); assertScenes(gd._fullLayout, 'hovermode', 'closest'); diff --git a/test/jasmine/tests/modebar_test.js b/test/jasmine/tests/modebar_test.js index 674a5a8eb55..5c0457d602a 100644 --- a/test/jasmine/tests/modebar_test.js +++ b/test/jasmine/tests/modebar_test.js @@ -342,8 +342,7 @@ describe('ModeBar', function() { var buttons = getButtons([ ['toImage'], ['zoom2d', 'pan2d'], - ['zoomIn2d', 'zoomOut2d', 'autoScale2d', 'resetScale2d'], - ['toggleSpikelines', 'hoverClosestCartesian', 'hoverCompareCartesian'] + ['zoomIn2d', 'zoomOut2d', 'autoScale2d', 'resetScale2d'] ]); var gd = getMockGraphInfo(['x'], ['y']); @@ -361,8 +360,7 @@ describe('ModeBar', function() { var buttons = getButtons([ ['toImage'], ['zoom2d', 'pan2d', 'select2d', 'lasso2d'], - ['zoomIn2d', 'zoomOut2d', 'autoScale2d', 'resetScale2d'], - ['toggleSpikelines', 'hoverClosestCartesian', 'hoverCompareCartesian'] + ['zoomIn2d', 'zoomOut2d', 'autoScale2d', 'resetScale2d'] ]); var gd = getMockGraphInfo(['x'], ['y']); @@ -385,8 +383,7 @@ describe('ModeBar', function() { var buttons = getButtons([ ['toImage'], ['zoom2d', 'pan2d', 'select2d', 'lasso2d'], - ['zoomIn2d', 'zoomOut2d', 'autoScale2d', 'resetScale2d'], - ['toggleSpikelines', 'hoverClosestCartesian', 'hoverCompareCartesian'] + ['zoomIn2d', 'zoomOut2d', 'autoScale2d', 'resetScale2d'] ]); var gd = getMockGraphInfo(['x'], ['y']); @@ -407,8 +404,7 @@ describe('ModeBar', function() { it('creates mode bar (cartesian fixed-axes version)', function() { var buttons = getButtons([ - ['toImage'], - ['toggleSpikelines', 'hoverClosestCartesian', 'hoverCompareCartesian'] + ['toImage'] ]); var gd = getMockGraphInfo(); @@ -425,8 +421,7 @@ describe('ModeBar', function() { var buttons = getButtons([ ['toImage'], ['zoom3d', 'pan3d', 'orbitRotation', 'tableRotation'], - ['resetCameraDefault3d', 'resetCameraLastSave3d'], - ['hoverClosest3d'] + ['resetCameraDefault3d', 'resetCameraLastSave3d'] ]); var gd = getMockGraphInfo(); @@ -443,8 +438,7 @@ describe('ModeBar', function() { var buttons = getButtons([ ['toImage'], ['pan2d'], - ['zoomInGeo', 'zoomOutGeo', 'resetGeo'], - ['hoverClosestGeo'] + ['zoomInGeo', 'zoomOutGeo', 'resetGeo'] ]); var gd = getMockGraphInfo(); @@ -461,8 +455,7 @@ describe('ModeBar', function() { var buttons = getButtons([ ['toImage'], ['pan2d', 'select2d', 'lasso2d'], - ['zoomInGeo', 'zoomOutGeo', 'resetGeo'], - ['hoverClosestGeo'] + ['zoomInGeo', 'zoomOutGeo', 'resetGeo'] ]); var gd = getMockGraphInfo(); @@ -484,8 +477,7 @@ describe('ModeBar', function() { var buttons = getButtons([ ['toImage'], ['pan2d'], - ['zoomInMapbox', 'zoomOutMapbox', 'resetViewMapbox'], - ['toggleHover'] + ['zoomInMapbox', 'zoomOutMapbox', 'resetViewMapbox'] ]); var gd = getMockGraphInfo(); @@ -502,8 +494,7 @@ describe('ModeBar', function() { var buttons = getButtons([ ['toImage'], ['pan2d', 'select2d', 'lasso2d'], - ['zoomInMapbox', 'zoomOutMapbox', 'resetViewMapbox'], - ['toggleHover'] + ['zoomInMapbox', 'zoomOutMapbox', 'resetViewMapbox'] ]); var gd = getMockGraphInfo(); @@ -525,8 +516,7 @@ describe('ModeBar', function() { var buttons = getButtons([ ['toImage'], ['zoom2d', 'pan2d'], - ['zoomIn2d', 'zoomOut2d', 'autoScale2d', 'resetScale2d'], - ['hoverClosestGl2d'] + ['zoomIn2d', 'zoomOut2d', 'autoScale2d', 'resetScale2d'] ]); var gd = getMockGraphInfo(['x'], ['y']); @@ -542,8 +532,7 @@ describe('ModeBar', function() { it('creates mode bar (pie version)', function() { var buttons = getButtons([ - ['toImage'], - ['hoverClosestPie'] + ['toImage'] ]); var gd = getMockGraphInfo(); @@ -560,8 +549,7 @@ describe('ModeBar', function() { var buttons = getButtons([ ['toImage'], ['zoom3d', 'pan3d', 'orbitRotation', 'tableRotation'], - ['resetViews'], - ['toggleSpikelines', 'hoverClosestCartesian', 'hoverCompareCartesian'] + ['resetViews'] ]); var gd = getMockGraphInfo(); @@ -578,8 +566,7 @@ describe('ModeBar', function() { var buttons = getButtons([ ['toImage'], ['zoom2d', 'pan2d'], - ['zoomIn2d', 'zoomOut2d', 'autoScale2d', 'resetViews'], - ['toggleSpikelines', 'hoverClosestCartesian', 'hoverCompareCartesian'] + ['zoomIn2d', 'zoomOut2d', 'autoScale2d', 'resetViews'] ]); var gd = getMockGraphInfo(['x'], ['y']); @@ -597,8 +584,7 @@ describe('ModeBar', function() { var buttons = getButtons([ ['toImage'], ['zoom2d', 'pan2d', 'select2d', 'lasso2d'], - ['zoomIn2d', 'zoomOut2d', 'autoScale2d', 'resetViews'], - ['toggleSpikelines', 'hoverClosestCartesian', 'hoverCompareCartesian'] + ['zoomIn2d', 'zoomOut2d', 'autoScale2d', 'resetViews'] ]); var gd = getMockGraphInfo(['x'], ['y']); @@ -621,8 +607,7 @@ describe('ModeBar', function() { var buttons = getButtons([ ['toImage'], ['zoom2d', 'pan2d', 'select2d', 'lasso2d'], - ['zoomIn2d', 'zoomOut2d', 'autoScale2d', 'resetScale2d'], - ['toggleSpikelines', 'hoverClosestCartesian', 'hoverCompareCartesian'] + ['zoomIn2d', 'zoomOut2d', 'autoScale2d', 'resetScale2d'] ]); var gd = getMockGraphInfo(['x'], ['y']); @@ -645,8 +630,7 @@ describe('ModeBar', function() { var buttons = getButtons([ ['toImage'], ['zoom3d', 'pan3d', 'orbitRotation', 'tableRotation'], - ['resetViews'], - ['toggleHover'] + ['resetViews'] ]); var gd = getMockGraphInfo(); @@ -662,8 +646,7 @@ describe('ModeBar', function() { it('creates mode bar (un-selectable ternary version)', function() { var buttons = getButtons([ ['toImage'], - ['zoom2d', 'pan2d'], - ['toggleHover'] + ['zoom2d', 'pan2d'] ]); var gd = getMockGraphInfo(); @@ -679,8 +662,7 @@ describe('ModeBar', function() { it('creates mode bar (selectable ternary version)', function() { var buttons = getButtons([ ['toImage'], - ['zoom2d', 'pan2d', 'select2d', 'lasso2d'], - ['toggleHover'] + ['zoom2d', 'pan2d', 'select2d', 'lasso2d'] ]); var gd = getMockGraphInfo(); @@ -701,8 +683,7 @@ describe('ModeBar', function() { it('creates mode bar (ternary + cartesian version)', function() { var buttons = getButtons([ ['toImage'], - ['zoom2d', 'pan2d'], - ['toggleSpikelines', 'hoverClosestCartesian', 'hoverCompareCartesian'] + ['zoom2d', 'pan2d'] ]); var gd = getMockGraphInfo(); @@ -719,8 +700,7 @@ describe('ModeBar', function() { var buttons = getButtons([ ['toImage'], ['zoom3d', 'pan3d', 'orbitRotation', 'tableRotation'], - ['resetViews'], - ['toggleHover'] + ['resetViews'] ]); var gd = getMockGraphInfo(); @@ -739,6 +719,7 @@ describe('ModeBar', function() { ]); var gd = getMockGraphInfo(); + gd._context.modeBarButtonsToAdd = ['hoverclosest']; gd._fullData = [{ type: 'indicator' }]; manageModeBar(gd); @@ -754,6 +735,7 @@ describe('ModeBar', function() { ]); var gd = getMockGraphInfo(); + gd._context.modeBarButtonsToAdd = ['hoverclosest']; gd._fullLayout._basePlotModules = [{ name: 'pie' }]; gd._fullData = [{ type: 'indicator' }, {type: 'pie'}]; @@ -811,32 +793,28 @@ describe('ModeBar', function() { gd._fullData = [{type: 'pie'}]; manageModeBar(gd); checkButtons(gd._fullLayout._modeBar, getButtons([ - ['toImage'], - ['hoverClosestPie'] + ['toImage'] ]), 1); gd._context.showSendToCloud = true; gd._context.showEditInChartStudio = false; manageModeBar(gd); checkButtons(gd._fullLayout._modeBar, getButtons([ - ['toImage', 'sendDataToCloud'], - ['hoverClosestPie'] + ['toImage', 'sendDataToCloud'] ]), 1); gd._context.showSendToCloud = false; gd._context.showEditInChartStudio = true; manageModeBar(gd); checkButtons(gd._fullLayout._modeBar, getButtons([ - ['toImage', 'editInChartStudio'], - ['hoverClosestPie'] + ['toImage', 'editInChartStudio'] ]), 1); gd._context.showSendToCloud = true; gd._context.showEditInChartStudio = true; manageModeBar(gd); checkButtons(gd._fullLayout._modeBar, getButtons([ - ['toImage', 'editInChartStudio'], - ['hoverClosestPie'] + ['toImage', 'editInChartStudio'] ]), 1); }); @@ -863,13 +841,13 @@ describe('ModeBar', function() { var gd = setupGraphInfo(); manageModeBar(gd); - expect(countButtons(gd._fullLayout._modeBar)).toEqual(11); + expect(countButtons(gd._fullLayout._modeBar)).toEqual(8); - gd._fullLayout._basePlotModules = [{ name: 'gl3d' }]; - gd._fullData = [{type: 'scatter3d'}]; + gd._fullLayout._basePlotModules = [{ name: 'geo' }]; + gd._fullData = [{type: 'scattergeo'}]; manageModeBar(gd); - expect(countButtons(gd._fullLayout._modeBar)).toEqual(9); + expect(countButtons(gd._fullLayout._modeBar)).toEqual(6); }); it('updates mode bar buttons if modeBarButtonsToRemove changes', function() { @@ -906,7 +884,7 @@ describe('ModeBar', function() { it('sets up buttons with modeBarButtonsToAdd and modeBarButtonToRemove', function() { var gd = setupGraphInfo(); gd._context.modeBarButtonsToRemove = [ - 'toImage', 'pan2d', 'hoverCompareCartesian' + 'toImage', 'pan2d' ]; gd._context.modeBarButtonsToAdd = [ { name: 'some button', click: noop }, @@ -916,14 +894,14 @@ describe('ModeBar', function() { manageModeBar(gd); var modeBar = gd._fullLayout._modeBar; - expect(countGroups(modeBar)).toEqual(6); - expect(countButtons(modeBar)).toEqual(10); + expect(countGroups(modeBar)).toEqual(5); + expect(countButtons(modeBar)).toEqual(8); }); it('sets up buttons with modeBarButtonsToAdd and modeBarButtonToRemove (2)', function() { var gd = setupGraphInfo(); gd._context.modeBarButtonsToRemove = [ - 'toImage', 'pan2d', 'hoverCompareCartesian' + 'toImage', 'pan2d' ]; gd._context.modeBarButtonsToAdd = [[ { name: 'some button', click: noop }, @@ -936,8 +914,8 @@ describe('ModeBar', function() { manageModeBar(gd); var modeBar = gd._fullLayout._modeBar; - expect(countGroups(modeBar)).toEqual(7); - expect(countButtons(modeBar)).toEqual(12); + expect(countGroups(modeBar)).toEqual(6); + expect(countButtons(modeBar)).toEqual(10); }); it('sets up buttons with fully custom modeBarButtons', function() { @@ -1119,7 +1097,12 @@ describe('ModeBar', function() { }; gd = createGraphDiv(); - Plotly.newPlot(gd, mockData, mockLayout).then(function() { + Plotly.newPlot(gd, mockData, mockLayout, { + modeBarButtonsToAdd: [ + 'togglespikelines', + 'v1hovermode' + ] + }).then(function() { modeBar = gd._fullLayout._modeBar; buttonToggle = selectButton(modeBar, 'toggleSpikelines'); buttonCompare = selectButton(modeBar, 'hoverCompareCartesian'); @@ -1197,7 +1180,7 @@ describe('ModeBar', function() { }); }); - describe('buttons hoverCompareCartesian and hoverClosestCartesian ', function() { + describe('buttons hoverCompareCartesian and hoverClosestCartesian', function() { it('should update layout hovermode', function() { expect(gd._fullLayout.hovermode).toBe('closest'); assertActive(hovermodeButtons, buttonClosest); @@ -1293,7 +1276,9 @@ describe('ModeBar', function() { }]; gd = createGraphDiv(); - Plotly.newPlot(gd, mockData).then(function() { + Plotly.newPlot(gd, mockData, {}, { + modeBarButtonsToAdd: ['hoverclosest'] + }).then(function() { modeBar = gd._fullLayout._modeBar; done(); }); @@ -1326,7 +1311,9 @@ describe('ModeBar', function() { }]; gd = createGraphDiv(); - Plotly.newPlot(gd, mockData).then(function() { + Plotly.newPlot(gd, mockData, {}, { + modeBarButtonsToAdd: ['hoverclosest'] + }).then(function() { modeBar = gd._fullLayout._modeBar; done(); }); @@ -1410,7 +1397,9 @@ describe('ModeBar', function() { Plotly.newPlot(gd, [ {type: 'scatterternary', a: [1], b: [2], c: [3]} - ]) + ], {}, { + modeBarButtonsToAdd: ['togglehover'] + }) .then(function() { _run('base'); diff --git a/test/jasmine/tests/plot_api_test.js b/test/jasmine/tests/plot_api_test.js index 78383e283f2..4b79a98133a 100644 --- a/test/jasmine/tests/plot_api_test.js +++ b/test/jasmine/tests/plot_api_test.js @@ -2687,7 +2687,7 @@ describe('Test plot api', function() { var modebars = document.getElementsByClassName('modebar-container'); expect(modebars.length).toBe(1, msg + ' # of modebar container'); var groups = document.getElementsByClassName('modebar-group'); - expect(groups.length).toBe(5, msg + ' # of modebar button groups'); + expect(groups.length).toBe(4, msg + ' # of modebar button groups'); }; }