From 576c54bf976a9c48a692c03d302502726cafcd61 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C3=89tienne=20T=C3=A9treault-Pinard?= <etienne@plot.ly>
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?= <etienne@plot.ly>
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<Su_y<

literal 0
HcmV?d00001

diff --git a/test/image/mocks/updatemenus_toggle.json b/test/image/mocks/updatemenus_toggle.json
new file mode 100644
index 00000000000..45b67ee019e
--- /dev/null
+++ b/test/image/mocks/updatemenus_toggle.json
@@ -0,0 +1,33 @@
+{
+  "data": [
+    {
+      "mode": "lines",
+      "y": [1, 1],
+      "line": {
+        "width": 5,
+        "color": "blue"
+      }
+    }
+  ],
+  "layout": {
+    "updatemenus": [
+      {
+        "type": "buttons",
+        "buttons": [
+          {
+            "label": "toggle",
+            "method": "restyle",
+            "args": [
+              "line.color",
+              "blue"
+            ],
+            "args2": [
+              "line.color",
+              "red"
+            ]
+          }
+        ]
+      }
+    ]
+  }
+}