From 576c54bf976a9c48a692c03d302502726cafcd61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20T=C3=A9treault-Pinard?= Date: Fri, 25 Oct 2019 14:45:15 -0400 Subject: [PATCH 1/2] add `args2` attribute to updatemenu buttons - this set of arguments is passed the set button `method` when the button is in the active state. --- src/components/updatemenus/attributes.js | 16 ++++++++ src/components/updatemenus/defaults.js | 1 + src/components/updatemenus/draw.js | 11 ++++-- test/jasmine/tests/updatemenus_test.js | 50 +++++++++++++++++++++++- 4 files changed, 73 insertions(+), 5 deletions(-) diff --git a/src/components/updatemenus/attributes.js b/src/components/updatemenus/attributes.js index f37e02e9e46..2d2a8794e8b 100644 --- a/src/components/updatemenus/attributes.js +++ b/src/components/updatemenus/attributes.js @@ -48,6 +48,22 @@ var buttonsAttrs = templatedArray('button', { 'method set in `method` on click.' ].join(' ') }, + args2: { + valType: 'info_array', + role: 'info', + freeLength: true, + items: [ + {valType: 'any'}, + {valType: 'any'}, + {valType: 'any'} + ], + description: [ + 'Sets a 2nd set of `args`,', + 'these arguments values are passed to the Plotly', + 'method set in `method` when clicking this button while in the active state.', + 'Use this to create toggle buttons.' + ].join(' ') + }, label: { valType: 'string', role: 'info', diff --git a/src/components/updatemenus/defaults.js b/src/components/updatemenus/defaults.js index 492b9c911a9..3c646a5efac 100644 --- a/src/components/updatemenus/defaults.js +++ b/src/components/updatemenus/defaults.js @@ -74,6 +74,7 @@ function buttonDefaults(buttonIn, buttonOut) { if(visible) { coerce('method'); coerce('args'); + coerce('args2'); coerce('label'); coerce('execute'); } diff --git a/src/components/updatemenus/draw.js b/src/components/updatemenus/draw.js index 58c21b9122b..ac4ca74ef16 100644 --- a/src/components/updatemenus/draw.js +++ b/src/components/updatemenus/draw.js @@ -119,6 +119,7 @@ module.exports = function draw(gd) { var gHeader = d3.select(this); var _gButton = menuOpts.type === 'dropdown' ? gButton : null; + Plots.manageCommandObserver(gd, menuOpts, menuOpts.buttons, function(data) { setActive(gd, menuOpts, menuOpts.buttons[data.index], gHeader, _gButton, scrollBox, data.index, true); }); @@ -306,10 +307,14 @@ function drawButtons(gd, gHeader, gButton, scrollBox, menuOpts) { // skip `dragend` events if(d3.event.defaultPrevented) return; - setActive(gd, menuOpts, buttonOpts, gHeader, gButton, scrollBox, buttonIndex); - if(buttonOpts.execute) { - Plots.executeAPICommand(gd, buttonOpts.method, buttonOpts.args); + if(buttonOpts.args2 && menuOpts.active === buttonIndex) { + setActive(gd, menuOpts, buttonOpts, gHeader, gButton, scrollBox, -1); + Plots.executeAPICommand(gd, buttonOpts.method, buttonOpts.args2); + } else { + setActive(gd, menuOpts, buttonOpts, gHeader, gButton, scrollBox, buttonIndex); + Plots.executeAPICommand(gd, buttonOpts.method, buttonOpts.args); + } } gd.emit('plotly_buttonclicked', {menu: menuOpts, button: buttonOpts, active: menuOpts.active}); diff --git a/test/jasmine/tests/updatemenus_test.js b/test/jasmine/tests/updatemenus_test.js index e0f86a5bbcf..81449b9dc18 100644 --- a/test/jasmine/tests/updatemenus_test.js +++ b/test/jasmine/tests/updatemenus_test.js @@ -601,6 +601,50 @@ describe('update menus interactions', function() { .then(done); }); + it('should apply update on button click (toggle via args2 case)', function(done) { + var menuOpts = { + type: 'buttons', + buttons: [{ + label: 'toggle', + method: 'restyle', + args: ['line.color', 'blue'], + args2: ['line.color', 'red'] + }] + }; + + var btn; + + function assertLineColor(msg, lineColor) { + expect(gd.data[2].line.color).toBe(lineColor, 'gd.data line.color| ' + msg); + expect(gd._fullData[2].line.color).toBe(lineColor, 'gd._fullData line.color| ' + msg); + } + + Plotly.relayout(gd, 'updatemenus', null) + .then(function() { return Plotly.relayout(gd, 'updatemenus[0]', menuOpts); }) + .then(function() { + btn = selectButton(0, {type: 'buttons'}); + assertItemColor(btn, activeColor); + assertLineColor('base', 'blue'); + return click(btn); + }) + .then(function() { + assertItemColor(btn, bgColor); + assertLineColor('base', 'red'); + return click(btn); + }) + .then(function() { + assertItemColor(btn, activeColor); + assertLineColor('base', 'blue'); + return click(btn); + }) + .then(function() { + assertItemColor(btn, bgColor); + assertLineColor('base', 'red'); + }) + .catch(failTest) + .then(done); + }); + it('should update correctly on failed binding comparisons', function(done) { // See https://github.com/plotly/plotly.js/issues/1169 // for more info. @@ -871,8 +915,10 @@ describe('update menus interactions', function() { return header; } - function selectButton(buttonIndex) { - var buttons = d3.selectAll('.' + constants.dropdownButtonClassName); + function selectButton(buttonIndex, opts) { + opts = opts || {}; + var k = opts.type === 'buttons' ? 'buttonClassName' : 'dropdownButtonClassName'; + var buttons = d3.selectAll('.' + constants[k]); var button = d3.select(buttons[0][buttonIndex]); return button; } From 62cacdbe02a348cc686dc4b4f1b7de892bd25196 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20T=C3=A9treault-Pinard?= Date: Fri, 25 Oct 2019 14:45:30 -0400 Subject: [PATCH 2/2] add baseline with a "toggle" updatemenu button --- test/image/baselines/updatemenus_toggle.png | Bin 0 -> 18590 bytes test/image/mocks/updatemenus_toggle.json | 33 ++++++++++++++++++++ 2 files changed, 33 insertions(+) create mode 100644 test/image/baselines/updatemenus_toggle.png create mode 100644 test/image/mocks/updatemenus_toggle.json diff --git a/test/image/baselines/updatemenus_toggle.png b/test/image/baselines/updatemenus_toggle.png new file mode 100644 index 0000000000000000000000000000000000000000..8652d930e56d4acb2985e8b84a959d62e942854c GIT binary patch literal 18590 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 G(EcA