diff --git a/src/components/legend/handle_click.js b/src/components/legend/handle_click.js index dd5ef26f1bd..ebd51c1dc09 100644 --- a/src/components/legend/handle_click.js +++ b/src/components/legend/handle_click.js @@ -1,7 +1,8 @@ 'use strict'; -var Lib = require('../../lib'); var Registry = require('../../registry'); +var Lib = require('../../lib'); +var pushUnique = Lib.pushUnique; var SHOWISOLATETIP = true; @@ -103,6 +104,8 @@ module.exports = function handleClick(g, gd, numClicks) { } } + var thisLegend = fullTrace.legend; + if(Registry.traceIs(fullTrace, 'pie-like')) { var thisLabel = legendItem.label; var thisLabelIndex = hiddenSlices.indexOf(thisLabel); @@ -111,14 +114,32 @@ module.exports = function handleClick(g, gd, numClicks) { if(thisLabelIndex === -1) hiddenSlices.push(thisLabel); else hiddenSlices.splice(thisLabelIndex, 1); } else if(mode === 'toggleothers') { - hiddenSlices = []; - gd.calcdata[0].forEach(function(d) { - if(thisLabel !== d.label) { - hiddenSlices.push(d.label); + var changed = thisLabelIndex !== -1; + var unhideList = []; + for(i = 0; i < gd.calcdata.length; i++) { + var cdi = gd.calcdata[i]; + for(j = 0; j < cdi.length; j++) { + var d = cdi[j]; + var dLabel = d.label; + + // ensure we toggle slices that are in this legend) + if(thisLegend === cdi[0].trace.legend) { + if(thisLabel !== dLabel) { + if(hiddenSlices.indexOf(dLabel) === -1) changed = true; + pushUnique(hiddenSlices, dLabel); + unhideList.push(dLabel); + } + } + } + } + + if(!changed) { + for(var q = 0; q < unhideList.length; q++) { + var pos = hiddenSlices.indexOf(unhideList[q]); + if(pos !== -1) { + hiddenSlices.splice(pos, 1); + } } - }); - if(gd._fullLayout.hiddenlabels && gd._fullLayout.hiddenlabels.length === hiddenSlices.length && thisLabelIndex === -1) { - hiddenSlices = []; } } @@ -183,7 +204,6 @@ module.exports = function handleClick(g, gd, numClicks) { } } - var thisLegend = fullTrace.legend; for(i = 0; i < fullData.length; i++) { // False is sticky; we don't change it. Also ensure we don't change states of itmes in other legend if(fullData[i].visible === false || fullData[i].legend !== thisLegend) continue; diff --git a/test/jasmine/tests/legend_test.js b/test/jasmine/tests/legend_test.js index ce6e2117562..3b939a2c3f4 100644 --- a/test/jasmine/tests/legend_test.js +++ b/test/jasmine/tests/legend_test.js @@ -1782,7 +1782,7 @@ describe('legend interaction', function() { }); }); - describe('traces in different legends', function() { + describe('for regular traces in different legends', function() { beforeEach(function(done) { Plotly.newPlot(gd, [ {x: [1, 2], y: [0, 1], visible: false}, @@ -2337,6 +2337,78 @@ describe('legend interaction', function() { .then(done, done.fail); }, 2 * jasmine.DEFAULT_TIMEOUT_INTERVAL); }); + + describe('should honor *itemclick* and *itemdoubleclick* settings | case of pie in multiple legends', function() { + var _assert; + + function run() { + return Promise.resolve() + .then(click(0, 1)).then(_assert(['legendonly', true, true, true, true, true])) + .then(click(0, 1)).then(_assert([true, true, true, true, true, true])) + .then(click(0, 2)).then(_assert([true, 'legendonly', 'legendonly', true, true, true])) + .then(click(0, 2)).then(_assert([true, true, true, true, true, true])) + .then(function() { + return Plotly.relayout(gd, { + 'legend.itemclick': false, + 'legend.itemdoubleclick': false + }); + }) + .then(delay(100)) + .then(click(0, 1)).then(_assert([true, true, true, true, true, true])) + .then(click(0, 2)).then(_assert([true, true, true, true, true, true])) + .then(function() { + return Plotly.relayout(gd, { + 'legend.itemclick': 'toggleothers', + 'legend.itemdoubleclick': 'toggle' + }); + }) + .then(delay(100)) + .then(click(0, 1)).then(_assert([true, 'legendonly', 'legendonly', true, true, true])) + .then(click(0, 1)).then(_assert([true, true, true, true, true, true])) + .then(click(0, 2)).then(_assert(['legendonly', true, true, true, true, true])) + .then(click(0, 2)).then(_assert([true, true, true, true, true, true])); + } + + _assert = function(_exp) { + return function() { + var exp = []; + if(_exp[0] === 'legendonly') exp.push('F'); + if(_exp[1] === 'legendonly') exp.push('E'); + if(_exp[2] === 'legendonly') exp.push('D'); + if(_exp[3] === 'legendonly') exp.push('C'); + if(_exp[4] === 'legendonly') exp.push('B'); + if(_exp[5] === 'legendonly') exp.push('A'); + expect(gd._fullLayout.hiddenlabels || []).toEqual(exp); + }; + }; + + it('- pie case | multiple legends', function(done) { + Plotly.newPlot(gd, [{ + legend: 'legend2', + type: 'pie', + labels: ['A', 'B', 'C'], + values: [1, 2, 3], + domain: { + y: [0, 0.45] + } + }, { + type: 'pie', + labels: ['D', 'E', 'F'], + values: [1, 2, 3], + domain: { + y: [0.55, 1] + } + }], { + legend2: { + y: 0.35 + }, + width: 500, + height: 500 + }) + .then(run) + .then(done, done.fail); + }, 2 * jasmine.DEFAULT_TIMEOUT_INTERVAL); + }); }); });