Skip to content

Commit a01dc4d

Browse files
authored
Merge pull request #6657 from plotly/pie-multi-legend-click
Fix double click pie slices having multiple legends
2 parents 32b6fec + 712156f commit a01dc4d

File tree

2 files changed

+102
-10
lines changed

2 files changed

+102
-10
lines changed

Diff for: src/components/legend/handle_click.js

+29-9
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
'use strict';
22

3-
var Lib = require('../../lib');
43
var Registry = require('../../registry');
4+
var Lib = require('../../lib');
5+
var pushUnique = Lib.pushUnique;
56

67
var SHOWISOLATETIP = true;
78

@@ -103,6 +104,8 @@ module.exports = function handleClick(g, gd, numClicks) {
103104
}
104105
}
105106

107+
var thisLegend = fullTrace.legend;
108+
106109
if(Registry.traceIs(fullTrace, 'pie-like')) {
107110
var thisLabel = legendItem.label;
108111
var thisLabelIndex = hiddenSlices.indexOf(thisLabel);
@@ -111,14 +114,32 @@ module.exports = function handleClick(g, gd, numClicks) {
111114
if(thisLabelIndex === -1) hiddenSlices.push(thisLabel);
112115
else hiddenSlices.splice(thisLabelIndex, 1);
113116
} else if(mode === 'toggleothers') {
114-
hiddenSlices = [];
115-
gd.calcdata[0].forEach(function(d) {
116-
if(thisLabel !== d.label) {
117-
hiddenSlices.push(d.label);
117+
var changed = thisLabelIndex !== -1;
118+
var unhideList = [];
119+
for(i = 0; i < gd.calcdata.length; i++) {
120+
var cdi = gd.calcdata[i];
121+
for(j = 0; j < cdi.length; j++) {
122+
var d = cdi[j];
123+
var dLabel = d.label;
124+
125+
// ensure we toggle slices that are in this legend)
126+
if(thisLegend === cdi[0].trace.legend) {
127+
if(thisLabel !== dLabel) {
128+
if(hiddenSlices.indexOf(dLabel) === -1) changed = true;
129+
pushUnique(hiddenSlices, dLabel);
130+
unhideList.push(dLabel);
131+
}
132+
}
133+
}
134+
}
135+
136+
if(!changed) {
137+
for(var q = 0; q < unhideList.length; q++) {
138+
var pos = hiddenSlices.indexOf(unhideList[q]);
139+
if(pos !== -1) {
140+
hiddenSlices.splice(pos, 1);
141+
}
118142
}
119-
});
120-
if(gd._fullLayout.hiddenlabels && gd._fullLayout.hiddenlabels.length === hiddenSlices.length && thisLabelIndex === -1) {
121-
hiddenSlices = [];
122143
}
123144
}
124145

@@ -183,7 +204,6 @@ module.exports = function handleClick(g, gd, numClicks) {
183204
}
184205
}
185206

186-
var thisLegend = fullTrace.legend;
187207
for(i = 0; i < fullData.length; i++) {
188208
// False is sticky; we don't change it. Also ensure we don't change states of itmes in other legend
189209
if(fullData[i].visible === false || fullData[i].legend !== thisLegend) continue;

Diff for: test/jasmine/tests/legend_test.js

+73-1
Original file line numberDiff line numberDiff line change
@@ -1782,7 +1782,7 @@ describe('legend interaction', function() {
17821782
});
17831783
});
17841784

1785-
describe('traces in different legends', function() {
1785+
describe('for regular traces in different legends', function() {
17861786
beforeEach(function(done) {
17871787
Plotly.newPlot(gd, [
17881788
{x: [1, 2], y: [0, 1], visible: false},
@@ -2337,6 +2337,78 @@ describe('legend interaction', function() {
23372337
.then(done, done.fail);
23382338
}, 2 * jasmine.DEFAULT_TIMEOUT_INTERVAL);
23392339
});
2340+
2341+
describe('should honor *itemclick* and *itemdoubleclick* settings | case of pie in multiple legends', function() {
2342+
var _assert;
2343+
2344+
function run() {
2345+
return Promise.resolve()
2346+
.then(click(0, 1)).then(_assert(['legendonly', true, true, true, true, true]))
2347+
.then(click(0, 1)).then(_assert([true, true, true, true, true, true]))
2348+
.then(click(0, 2)).then(_assert([true, 'legendonly', 'legendonly', true, true, true]))
2349+
.then(click(0, 2)).then(_assert([true, true, true, true, true, true]))
2350+
.then(function() {
2351+
return Plotly.relayout(gd, {
2352+
'legend.itemclick': false,
2353+
'legend.itemdoubleclick': false
2354+
});
2355+
})
2356+
.then(delay(100))
2357+
.then(click(0, 1)).then(_assert([true, true, true, true, true, true]))
2358+
.then(click(0, 2)).then(_assert([true, true, true, true, true, true]))
2359+
.then(function() {
2360+
return Plotly.relayout(gd, {
2361+
'legend.itemclick': 'toggleothers',
2362+
'legend.itemdoubleclick': 'toggle'
2363+
});
2364+
})
2365+
.then(delay(100))
2366+
.then(click(0, 1)).then(_assert([true, 'legendonly', 'legendonly', true, true, true]))
2367+
.then(click(0, 1)).then(_assert([true, true, true, true, true, true]))
2368+
.then(click(0, 2)).then(_assert(['legendonly', true, true, true, true, true]))
2369+
.then(click(0, 2)).then(_assert([true, true, true, true, true, true]));
2370+
}
2371+
2372+
_assert = function(_exp) {
2373+
return function() {
2374+
var exp = [];
2375+
if(_exp[0] === 'legendonly') exp.push('F');
2376+
if(_exp[1] === 'legendonly') exp.push('E');
2377+
if(_exp[2] === 'legendonly') exp.push('D');
2378+
if(_exp[3] === 'legendonly') exp.push('C');
2379+
if(_exp[4] === 'legendonly') exp.push('B');
2380+
if(_exp[5] === 'legendonly') exp.push('A');
2381+
expect(gd._fullLayout.hiddenlabels || []).toEqual(exp);
2382+
};
2383+
};
2384+
2385+
it('- pie case | multiple legends', function(done) {
2386+
Plotly.newPlot(gd, [{
2387+
legend: 'legend2',
2388+
type: 'pie',
2389+
labels: ['A', 'B', 'C'],
2390+
values: [1, 2, 3],
2391+
domain: {
2392+
y: [0, 0.45]
2393+
}
2394+
}, {
2395+
type: 'pie',
2396+
labels: ['D', 'E', 'F'],
2397+
values: [1, 2, 3],
2398+
domain: {
2399+
y: [0.55, 1]
2400+
}
2401+
}], {
2402+
legend2: {
2403+
y: 0.35
2404+
},
2405+
width: 500,
2406+
height: 500
2407+
})
2408+
.then(run)
2409+
.then(done, done.fail);
2410+
}, 2 * jasmine.DEFAULT_TIMEOUT_INTERVAL);
2411+
});
23402412
});
23412413
});
23422414

0 commit comments

Comments
 (0)