Skip to content

Commit afeaf5e

Browse files
author
Robert Paskowitz
committed
Allow toggling legend to show just 1 series (or group) by double clicking
1 parent b252075 commit afeaf5e

File tree

2 files changed

+86
-26
lines changed

2 files changed

+86
-26
lines changed

src/components/legend/constants.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,6 @@ module.exports = {
1212
scrollBarWidth: 4,
1313
scrollBarHeight: 20,
1414
scrollBarColor: '#808BA4',
15-
scrollBarMargin: 4
15+
scrollBarMargin: 4,
16+
DBLCLICKDELAY: 300
1617
};

src/components/legend/draw.js

+84-25
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ module.exports = function draw(gd) {
3333

3434
if(!fullLayout._infolayer || !gd.calcdata) return;
3535

36+
if(!gd._legendMouseDownTime) gd._legendMouseDownTime = 0;
37+
3638
var opts = fullLayout.legend,
3739
legendData = fullLayout.showlegend && getLegendData(gd.calcdata, opts),
3840
hiddenSlices = fullLayout.hiddenlabels || [];
@@ -395,9 +397,9 @@ function drawTexts(g, gd) {
395397
}
396398

397399
function setupTraceToggle(g, gd) {
398-
var hiddenSlices = gd._fullLayout.hiddenlabels ?
399-
gd._fullLayout.hiddenlabels.slice() :
400-
[];
400+
var newMouseDownTime,
401+
numClicks = 1,
402+
DBLCLICKDELAY = constants.DBLCLICKDELAY;
401403

402404
var traceToggle = g.selectAll('rect')
403405
.data([0]);
@@ -408,41 +410,98 @@ function setupTraceToggle(g, gd) {
408410
.attr('pointer-events', 'all')
409411
.call(Color.fill, 'rgba(0,0,0,0)');
410412

411-
traceToggle.on('click', function() {
413+
414+
traceToggle.on('mousedown', function() {
415+
newMouseDownTime = (new Date()).getTime();
416+
if(newMouseDownTime - gd._legendMouseDownTime < DBLCLICKDELAY) {
417+
// in a click train
418+
numClicks += 1;
419+
}
420+
else {
421+
// new click train
422+
numClicks = 1;
423+
gd._legendMouseDownTime = newMouseDownTime;
424+
}
425+
});
426+
traceToggle.on('mouseup', function() {
412427
if(gd._dragged) return;
428+
var legend = gd._fullLayout.legend;
413429

414-
var legendItem = g.data()[0][0],
415-
fullData = gd._fullData,
416-
trace = legendItem.trace,
417-
legendgroup = trace.legendgroup,
418-
traceIndicesInGroup = [],
419-
tracei,
420-
newVisible;
430+
if((new Date()).getTime() - gd._legendMouseDownTime > DBLCLICKDELAY) {
431+
numClicks = Math.max(numClicks - 1, 1);
432+
}
421433

422-
if(Registry.traceIs(trace, 'pie')) {
423-
var thisLabel = legendItem.label,
424-
thisLabelIndex = hiddenSlices.indexOf(thisLabel);
434+
if(numClicks === 1) {
435+
legend._clickTimeout = setTimeout(function() { handleClick(g, gd, numClicks); }, 300);
436+
} else if(numClicks === 2) {
437+
if(legend._clickTimeout) {
438+
clearTimeout(legend._clickTimeout);
439+
}
440+
handleClick(g, gd, numClicks);
441+
}
442+
});
443+
}
444+
445+
function handleClick(g, gd, numClicks) {
446+
var hiddenSlices = gd._fullLayout.hiddenlabels ?
447+
gd._fullLayout.hiddenlabels.slice() :
448+
[];
425449

450+
var legendItem = g.data()[0][0],
451+
fullData = gd._fullData,
452+
trace = legendItem.trace,
453+
legendgroup = trace.legendgroup,
454+
traceIndicesInGroup = [],
455+
tracei,
456+
newVisible;
457+
458+
if(Registry.traceIs(trace, 'pie')) {
459+
var thisLabel = legendItem.label,
460+
thisLabelIndex = hiddenSlices.indexOf(thisLabel);
461+
462+
if(numClicks === 1) {
426463
if(thisLabelIndex === -1) hiddenSlices.push(thisLabel);
427464
else hiddenSlices.splice(thisLabelIndex, 1);
465+
} else if(numClicks === 2) {
466+
hiddenSlices = [];
467+
gd.calcdata[0].forEach(function(d) {
468+
if(thisLabel !== d.label) {
469+
hiddenSlices.push(d.label);
470+
}
471+
});
472+
}
473+
474+
Plotly.relayout(gd, 'hiddenlabels', hiddenSlices);
475+
} else {
476+
var otherTraces = [],
477+
traceIndex,
478+
i;
479+
480+
for(i = 0; i < fullData.length; i++) {
481+
otherTraces.push(i);
482+
}
428483

429-
Plotly.relayout(gd, 'hiddenlabels', hiddenSlices);
484+
if(legendgroup === '') {
485+
traceIndicesInGroup = [trace.index];
486+
otherTraces.splice(trace.index, 1);
430487
} else {
431-
if(legendgroup === '') {
432-
traceIndicesInGroup = [trace.index];
433-
} else {
434-
for(var i = 0; i < fullData.length; i++) {
435-
tracei = fullData[i];
436-
if(tracei.legendgroup === legendgroup) {
437-
traceIndicesInGroup.push(tracei.index);
438-
}
488+
for(i = 0; i < fullData.length; i++) {
489+
tracei = fullData[i];
490+
if(tracei.legendgroup === legendgroup) {
491+
traceIndicesInGroup.push(tracei.index);
492+
traceIndex = otherTraces.indexOf(i);
493+
otherTraces.splice(traceIndex, 1);
439494
}
440495
}
441-
496+
}
497+
if(numClicks === 1) {
442498
newVisible = trace.visible === true ? 'legendonly' : true;
443499
Plotly.restyle(gd, 'visible', newVisible, traceIndicesInGroup);
500+
} else if(numClicks === 2) {
501+
Plotly.restyle(gd, 'visible', true, traceIndicesInGroup);
502+
Plotly.restyle(gd, 'visible', 'legendonly', otherTraces);
444503
}
445-
});
504+
}
446505
}
447506

448507
function computeTextDimensions(g, gd) {

0 commit comments

Comments
 (0)