diff --git a/src/components/legend/draw.js b/src/components/legend/draw.js index 8fe9f62d35f..592620c3820 100644 --- a/src/components/legend/draw.js +++ b/src/components/legend/draw.js @@ -56,8 +56,9 @@ module.exports = function draw(gd) { }); var clipPath = fullLayout._topdefs.selectAll('#' + clipId) - .data([0]) - .enter().append('clipPath') + .data([0]); + + clipPath.enter().append('clipPath') .attr('id', clipId) .append('rect'); @@ -210,7 +211,7 @@ module.exports = function draw(gd) { legend.attr('transform', 'translate(' + lx + ',' + ly + ')'); - clipPath.attr({ + clipPath.select('rect').attr({ width: opts.width, height: scrollheight, x: 0, @@ -220,7 +221,8 @@ module.exports = function draw(gd) { legend.call(Drawing.setClipUrl, clipId); // If scrollbar should be shown. - if(gd.firstRender && opts.height - scrollheight > 0 && !gd._context.staticPlot) { + if(opts.height - scrollheight > 0 && !gd._context.staticPlot) { + bg.attr({ width: opts.width - 2 * opts.borderwidth + constants.scrollBarWidth }); @@ -229,44 +231,46 @@ module.exports = function draw(gd) { width: opts.width + constants.scrollBarWidth }); - legend.node().addEventListener('wheel', function(e) { - e.preventDefault(); - scrollHandler(e.deltaY / 20); - }); - - scrollBar.node().addEventListener('mousedown', function(e) { - e.preventDefault(); + if(gd.firstRender) { + // Move scrollbar to starting position + scrollBar.call( + Drawing.setRect, + opts.width - (constants.scrollBarWidth + constants.scrollBarMargin), + constants.scrollBarMargin, + constants.scrollBarWidth, + constants.scrollBarHeight + ); + scrollBox.attr('data-scroll',0); + } - function mMove(e) { - if(e.buttons === 1) { - scrollHandler(e.movementY); - } - } + scrollHandler(0,scrollheight); - function mUp() { - scrollBar.node().removeEventListener('mousemove', mMove); - window.removeEventListener('mouseup', mUp); - } + legend.on('wheel',null); - window.addEventListener('mousemove', mMove); - window.addEventListener('mouseup', mUp); + legend.on('wheel', function() { + var e = d3.event; + e.preventDefault(); + scrollHandler(e.deltaY / 20, scrollheight); }); - // Move scrollbar to starting position on the first render - scrollBar.call( - Drawing.setRect, - opts.width - (constants.scrollBarWidth + constants.scrollBarMargin), - constants.scrollBarMargin, - constants.scrollBarWidth, - constants.scrollBarHeight - ); + scrollBar.on('.drag',null); + scrollBox.on('.drag',null); + var drag = d3.behavior.drag() + .on('drag', function() { + scrollHandler(d3.event.dy, scrollheight); + }); + + scrollBar.call(drag); + scrollBox.call(drag); + } - function scrollHandler(delta) { + + function scrollHandler(delta, scrollheight) { var scrollBarTrack = scrollheight - constants.scrollBarHeight - 2 * constants.scrollBarMargin, translateY = scrollBox.attr('data-scroll'), - scrollBoxY = Lib.constrain(translateY - delta, Math.min(scrollheight - opts.height, 0), 0), + scrollBoxY = Lib.constrain(translateY - delta, scrollheight-opts.height, 0), scrollBarY = -scrollBoxY / (opts.height - scrollheight) * scrollBarTrack + constants.scrollBarMargin; scrollBox.attr('data-scroll', scrollBoxY); diff --git a/test/jasmine/tests/legend_scroll_test.js b/test/jasmine/tests/legend_scroll_test.js index 5bdf05d8e62..607a97bdd6c 100644 --- a/test/jasmine/tests/legend_scroll_test.js +++ b/test/jasmine/tests/legend_scroll_test.js @@ -20,6 +20,11 @@ describe('The legend', function() { return gd._fullLayout._topdefs.selectAll('#legend' + uid).size(); } + function getPlotHeight(gd) { + return gd._fullLayout.height - gd._fullLayout.margin.t - gd._fullLayout.margin.b; + } + + describe('when plotted with many traces', function() { beforeEach(function() { gd = createGraph(); @@ -30,10 +35,9 @@ describe('The legend', function() { afterEach(destroyGraph); it('should not exceed plot height', function() { - var legendHeight = getBBox(legend).height, - plotHeight = gd._fullLayout.height - gd._fullLayout.margin.t - gd._fullLayout.margin.b; + var legendHeight = getBBox(legend).height; - expect(+legendHeight).toBe(plotHeight); + expect(+legendHeight).toBe(getPlotHeight(gd)); }); it('should insert a scrollbar', function() { @@ -88,10 +92,29 @@ describe('The legend', function() { done(); }); }); + + it('should resize when relayout\'ed with new height', function(done) { + var origLegendHeight = getBBox(legend).height; + + Plotly.relayout(gd, {'height': gd._fullLayout.height/2}).then(function() { + var legendHeight = getBBox(legend).height; + + //legend still exists and not duplicated + expect(countLegendGroups(gd)).toBe(1); + expect(countLegendClipPaths(gd)).toBe(1); + + // clippath resized to new height less than new plot height + expect(+legendHeight).toBe(getPlotHeight(gd)); + expect(+legendHeight).toBeLessThan(+origLegendHeight); + + done(); + }); + }); }); + describe('when plotted with few traces', function() { - var gd; + var gd, legend; beforeEach(function() { gd = createGraph(); @@ -122,6 +145,21 @@ describe('The legend', function() { done(); }); }); + + it('should resize when traces added', function(done) { + legend = document.getElementsByClassName('legend')[0]; + var origLegendHeight = getBBox(legend).height; + + Plotly.addTrace(gd, { x: [1,2,3], y: [4,3,2], name: 'Test2' }).then(function() { + var legend = document.getElementsByClassName('legend')[0]; + var legendHeight = getBBox(legend).height; + // clippath resized to show new trace + expect(+legendHeight).toBeCloseTo(+origLegendHeight+18, 0); + + done(); + }); + + }); }); });
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies: