Skip to content

Commit d12d417

Browse files
authored
Merge pull request #1700 from plotly/add-execute-flag-to-components
Add `execute` flag to components
2 parents f27885d + a84b2e7 commit d12d417

File tree

9 files changed

+74
-6
lines changed

9 files changed

+74
-6
lines changed

src/components/sliders/attributes.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,18 @@ var stepsAttrs = {
5353
'Sets the value of the slider step, used to refer to the step programatically.',
5454
'Defaults to the slider label if not provided.'
5555
].join(' ')
56+
},
57+
execute: {
58+
valType: 'boolean',
59+
role: 'info',
60+
dflt: true,
61+
description: [
62+
'When true, the API method is executed. When false, all other behaviors are the same',
63+
'and command execution is skipped. This may be useful when hooking into, for example,',
64+
'the `plotly_sliderchange` method and executing the API command manually without losing',
65+
'the benefit of the slider automatically binding to the state of the plot through the',
66+
'specification of `method` and `args`.'
67+
].join(' ')
5668
}
5769
};
5870

src/components/sliders/defaults.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ function stepsDefaults(sliderIn, sliderOut) {
104104
coerce('args');
105105
coerce('label', 'step-' + i);
106106
coerce('value', valueOut.label);
107+
coerce('execute');
107108

108109
valuesOut.push(valueOut);
109110
}

src/components/sliders/draw.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -409,7 +409,9 @@ function setActive(gd, sliderGroup, sliderOpts, index, doCallback, doTransition)
409409
var _step = sliderGroup._nextMethod.step;
410410
if(!_step.method) return;
411411

412-
Plots.executeAPICommand(gd, _step.method, _step.args);
412+
if(_step.execute) {
413+
Plots.executeAPICommand(gd, _step.method, _step.args);
414+
}
413415

414416
sliderGroup._nextMethod = null;
415417
sliderGroup._nextMethodRaf = null;

src/components/updatemenus/attributes.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,18 @@ var buttonsAttrs = {
4444
role: 'info',
4545
dflt: '',
4646
description: 'Sets the text label to appear on the button.'
47+
},
48+
execute: {
49+
valType: 'boolean',
50+
role: 'info',
51+
dflt: true,
52+
description: [
53+
'When true, the API method is executed. When false, all other behaviors are the same',
54+
'and command execution is skipped. This may be useful when hooking into, for example,',
55+
'the `plotly_buttonclicked` method and executing the API command manually without losing',
56+
'the benefit of the updatemenu automatically binding to the state of the plot through the',
57+
'specification of `method` and `args`.'
58+
].join(' ')
4759
}
4860
};
4961

src/components/updatemenus/defaults.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ function buttonsDefaults(menuIn, menuOut) {
8484

8585
coerce('args');
8686
coerce('label');
87+
coerce('execute');
8788

8889
buttonOut._index = i;
8990
buttonsOut.push(buttonOut);

src/components/updatemenus/draw.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -331,7 +331,9 @@ function drawButtons(gd, gHeader, gButton, scrollBox, menuOpts) {
331331

332332
setActive(gd, menuOpts, buttonOpts, gHeader, gButton, scrollBox, buttonIndex);
333333

334-
Plots.executeAPICommand(gd, buttonOpts.method, buttonOpts.args);
334+
if(buttonOpts.execute) {
335+
Plots.executeAPICommand(gd, buttonOpts.method, buttonOpts.args);
336+
}
335337

336338
gd.emit('plotly_buttonclicked', {menu: menuOpts, button: buttonOpts, active: menuOpts.active});
337339
});

test/image/mocks/sliders.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,8 @@
115115
}, {
116116
"label": "purple",
117117
"method": "restyle",
118-
"args": [{"marker.color": "purple"}]
118+
"args": [{"marker.color": "purple"}],
119+
"execute": false
119120
}],
120121
"visible": true,
121122
"x": 0.5,

test/jasmine/tests/sliders_test.js

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -99,15 +99,18 @@ describe('sliders defaults', function() {
9999
expect(layoutOut.sliders[0].steps).toEqual([{
100100
method: 'relayout',
101101
label: 'Label #1',
102-
value: 'label-1'
102+
value: 'label-1',
103+
execute: true
103104
}, {
104105
method: 'update',
105106
label: 'Label #2',
106-
value: 'Label #2'
107+
value: 'Label #2',
108+
execute: true
107109
}, {
108110
method: 'animate',
109111
label: 'step-2',
110-
value: 'lacks-label'
112+
value: 'lacks-label',
113+
execute: true
111114
}]);
112115
});
113116

@@ -131,6 +134,7 @@ describe('sliders defaults', function() {
131134
args: ['title', 'Hello World'],
132135
label: 'step-1',
133136
value: 'step-1',
137+
execute: true
134138
});
135139
});
136140

@@ -155,6 +159,7 @@ describe('sliders defaults', function() {
155159
args: ['title', 'Hello World'],
156160
label: 'step-1',
157161
value: 'step-1',
162+
execute: true
158163
});
159164
});
160165

@@ -175,11 +180,13 @@ describe('sliders defaults', function() {
175180
method: 'skip',
176181
label: 'step-0',
177182
value: 'step-0',
183+
execute: true,
178184
}, {
179185
method: 'skip',
180186
args: ['title', 'Hello World'],
181187
label: 'step-1',
182188
value: 'step-1',
189+
execute: true,
183190
});
184191
});
185192

test/jasmine/tests/updatemenus_test.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ describe('update menus defaults', function() {
111111
expect(layoutOut.updatemenus[0].buttons[0]).toEqual({
112112
method: 'relayout',
113113
args: ['title', 'Hello World'],
114+
execute: true,
114115
label: '',
115116
_index: 1
116117
});
@@ -135,6 +136,7 @@ describe('update menus defaults', function() {
135136
expect(layoutOut.updatemenus[0].buttons[0]).toEqual({
136137
method: 'relayout',
137138
args: ['title', 'Hello World'],
139+
execute: true,
138140
label: '',
139141
_index: 1
140142
});
@@ -156,11 +158,13 @@ describe('update menus defaults', function() {
156158
expect(layoutOut.updatemenus[0].buttons[0]).toEqual({
157159
method: 'skip',
158160
label: '',
161+
execute: true,
159162
_index: 0
160163
}, {
161164
method: 'skip',
162165
args: ['title', 'Hello World'],
163166
label: '',
167+
execute: true,
164168
_index: 1
165169
});
166170
});
@@ -444,6 +448,32 @@ describe('update menus interactions', function() {
444448
});
445449
});
446450

451+
it('should execute the API command when execute = true', function(done) {
452+
expect(gd.data[0].line.color).toEqual('blue');
453+
454+
click(selectHeader(0)).then(function() {
455+
return click(selectButton(2));
456+
}).then(function() {
457+
// Has been changed:
458+
expect(gd.data[0].line.color).toEqual('green');
459+
}).catch(fail).then(done);
460+
});
461+
462+
it('should not execute the API command when execute = false', function(done) {
463+
// This test is identical to the one above, except that it disables
464+
// the command by setting execute = false first:
465+
expect(gd.data[0].line.color).toEqual('blue');
466+
467+
Plotly.relayout(gd, 'updatemenus[0].buttons[2].execute', false).then(function() {
468+
return click(selectHeader(0));
469+
}).then(function() {
470+
return click(selectButton(2));
471+
}).then(function() {
472+
// Is unchanged:
473+
expect(gd.data[0].line.color).toEqual('blue');
474+
}).catch(fail).then(done);
475+
});
476+
447477
it('should emit an event on button click', function(done) {
448478
var clickCnt = 0;
449479
var data = [];

0 commit comments

Comments
 (0)