Skip to content

Commit a4cc99e

Browse files
committed
Merge pull request #365 from plotly/legend-fixup
Legend fixups [fixes #348]
2 parents e03e9e0 + 927af3b commit a4cc99e

File tree

2 files changed

+88
-38
lines changed

2 files changed

+88
-38
lines changed

src/components/legend/draw.js

+36-32
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,9 @@ module.exports = function draw(gd) {
5656
});
5757

5858
var clipPath = fullLayout._topdefs.selectAll('#' + clipId)
59-
.data([0])
60-
.enter().append('clipPath')
59+
.data([0]);
60+
61+
clipPath.enter().append('clipPath')
6162
.attr('id', clipId)
6263
.append('rect');
6364

@@ -210,7 +211,7 @@ module.exports = function draw(gd) {
210211

211212
legend.attr('transform', 'translate(' + lx + ',' + ly + ')');
212213

213-
clipPath.attr({
214+
clipPath.select('rect').attr({
214215
width: opts.width,
215216
height: scrollheight,
216217
x: 0,
@@ -220,7 +221,8 @@ module.exports = function draw(gd) {
220221
legend.call(Drawing.setClipUrl, clipId);
221222

222223
// If scrollbar should be shown.
223-
if(gd.firstRender && opts.height - scrollheight > 0 && !gd._context.staticPlot) {
224+
if(opts.height - scrollheight > 0 && !gd._context.staticPlot) {
225+
224226
bg.attr({
225227
width: opts.width - 2 * opts.borderwidth + constants.scrollBarWidth
226228
});
@@ -229,44 +231,46 @@ module.exports = function draw(gd) {
229231
width: opts.width + constants.scrollBarWidth
230232
});
231233

232-
legend.node().addEventListener('wheel', function(e) {
233-
e.preventDefault();
234-
scrollHandler(e.deltaY / 20);
235-
});
236-
237-
scrollBar.node().addEventListener('mousedown', function(e) {
238-
e.preventDefault();
234+
if(gd.firstRender) {
235+
// Move scrollbar to starting position
236+
scrollBar.call(
237+
Drawing.setRect,
238+
opts.width - (constants.scrollBarWidth + constants.scrollBarMargin),
239+
constants.scrollBarMargin,
240+
constants.scrollBarWidth,
241+
constants.scrollBarHeight
242+
);
243+
scrollBox.attr('data-scroll',0);
244+
}
239245

240-
function mMove(e) {
241-
if(e.buttons === 1) {
242-
scrollHandler(e.movementY);
243-
}
244-
}
246+
scrollHandler(0,scrollheight);
245247

246-
function mUp() {
247-
scrollBar.node().removeEventListener('mousemove', mMove);
248-
window.removeEventListener('mouseup', mUp);
249-
}
248+
legend.on('wheel',null);
250249

251-
window.addEventListener('mousemove', mMove);
252-
window.addEventListener('mouseup', mUp);
250+
legend.on('wheel', function() {
251+
var e = d3.event;
252+
e.preventDefault();
253+
scrollHandler(e.deltaY / 20, scrollheight);
253254
});
254255

255-
// Move scrollbar to starting position on the first render
256-
scrollBar.call(
257-
Drawing.setRect,
258-
opts.width - (constants.scrollBarWidth + constants.scrollBarMargin),
259-
constants.scrollBarMargin,
260-
constants.scrollBarWidth,
261-
constants.scrollBarHeight
262-
);
256+
scrollBar.on('.drag',null);
257+
scrollBox.on('.drag',null);
258+
var drag = d3.behavior.drag()
259+
.on('drag', function() {
260+
scrollHandler(d3.event.dy, scrollheight);
261+
});
262+
263+
scrollBar.call(drag);
264+
scrollBox.call(drag);
265+
263266
}
264267

265-
function scrollHandler(delta) {
268+
269+
function scrollHandler(delta, scrollheight) {
266270

267271
var scrollBarTrack = scrollheight - constants.scrollBarHeight - 2 * constants.scrollBarMargin,
268272
translateY = scrollBox.attr('data-scroll'),
269-
scrollBoxY = Lib.constrain(translateY - delta, Math.min(scrollheight - opts.height, 0), 0),
273+
scrollBoxY = Lib.constrain(translateY - delta, scrollheight-opts.height, 0),
270274
scrollBarY = -scrollBoxY / (opts.height - scrollheight) * scrollBarTrack + constants.scrollBarMargin;
271275

272276
scrollBox.attr('data-scroll', scrollBoxY);

test/jasmine/tests/legend_scroll_test.js

+52-6
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
var Plotly = require('@lib/index');
2+
var Lib = require('@src/lib');
3+
24
var createGraph = require('../assets/create_graph_div');
35
var destroyGraph = require('../assets/destroy_graph_div');
46
var getBBox = require('../assets/get_bbox');
@@ -20,20 +22,29 @@ describe('The legend', function() {
2022
return gd._fullLayout._topdefs.selectAll('#legend' + uid).size();
2123
}
2224

25+
function getPlotHeight(gd) {
26+
return gd._fullLayout.height - gd._fullLayout.margin.t - gd._fullLayout.margin.b;
27+
}
28+
29+
2330
describe('when plotted with many traces', function() {
24-
beforeEach(function() {
31+
beforeEach(function(done) {
2532
gd = createGraph();
26-
Plotly.plot(gd, mock.data, mock.layout);
27-
legend = document.getElementsByClassName('legend')[0];
33+
34+
var mockCopy = Lib.extendDeep({}, mock);
35+
36+
Plotly.plot(gd, mockCopy.data, mockCopy.layout).then(function() {
37+
legend = document.getElementsByClassName('legend')[0];
38+
done();
39+
});
2840
});
2941

3042
afterEach(destroyGraph);
3143

3244
it('should not exceed plot height', function() {
33-
var legendHeight = getBBox(legend).height,
34-
plotHeight = gd._fullLayout.height - gd._fullLayout.margin.t - gd._fullLayout.margin.b;
45+
var legendHeight = getBBox(legend).height;
3546

36-
expect(+legendHeight).toBe(plotHeight);
47+
expect(+legendHeight).toBe(getPlotHeight(gd));
3748
});
3849

3950
it('should insert a scrollbar', function() {
@@ -88,8 +99,27 @@ describe('The legend', function() {
8899
done();
89100
});
90101
});
102+
103+
it('should resize when relayout\'ed with new height', function(done) {
104+
var origLegendHeight = getBBox(legend).height;
105+
106+
Plotly.relayout(gd, 'height', gd._fullLayout.height / 2).then(function() {
107+
var legendHeight = getBBox(legend).height;
108+
109+
//legend still exists and not duplicated
110+
expect(countLegendGroups(gd)).toBe(1);
111+
expect(countLegendClipPaths(gd)).toBe(1);
112+
113+
// clippath resized to new height less than new plot height
114+
expect(+legendHeight).toBe(getPlotHeight(gd));
115+
expect(+legendHeight).toBeLessThan(+origLegendHeight);
116+
117+
done();
118+
});
119+
});
91120
});
92121

122+
93123
describe('when plotted with few traces', function() {
94124
var gd;
95125

@@ -122,6 +152,22 @@ describe('The legend', function() {
122152
done();
123153
});
124154
});
155+
156+
it('should resize when traces added', function(done) {
157+
var origLegend = document.getElementsByClassName('legend')[0];
158+
var origLegendHeight = getBBox(origLegend).height;
159+
160+
Plotly.addTraces(gd, { x: [1,2,3], y: [4,3,2], name: 'Test2' }).then(function() {
161+
var legend = document.getElementsByClassName('legend')[0];
162+
var legendHeight = getBBox(legend).height;
163+
164+
// clippath resized to show new trace
165+
expect(+legendHeight).toBeCloseTo(+origLegendHeight + 19, 0);
166+
167+
done();
168+
});
169+
170+
});
125171
});
126172
});
127173

0 commit comments

Comments
 (0)