diff --git a/src/components/rangeslider/draw.js b/src/components/rangeslider/draw.js index 1a7fe176df6..5eeed58e1cf 100644 --- a/src/components/rangeslider/draw.js +++ b/src/components/rangeslider/draw.js @@ -100,7 +100,7 @@ module.exports = function(gd) { var margin = fullLayout.margin; var graphSize = fullLayout._size; var domain = axisOpts.domain; - var tickHeight = (axisOpts._boundingBox || {}).height || 0; + var tickHeight = opts._tickHeight; var oppBottom = opts._oppBottom; diff --git a/src/components/rangeslider/helpers.js b/src/components/rangeslider/helpers.js index 6009d0d51a1..9ab9397ae47 100644 --- a/src/components/rangeslider/helpers.js +++ b/src/components/rangeslider/helpers.js @@ -54,6 +54,7 @@ exports.autoMarginOpts = function(gd, ax) { opts._oppBottom = oppBottom; var tickHeight = (ax.side === 'bottom' && ax._boundingBox.height) || 0; + opts._tickHeight = tickHeight; return { x: 0, diff --git a/src/plot_api/plot_api.js b/src/plot_api/plot_api.js index d95a31ca72e..5107d512715 100644 --- a/src/plot_api/plot_api.js +++ b/src/plot_api/plot_api.js @@ -1937,8 +1937,19 @@ function addAxRangeSequence(seq, rangesAltered) { // subroutine of its own so that finalDraw always gets // executed after drawData var drawAxes = rangesAltered ? - function(gd) { return Axes.draw(gd, Object.keys(rangesAltered), {skipTitle: true}); } : - function(gd) { return Axes.draw(gd, 'redraw'); }; + function(gd) { + var opts = {skipTitle: true}; + for(var id in rangesAltered) { + if(Axes.getFromId(gd, id).automargin) { + opts = {}; + break; + } + } + return Axes.draw(gd, Object.keys(rangesAltered), opts); + } : + function(gd) { + return Axes.draw(gd, 'redraw'); + }; seq.push( subroutines.doAutoRangeAndConstraints, diff --git a/test/image/baselines/range_slider_multiple.png b/test/image/baselines/range_slider_multiple.png index 5761b38161d..4d21f5ebaed 100644 Binary files a/test/image/baselines/range_slider_multiple.png and b/test/image/baselines/range_slider_multiple.png differ diff --git a/test/image/baselines/range_slider_top_axis.png b/test/image/baselines/range_slider_top_axis.png new file mode 100644 index 00000000000..e42803653b3 Binary files /dev/null and b/test/image/baselines/range_slider_top_axis.png differ diff --git a/test/image/mocks/range_slider_top_axis.json b/test/image/mocks/range_slider_top_axis.json new file mode 100644 index 00000000000..71af955bcdd --- /dev/null +++ b/test/image/mocks/range_slider_top_axis.json @@ -0,0 +1,39 @@ +{ + "data": [ + { + "x": [ + "a", + "b", + "c", + "d", + "long category", + "another even longer", + "the longest one yet!!!!!!" + ], + "y": [ + 0, + 10, + 20, + 30, + 40, + 50, + 60 + ] + } + ], + "layout": { + "xaxis": { + "title": { + "text": "Top X Axis", + "font": {"size": 24} + }, + "rangeslider": { + "visible": true + }, + "side": "top", + "automargin": true + }, + "width": 400, + "height": 400 + } +} diff --git a/test/jasmine/tests/range_slider_test.js b/test/jasmine/tests/range_slider_test.js index a6246a251f4..f71ce51a7c7 100644 --- a/test/jasmine/tests/range_slider_test.js +++ b/test/jasmine/tests/range_slider_test.js @@ -352,6 +352,51 @@ describe('Visible rangesliders', function() { .catch(failTest) .then(done); }); + + it('should automargin correctly with a top or bottom x axis', function(done) { + var topMock = require('@mocks/range_slider_top_axis'); + + function assertTop(hasExtra) { + var op = hasExtra ? 'toBeGreaterThan' : 'toBeLessThan'; + expect(gd._fullLayout._size.t)[op](102); + expect(gd._fullLayout._size.b).toBeWithin(128, 5); + } + + function assertBottom(val) { + expect(gd._fullLayout._size.t).toBe(100); + expect(gd._fullLayout._size.b).toBeWithin(val, 10); + } + + Plotly.plot(gd, topMock) + .then(function() { + assertTop(true); + return Plotly.relayout(gd, 'xaxis.range', [-0.5, 1.5]); + }) + .then(function() { + assertTop(false); + return Plotly.relayout(gd, 'xaxis.range', [-0.5, 6.5]); + }) + .then(function() { + assertTop(true); + // rangeslider automargins even without automargin turned on + // axis.automargin only affects automargin directly from labels, + // not when the rangeslider is pushed down by labels. + return Plotly.relayout(gd, {'xaxis.side': 'bottom', 'xaxis.automargin': false}); + }) + .then(function() { + assertBottom(210); + return Plotly.relayout(gd, 'xaxis.range', [-0.5, 1.5]); + }) + .then(function() { + assertBottom(145); + return Plotly.relayout(gd, 'xaxis.range', [-0.5, 6.5]); + }) + .then(function() { + assertBottom(210); + }) + .catch(failTest) + .then(done); + }); }); describe('Rangeslider visibility property', function() {