Skip to content

Allow toggling legend to show just 1 series (or group) by double clicking #1432

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Mar 13, 2017
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
186 changes: 186 additions & 0 deletions test/jasmine/tests/legend_test.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
var Plotly = require('@lib/index');
var Plots = require('@src/plots/plots');
var Lib = require('@src/lib');
var DBLCLICKDELAY = require('@src/constants/interactions').DBLCLICKDELAY;

var Legend = require('@src/components/legend');
var getLegendData = require('@src/components/legend/get_legend_data');
Expand Down Expand Up @@ -628,3 +629,188 @@ describe('legend restyle update', function() {
});
});
});

describe('legend interaction', function() {
'use strict';

describe('pie chart', function() {
var mockCopy, gd, legendItems, legendItem, legendLabels, legendLabel;
var testEntry = 2;

beforeAll(function(done) {
var mock = require('@mocks/pie_simple.json');
mockCopy = Lib.extendDeep({}, mock);
gd = createGraphDiv();

Plotly.plot(gd, mockCopy.data, mockCopy.layout).then(function() {
legendItems = d3.selectAll('rect.legendtoggle')[0];
legendLabels = d3.selectAll('text.legendtext')[0];
legendItem = legendItems[testEntry];
legendLabel = legendLabels[testEntry].innerHTML;
done();
});
});
afterAll(function() {
destroyGraphDiv();
});
describe('single click', function() {
it('should hide slice', function(done) {
legendItem.dispatchEvent(new MouseEvent('mousedown'));
legendItem.dispatchEvent(new MouseEvent('mouseup'));
setTimeout(function() {
expect(gd._fullLayout.hiddenlabels.length).toBe(1);
expect(gd._fullLayout.hiddenlabels[0]).toBe(legendLabel);
done();
}, DBLCLICKDELAY * 2);
});
it('should fade legend item', function() {
expect(+legendItem.parentNode.style.opacity).toBeLessThan(1);
});
it('should unhide slice', function(done) {
legendItem.dispatchEvent(new MouseEvent('mousedown'));
legendItem.dispatchEvent(new MouseEvent('mouseup'));
setTimeout(function() {
expect(gd._fullLayout.hiddenlabels.length).toBe(0);
done();
}, DBLCLICKDELAY * 2);
});
it('should unfade legend item', function() {
expect(+legendItem.parentNode.style.opacity).toBe(1);
});
});

describe('double click', function() {
it('should hide other slices', function(done) {
legendItem.dispatchEvent(new MouseEvent('mousedown'));
legendItem.dispatchEvent(new MouseEvent('mouseup'));
legendItem.dispatchEvent(new MouseEvent('mousedown'));
legendItem.dispatchEvent(new MouseEvent('mouseup'));
setTimeout(function() {
expect(gd._fullLayout.hiddenlabels.length).toBe((legendItems.length - 1));
expect(gd._fullLayout.hiddenlabels.indexOf(legendLabel)).toBe(-1);
done();
}, DBLCLICKDELAY);
});
it('should fade other legend items', function() {
var legendItemi;
for(var i = 0; i < legendItems.length; i++) {
legendItemi = legendItems[i];
if(i === testEntry) {
expect(+legendItemi.parentNode.style.opacity).toBe(1);
} else {
expect(+legendItemi.parentNode.style.opacity).toBeLessThan(1);
}
}
});
it('should unhide all slices', function(done) {
legendItem.dispatchEvent(new MouseEvent('mousedown'));
legendItem.dispatchEvent(new MouseEvent('mouseup'));
legendItem.dispatchEvent(new MouseEvent('mousedown'));
legendItem.dispatchEvent(new MouseEvent('mouseup'));
setTimeout(function() {
expect(gd._fullLayout.hiddenlabels.length).toBe(0);
done();
}, DBLCLICKDELAY);
});
it('should unfade legend items', function() {
var legendItemi;
for(var i = 0; i < legendItems.length; i++) {
legendItemi = legendItems[i];
expect(+legendItemi.parentNode.style.opacity).toBe(1);
}
});
});
});
describe('non-pie chart', function() {
var mockCopy, gd, legendItems, legendItem;
var testEntry = 2;

beforeAll(function(done) {
var mock = require('@mocks/29.json');
mockCopy = Lib.extendDeep({}, mock);
gd = createGraphDiv();

Plotly.plot(gd, mockCopy.data, mockCopy.layout).then(function() {
legendItems = d3.selectAll('rect.legendtoggle')[0];
legendItem = legendItems[testEntry];
done();
});
});
afterAll(function() {
destroyGraphDiv();
});

describe('single click', function() {
it('should hide series', function(done) {
legendItem.dispatchEvent(new MouseEvent('mousedown'));
legendItem.dispatchEvent(new MouseEvent('mouseup'));
setTimeout(function() {
expect(gd.data[2].visible).toBe('legendonly');
done();
}, DBLCLICKDELAY * 2);
});
it('should fade legend item', function() {
expect(+legendItem.parentNode.style.opacity).toBeLessThan(1);
});
it('should unhide series', function(done) {
legendItem.dispatchEvent(new MouseEvent('mousedown'));
legendItem.dispatchEvent(new MouseEvent('mouseup'));
setTimeout(function() {
expect(gd.data[2].visible).toBe(true);
done();
}, DBLCLICKDELAY * 2);
});
it('should unfade legend item', function() {
expect(+legendItem.parentNode.style.opacity).toBe(1);
});
});
describe('double click', function() {
it('should hide series', function(done) {
legendItem.dispatchEvent(new MouseEvent('mousedown'));
legendItem.dispatchEvent(new MouseEvent('mouseup'));
legendItem.dispatchEvent(new MouseEvent('mousedown'));
legendItem.dispatchEvent(new MouseEvent('mouseup'));
setTimeout(function() {
for(var i = 0; i < legendItems.length; i++) {
if(i === testEntry) {
expect(gd.data[i].visible).toBe(true);
} else {
expect(gd.data[i].visible).toBe('legendonly');
}
}
done();
}, DBLCLICKDELAY);
});
it('should fade legend item', function() {
var legendItemi;
for(var i = 0; i < legendItems.length; i++) {
legendItemi = legendItems[i];
if(i === testEntry) {
expect(+legendItemi.parentNode.style.opacity).toBe(1);
} else {
expect(+legendItemi.parentNode.style.opacity).toBeLessThan(1);
}
}
});
it('should unhide series', function(done) {
legendItem.dispatchEvent(new MouseEvent('mousedown'));
legendItem.dispatchEvent(new MouseEvent('mouseup'));
legendItem.dispatchEvent(new MouseEvent('mousedown'));
legendItem.dispatchEvent(new MouseEvent('mouseup'));
setTimeout(function() {
for(var i = 0; i < legendItems.length; i++) {
expect(gd.data[i].visible).toBe(true);
}
done();
}, DBLCLICKDELAY);
});
it('should unfade legend items', function() {
var legendItemi;
for(var i = 0; i < legendItems.length; i++) {
legendItemi = legendItems[i];
expect(+legendItemi.parentNode.style.opacity).toBe(1);
}
});
});
});
});
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These tests are great, and they lock down a lot more behavior than just what you added, thanks! 🍻

Can we reduce the delays a bit? I guess the DBLCLICKDELAY * 2 delays just need to be > DBLCLICKDELAY, can we drop them to DBLCLICKDELAY + 20 or something? And the delays after a double click can presumably be very short (perhaps 20)?

Non-blocking, but you might also want to make helpers to reduce repetition generating the mouse events. Either click(element) and doubleclick(element) or click(element, count).

Oh, but this one is blocking: we have click and double_click helpers in test assets - which aren't useful here because they're linked to mouse coordinates rather than an element - but I see that double_click uses DBLCLICKDELAY so needs its reference updated. I guess the tests that use it will still pass with no delay, but not exactly what we wanted them to be testing...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lowered the delays which uncovered a bug in the implementation, so both have been fixed.

Updated to DBLCLICKDELAY done in the double_click asset.

Didn't introduce any new click helpers for now, because those existing assets will be cause for confusion. Probably worth a general refactor as there are a few dozen mousedown+mouseup combo clicks across other tests.