Skip to content

Commit cebc31c

Browse files
committed
- add 'rangeslider.autorange' attribute - and rm _needsExpand flag - add range slider calcAutorange handler to compute range slider auto range during the calc step
1 parent 0e931d6 commit cebc31c

File tree

8 files changed

+123
-96
lines changed

8 files changed

+123
-96
lines changed

src/components/rangeslider/attributes.js

+10
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,16 @@ module.exports = {
3030
role: 'style',
3131
description: 'Sets the border color of the range slider.'
3232
},
33+
autorange: {
34+
valType: 'boolean',
35+
dflt: true,
36+
role: 'style',
37+
description: [
38+
'Determines whether or not the range slider range is',
39+
'computed in relation to the input data.',
40+
'If `range` is provided, then `autorange` is set to *false*.'
41+
].join(' ')
42+
},
3343
range: {
3444
valType: 'info_array',
3545
role: 'info',
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/**
2+
* Copyright 2012-2017, Plotly, Inc.
3+
* All rights reserved.
4+
*
5+
* This source code is licensed under the MIT license found in the
6+
* LICENSE file in the root directory of this source tree.
7+
*/
8+
9+
'use strict';
10+
11+
var Axes = require('../../plots/cartesian/axes');
12+
var constants = require('./constants');
13+
14+
module.exports = function calcAutorange(gd) {
15+
var axes = Axes.list(gd, 'x', true);
16+
17+
// Compute new slider range using axis autorange if necessary.
18+
//
19+
// Copy back range to input range slider container to skip
20+
// this step in subsequent draw calls.
21+
22+
for(var i = 0; i < axes.length; i++) {
23+
var ax = axes[i],
24+
opts = ax[constants.name];
25+
26+
// Don't try calling getAutoRange if _min and _max are filled in.
27+
// This happens on updates where the calc step is skipped.
28+
29+
if(opts && opts.visible && opts.autorange && ax._min.length && ax._max.length) {
30+
opts._input.autorange = true;
31+
opts._input.range = opts.range = Axes.getAutoRange(ax);
32+
}
33+
}
34+
};

src/components/rangeslider/defaults.js

+12-4
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88

99
'use strict';
1010

11+
var isNumeric = require('fast-isnumeric');
12+
1113
var Lib = require('../../lib');
1214
var attributes = require('./attributes');
1315

@@ -32,21 +34,27 @@ module.exports = function handleDefaults(layoutIn, layoutOut, axName) {
3234
coerce('bordercolor');
3335
coerce('borderwidth');
3436
coerce('thickness');
37+
38+
coerce('autorange', !(
39+
(containerIn.range || []).length === 2 &&
40+
isNumeric(axOut.r2l(containerIn.range[0])) &&
41+
isNumeric(axOut.r2l(containerIn.range[1]))
42+
));
3543
coerce('visible');
3644
coerce('range');
3745

3846
// Expand slider range to the axis range
39-
if(containerOut.range && !axOut.autorange) {
40-
// TODO: what if the ranges are reversed?
47+
// TODO: what if the ranges are reversed?
48+
if(containerOut.range) {
4149
var outRange = containerOut.range,
4250
axRange = axOut.range;
4351

4452
outRange[0] = axOut.l2r(Math.min(axOut.r2l(outRange[0]), axOut.r2l(axRange[0])));
4553
outRange[1] = axOut.l2r(Math.max(axOut.r2l(outRange[1]), axOut.r2l(axRange[1])));
46-
} else {
47-
axOut._needsExpand = true;
4854
}
4955

56+
axOut.cleanRange('rangeslider.range');
57+
5058
// to map back range slider (auto) range
5159
containerOut._input = containerIn;
5260
};

src/components/rangeslider/draw.js

-7
Original file line numberDiff line numberDiff line change
@@ -79,13 +79,6 @@ module.exports = function(gd) {
7979
var rangeSlider = d3.select(this),
8080
opts = axisOpts[constants.name];
8181

82-
// compute new slider range using axis autorange if necessary
83-
// copy back range to input range slider container to skip
84-
// this step in subsequent draw calls
85-
if(!opts.range) {
86-
opts._input.range = opts.range = Axes.getAutoRange(axisOpts);
87-
}
88-
8982
// update range slider dimensions
9083

9184
var margin = fullLayout.margin,

src/components/rangeslider/index.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,6 @@ module.exports = {
2020

2121
layoutAttributes: require('./attributes'),
2222
handleDefaults: require('./defaults'),
23-
23+
calcAutorange: require('./calc_autorange'),
2424
draw: require('./draw')
2525
};

src/plot_api/plot_api.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,6 @@ Plotly.plot = function(gd, data, layout, config) {
189189
}
190190

191191
// draw anything that can affect margins.
192-
// currently this is legend and colorbars
193192
function marginPushers() {
194193
var calcdata = gd.calcdata;
195194
var i, cd, trace;
@@ -253,7 +252,8 @@ Plotly.plot = function(gd, data, layout, config) {
253252
return Lib.syncOrAsync([
254253
Registry.getComponentMethod('shapes', 'calcAutorange'),
255254
Registry.getComponentMethod('annotations', 'calcAutorange'),
256-
doAutoRange
255+
doAutoRange,
256+
Registry.getComponentMethod('rangeslider', 'calcAutorange')
257257
], gd);
258258
}
259259

src/plots/cartesian/axes.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -378,7 +378,9 @@ axes.saveRangeInitial = function(gd, overwrite) {
378378
// tozero: (boolean) make sure to include zero if axis is linear,
379379
// and make it a tight bound if possible
380380
axes.expand = function(ax, data, options) {
381-
if(!(ax.autorange || ax._needsExpand) || !data) return;
381+
var needsAutorange = (ax.autorange || Lib.nestedProperty(ax, 'rangeslider.autorange'));
382+
if(!needsAutorange || !data) return;
383+
382384
if(!ax._min) ax._min = [];
383385
if(!ax._max) ax._max = [];
384386
if(!options) options = {};

test/jasmine/tests/range_slider_test.js

+61-81
Original file line numberDiff line numberDiff line change
@@ -336,13 +336,17 @@ describe('the range slider', function() {
336336

337337
describe('handleDefaults function', function() {
338338

339+
function _supply(layoutIn, layoutOut, axName) {
340+
setConvert(layoutOut[axName]);
341+
RangeSlider.handleDefaults(layoutIn, layoutOut, axName);
342+
}
343+
339344
it('should not coerce anything if rangeslider isn\'t set', function() {
340345
var layoutIn = { xaxis: {} },
341346
layoutOut = { xaxis: {} },
342347
expected = { xaxis: {} };
343348

344-
RangeSlider.handleDefaults(layoutIn, layoutOut, 'xaxis');
345-
349+
_supply(layoutIn, layoutOut, 'xaxis');
346350
expect(layoutIn).toEqual(expected);
347351
});
348352

@@ -351,53 +355,45 @@ describe('the range slider', function() {
351355
layoutOut = { xaxis: { rangeslider: {}} },
352356
expected = { xaxis: { rangeslider: { visible: true }} };
353357

354-
RangeSlider.handleDefaults(layoutIn, layoutOut, 'xaxis');
355-
358+
_supply(layoutIn, layoutOut, 'xaxis');
356359
expect(layoutIn).toEqual(expected);
357360
});
358361

359362
it('should set defaults if rangeslider is set to anything truthy', function() {
360363
var layoutIn = { xaxis: { rangeslider: {} }},
361364
layoutOut = { xaxis: {} },
362365
expected = {
363-
xaxis: {
364-
rangeslider: {
365-
visible: true,
366-
thickness: 0.15,
367-
bgcolor: '#fff',
368-
borderwidth: 0,
369-
bordercolor: '#444',
370-
_input: layoutIn.xaxis.rangeslider
371-
},
372-
_needsExpand: true
373-
}
366+
visible: true,
367+
autorange: true,
368+
range: [-1, 6],
369+
thickness: 0.15,
370+
bgcolor: '#fff',
371+
borderwidth: 0,
372+
bordercolor: '#444',
373+
_input: layoutIn.xaxis.rangeslider
374374
};
375375

376-
RangeSlider.handleDefaults(layoutIn, layoutOut, 'xaxis');
377-
378-
expect(layoutOut).toEqual(expected);
376+
_supply(layoutIn, layoutOut, 'xaxis');
377+
expect(layoutOut.xaxis.rangeslider).toEqual(expected);
379378
});
380379

381380
it('should set defaults if rangeslider.visible is true', function() {
382381
var layoutIn = { xaxis: { rangeslider: { visible: true }} },
383382
layoutOut = { xaxis: { rangeslider: {}} },
384383
expected = {
385-
xaxis: {
386-
rangeslider: {
387-
visible: true,
388-
thickness: 0.15,
389-
bgcolor: '#fff',
390-
borderwidth: 0,
391-
bordercolor: '#444',
392-
_input: layoutIn.xaxis.rangeslider
393-
},
394-
_needsExpand: true
395-
}
384+
visible: true,
385+
autorange: true,
386+
range: [-1, 6],
387+
thickness: 0.15,
388+
bgcolor: '#fff',
389+
borderwidth: 0,
390+
bordercolor: '#444',
391+
_input: layoutIn.xaxis.rangeslider
396392
};
397393

398-
RangeSlider.handleDefaults(layoutIn, layoutOut, 'xaxis');
394+
_supply(layoutIn, layoutOut, 'xaxis');
395+
expect(layoutOut.xaxis.rangeslider).toEqual(expected);
399396

400-
expect(layoutOut).toEqual(expected);
401397
});
402398

403399
it('should set defaults if properties are invalid', function() {
@@ -410,72 +406,57 @@ describe('the range slider', function() {
410406
}}},
411407
layoutOut = { xaxis: {} },
412408
expected = {
413-
xaxis: {
414-
rangeslider: {
415-
visible: true,
416-
thickness: 0.15,
417-
bgcolor: '#fff',
418-
borderwidth: 0,
419-
bordercolor: '#444',
420-
_input: layoutIn.xaxis.rangeslider
421-
},
422-
_needsExpand: true
423-
}
409+
visible: true,
410+
autorange: true,
411+
range: [-1, 6],
412+
thickness: 0.15,
413+
bgcolor: '#fff',
414+
borderwidth: 0,
415+
bordercolor: '#444',
416+
_input: layoutIn.xaxis.rangeslider
424417
};
425418

426-
RangeSlider.handleDefaults(layoutIn, layoutOut, 'xaxis');
427-
428-
expect(layoutOut).toEqual(expected);
419+
_supply(layoutIn, layoutOut, 'xaxis');
420+
expect(layoutOut.xaxis.rangeslider).toEqual(expected);
429421
});
430422

431423
it('should expand the rangeslider range to axis range', function() {
432424
var layoutIn = { xaxis: { rangeslider: { range: [5, 6] } } },
433425
layoutOut = { xaxis: { range: [1, 10], type: 'linear'} },
434426
expected = {
435-
xaxis: {
436-
rangeslider: {
437-
visible: true,
438-
thickness: 0.15,
439-
bgcolor: '#fff',
440-
borderwidth: 0,
441-
bordercolor: '#444',
442-
range: [1, 10],
443-
_input: layoutIn.xaxis.rangeslider
444-
},
445-
range: [1, 10]
446-
}
427+
visible: true,
428+
autorange: false,
429+
range: [1, 10],
430+
thickness: 0.15,
431+
bgcolor: '#fff',
432+
borderwidth: 0,
433+
bordercolor: '#444',
434+
_input: layoutIn.xaxis.rangeslider
447435
};
448436

449-
setConvert(layoutOut.xaxis);
450-
451-
RangeSlider.handleDefaults(layoutIn, layoutOut, 'xaxis');
437+
_supply(layoutIn, layoutOut, 'xaxis');
452438

453439
// don't compare the whole layout, because we had to run setConvert which
454440
// attaches all sorts of other stuff to xaxis
455-
expect(layoutOut.xaxis.rangeslider).toEqual(expected.xaxis.rangeslider);
441+
expect(layoutOut.xaxis.rangeslider).toEqual(expected);
456442
});
457443

458-
it('should set _needsExpand when an axis range is set', function() {
459-
var layoutIn = { xaxis: { rangeslider: true } },
460-
layoutOut = { xaxis: { range: [2, 40]} },
444+
it('should set autorange to true when range input is invalid', function() {
445+
var layoutIn = { xaxis: { rangeslider: { range: 'not-gonna-work'}} },
446+
layoutOut = { xaxis: {} },
461447
expected = {
462-
xaxis: {
463-
rangeslider: {
464-
visible: true,
465-
thickness: 0.15,
466-
bgcolor: '#fff',
467-
borderwidth: 0,
468-
bordercolor: '#444',
469-
_input: {}
470-
},
471-
range: [2, 40],
472-
_needsExpand: true
473-
},
448+
visible: true,
449+
autorange: true,
450+
range: [-1, 6],
451+
thickness: 0.15,
452+
bgcolor: '#fff',
453+
borderwidth: 0,
454+
bordercolor: '#444',
455+
_input: layoutIn.xaxis.rangeslider
474456
};
475457

476-
RangeSlider.handleDefaults(layoutIn, layoutOut, 'xaxis');
477-
478-
expect(layoutOut).toEqual(expected);
458+
_supply(layoutIn, layoutOut, 'xaxis');
459+
expect(layoutOut.xaxis.rangeslider).toEqual(expected);
479460
});
480461

481462
it('should default \'bgcolor\' to layout \'plot_bgcolor\'', function() {
@@ -488,8 +469,7 @@ describe('the range slider', function() {
488469
plot_bgcolor: 'blue'
489470
};
490471

491-
RangeSlider.handleDefaults(layoutIn, layoutOut, 'xaxis');
492-
472+
_supply(layoutIn, layoutOut, 'xaxis');
493473
expect(layoutOut.xaxis.rangeslider.bgcolor).toEqual('blue');
494474
});
495475
});

0 commit comments

Comments
 (0)