Skip to content

Commit 939df6e

Browse files
authored
Merge pull request #3323 from plotly/clean-defaults-mc
Clean up automargin pipeline a bit
2 parents a25c5e3 + f55e769 commit 939df6e

19 files changed

+342
-203
lines changed

src/components/legend/defaults.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ module.exports = function legendDefaults(layoutIn, layoutOut, fullData) {
8686
coerce('orientation');
8787
if(containerOut.orientation === 'h') {
8888
var xaxis = layoutIn.xaxis;
89-
if(xaxis && xaxis.rangeslider && xaxis.rangeslider.visible) {
89+
if(Registry.getComponentMethod('rangeslider', 'isVisible')(xaxis)) {
9090
defaultX = 0;
9191
defaultXAnchor = 'left';
9292
defaultY = 1.1;

src/components/rangeslider/draw.js

+25-53
Original file line numberDiff line numberDiff line change
@@ -19,16 +19,21 @@ var Color = require('../color');
1919
var Titles = require('../titles');
2020

2121
var Cartesian = require('../../plots/cartesian');
22-
var Axes = require('../../plots/cartesian/axes');
22+
var axisIDs = require('../../plots/cartesian/axis_ids');
2323

2424
var dragElement = require('../dragelement');
2525
var setCursor = require('../../lib/setcursor');
2626

2727
var constants = require('./constants');
2828

2929
module.exports = function(gd) {
30-
var fullLayout = gd._fullLayout,
31-
rangeSliderData = makeRangeSliderData(fullLayout);
30+
var fullLayout = gd._fullLayout;
31+
var rangeSliderData = fullLayout._rangeSliderData;
32+
for(var i = 0; i < rangeSliderData.length; i++) {
33+
var opts = rangeSliderData[i][constants.name];
34+
// fullLayout._uid may not exist when we call makeData
35+
opts._clipId = opts._id + '-' + fullLayout._uid;
36+
}
3237

3338
/*
3439
* <g container />
@@ -55,10 +60,6 @@ module.exports = function(gd) {
5560
.selectAll('g.' + constants.containerClassName)
5661
.data(rangeSliderData, keyFunction);
5762

58-
rangeSliders.enter().append('g')
59-
.classed(constants.containerClassName, true)
60-
.attr('pointer-events', 'all');
61-
6263
// remove exiting sliders and their corresponding clip paths
6364
rangeSliders.exit().each(function(axisOpts) {
6465
var opts = axisOpts[constants.name];
@@ -68,12 +69,16 @@ module.exports = function(gd) {
6869
// return early if no range slider is visible
6970
if(rangeSliderData.length === 0) return;
7071

72+
rangeSliders.enter().append('g')
73+
.classed(constants.containerClassName, true)
74+
.attr('pointer-events', 'all');
75+
7176
// for all present range sliders
7277
rangeSliders.each(function(axisOpts) {
73-
var rangeSlider = d3.select(this),
74-
opts = axisOpts[constants.name],
75-
oppAxisOpts = fullLayout[Axes.id2name(axisOpts.anchor)],
76-
oppAxisRangeOpts = opts[Axes.id2name(axisOpts.anchor)];
78+
var rangeSlider = d3.select(this);
79+
var opts = axisOpts[constants.name];
80+
var oppAxisOpts = fullLayout[axisIDs.id2name(axisOpts.anchor)];
81+
var oppAxisRangeOpts = opts[axisIDs.id2name(axisOpts.anchor)];
7782

7883
// update range
7984
// Expand slider range to the axis range
@@ -97,19 +102,9 @@ module.exports = function(gd) {
97102
var domain = axisOpts.domain;
98103
var tickHeight = (axisOpts._boundingBox || {}).height || 0;
99104

100-
var oppBottom = Infinity;
101-
var subplotData = Axes.getSubplots(gd, axisOpts);
102-
for(var i = 0; i < subplotData.length; i++) {
103-
var oppAxis = Axes.getFromId(gd, subplotData[i].substr(subplotData[i].indexOf('y')));
104-
oppBottom = Math.min(oppBottom, oppAxis.domain[0]);
105-
}
106-
107-
opts._id = constants.name + axisOpts._id;
108-
opts._clipId = opts._id + '-' + fullLayout._uid;
105+
var oppBottom = opts._oppBottom;
109106

110107
opts._width = graphSize.w * (domain[1] - domain[0]);
111-
opts._height = (fullLayout.height - margin.b - margin.t) * opts.thickness;
112-
opts._offsetShift = Math.floor(opts.borderwidth / 2);
113108

114109
var x = Math.round(margin.l + (graphSize.w * domain[0]));
115110

@@ -177,36 +172,9 @@ module.exports = function(gd) {
177172
}
178173
});
179174
}
180-
181-
// update margins
182-
Plots.autoMargin(gd, opts._id, {
183-
x: domain[0],
184-
y: oppBottom,
185-
l: 0,
186-
r: 0,
187-
t: 0,
188-
b: opts._height + margin.b + tickHeight,
189-
pad: constants.extraPad + opts._offsetShift * 2
190-
});
191175
});
192176
};
193177

194-
function makeRangeSliderData(fullLayout) {
195-
var axes = Axes.list({ _fullLayout: fullLayout }, 'x', true),
196-
name = constants.name,
197-
out = [];
198-
199-
if(fullLayout._has('gl2d')) return out;
200-
201-
for(var i = 0; i < axes.length; i++) {
202-
var ax = axes[i];
203-
204-
if(ax[name] && ax[name].visible) out.push(ax);
205-
}
206-
207-
return out;
208-
}
209-
210178
function setupDragElement(rangeSlider, gd, axisOpts, opts) {
211179
var slideBox = rangeSlider.select('rect.' + constants.slideBoxClassName).node(),
212180
grabAreaMin = rangeSlider.select('rect.' + constants.grabAreaMinClassName).node(),
@@ -393,11 +361,10 @@ function addClipPath(rangeSlider, gd, axisOpts, opts) {
393361
}
394362

395363
function drawRangePlot(rangeSlider, gd, axisOpts, opts) {
396-
var subplotData = Axes.getSubplots(gd, axisOpts),
397-
calcData = gd.calcdata;
364+
var calcData = gd.calcdata;
398365

399366
var rangePlots = rangeSlider.selectAll('g.' + constants.rangePlotClassName)
400-
.data(subplotData, Lib.identity);
367+
.data(axisOpts._subplotsWith, Lib.identity);
401368

402369
rangePlots.enter().append('g')
403370
.attr('class', function(id) { return constants.rangePlotClassName + ' ' + id; })
@@ -413,7 +380,7 @@ function drawRangePlot(rangeSlider, gd, axisOpts, opts) {
413380
var plotgroup = d3.select(this),
414381
isMainPlot = (i === 0);
415382

416-
var oppAxisOpts = Axes.getFromId(gd, id, 'y'),
383+
var oppAxisOpts = axisIDs.getFromId(gd, id, 'y'),
417384
oppAxisName = oppAxisOpts._name,
418385
oppAxisRangeOpts = opts[oppAxisName];
419386

@@ -445,6 +412,11 @@ function drawRangePlot(rangeSlider, gd, axisOpts, opts) {
445412
var xa = mockFigure._fullLayout.xaxis;
446413
var ya = mockFigure._fullLayout[oppAxisName];
447414

415+
xa.clearCalc();
416+
xa.setScale();
417+
ya.clearCalc();
418+
ya.setScale();
419+
448420
var plotinfo = {
449421
id: id,
450422
plotgroup: plotgroup,

src/components/rangeslider/helpers.js

+67
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
/**
2+
* Copyright 2012-2018, 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 axisIDs = require('../../plots/cartesian/axis_ids');
12+
var constants = require('./constants');
13+
var name = constants.name;
14+
15+
function isVisible(ax) {
16+
var rangeSlider = ax && ax[name];
17+
return rangeSlider && rangeSlider.visible;
18+
}
19+
exports.isVisible = isVisible;
20+
21+
exports.makeData = function(fullLayout) {
22+
var axes = axisIDs.list({ _fullLayout: fullLayout }, 'x', true);
23+
var margin = fullLayout.margin;
24+
var rangeSliderData = [];
25+
26+
if(!fullLayout._has('gl2d')) {
27+
for(var i = 0; i < axes.length; i++) {
28+
var ax = axes[i];
29+
30+
if(isVisible(ax)) {
31+
rangeSliderData.push(ax);
32+
33+
var opts = ax[name];
34+
opts._id = name + ax._id;
35+
opts._height = (fullLayout.height - margin.b - margin.t) * opts.thickness;
36+
opts._offsetShift = Math.floor(opts.borderwidth / 2);
37+
}
38+
}
39+
}
40+
41+
fullLayout._rangeSliderData = rangeSliderData;
42+
};
43+
44+
exports.autoMarginOpts = function(gd, ax) {
45+
var opts = ax[name];
46+
47+
var oppBottom = Infinity;
48+
var counterAxes = ax._counterAxes;
49+
for(var j = 0; j < counterAxes.length; j++) {
50+
var counterId = counterAxes[j];
51+
var oppAxis = axisIDs.getFromId(gd, counterId);
52+
oppBottom = Math.min(oppBottom, oppAxis.domain[0]);
53+
}
54+
opts._oppBottom = oppBottom;
55+
56+
var tickHeight = (ax.side === 'bottom' && ax._boundingBox.height) || 0;
57+
58+
return {
59+
x: 0,
60+
y: oppBottom,
61+
l: 0,
62+
r: 0,
63+
t: 0,
64+
b: opts._height + gd._fullLayout.margin.b + tickHeight,
65+
pad: constants.extraPad + opts._offsetShift * 2
66+
};
67+
};

src/components/rangeslider/index.js

+5-1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
var Lib = require('../../lib');
1212
var attrs = require('./attributes');
1313
var oppAxisAttrs = require('./oppaxis_attributes');
14+
var helpers = require('./helpers');
1415

1516
module.exports = {
1617
moduleType: 'component',
@@ -29,5 +30,8 @@ module.exports = {
2930
layoutAttributes: require('./attributes'),
3031
handleDefaults: require('./defaults'),
3132
calcAutorange: require('./calc_autorange'),
32-
draw: require('./draw')
33+
draw: require('./draw'),
34+
isVisible: helpers.isVisible,
35+
makeData: helpers.makeData,
36+
autoMarginOpts: helpers.autoMarginOpts
3337
};

src/plot_api/plot_api.js

+6-2
Original file line numberDiff line numberDiff line change
@@ -332,8 +332,7 @@ exports.plot = function(gd, data, layout, config) {
332332
return Lib.syncOrAsync([
333333
Registry.getComponentMethod('shapes', 'calcAutorange'),
334334
Registry.getComponentMethod('annotations', 'calcAutorange'),
335-
doAutoRangeAndConstraints,
336-
Registry.getComponentMethod('rangeslider', 'calcAutorange')
335+
doAutoRangeAndConstraints
337336
], gd);
338337
}
339338

@@ -345,6 +344,11 @@ exports.plot = function(gd, data, layout, config) {
345344
// store initial ranges *after* enforcing constraints, otherwise
346345
// we will never look like we're at the initial ranges
347346
if(graphWasEmpty) Axes.saveRangeInitial(gd);
347+
348+
// this one is different from shapes/annotations calcAutorange
349+
// the others incorporate those components into ax._extremes,
350+
// this one actually sets the ranges in rangesliders.
351+
Registry.getComponentMethod('rangeslider', 'calcAutorange')(gd);
348352
}
349353

350354
// draw ticks, titles, and calculate axis scaling (._b, ._m)

src/plot_api/subroutines.js

+4-52
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ function lsInner(gd) {
5555
var gs = fullLayout._size;
5656
var pad = gs.p;
5757
var axList = Axes.list(gd, '', true);
58-
var i, subplot, plotinfo, xa, ya;
58+
var i, subplot, plotinfo, ax, xa, ya;
5959

6060
fullLayout._paperdiv.style({
6161
width: (gd._context.responsive && fullLayout.autosize && !gd._context._hasZeroWidth && !gd.layout.width) ? '100%' : fullLayout.width + 'px',
@@ -91,10 +91,7 @@ function lsInner(gd) {
9191

9292
// some preparation of axis position info
9393
for(i = 0; i < axList.length; i++) {
94-
var ax = axList[i];
95-
96-
// reset scale in case the margins have changed
97-
ax.setScale();
94+
ax = axList[i];
9895

9996
var counterAx = ax._anchorAxis;
10097

@@ -113,11 +110,6 @@ function lsInner(gd) {
113110
ax._mainMirrorPosition = (ax.mirror && counterAx) ?
114111
getLinePosition(ax, counterAx,
115112
alignmentConstants.OPPOSITE_SIDE[ax.side]) : null;
116-
117-
// Figure out which subplot to draw ticks, labels, & axis lines on
118-
// do this as a separate loop so we already have all the
119-
// _mainAxis and _anchorAxis links set
120-
ax._mainSubplot = findMainSubplot(ax, fullLayout);
121113
}
122114

123115
// figure out which backgrounds we need to draw,
@@ -358,48 +350,6 @@ function lsInner(gd) {
358350
return gd._promises.length && Promise.all(gd._promises);
359351
}
360352

361-
function findMainSubplot(ax, fullLayout) {
362-
var subplotList = fullLayout._subplots;
363-
var ids = subplotList.cartesian.concat(subplotList.gl2d || []);
364-
var mockGd = {_fullLayout: fullLayout};
365-
366-
var isX = ax._id.charAt(0) === 'x';
367-
var anchorAx = ax._mainAxis._anchorAxis;
368-
var mainSubplotID = '';
369-
var nextBestMainSubplotID = '';
370-
var anchorID = '';
371-
372-
// First try the main ID with the anchor
373-
if(anchorAx) {
374-
anchorID = anchorAx._mainAxis._id;
375-
mainSubplotID = isX ? (ax._id + anchorID) : (anchorID + ax._id);
376-
}
377-
378-
// Then look for a subplot with the counteraxis overlaying the anchor
379-
// If that fails just use the first subplot including this axis
380-
if(!mainSubplotID || !fullLayout._plots[mainSubplotID]) {
381-
mainSubplotID = '';
382-
383-
for(var j = 0; j < ids.length; j++) {
384-
var id = ids[j];
385-
var yIndex = id.indexOf('y');
386-
var idPart = isX ? id.substr(0, yIndex) : id.substr(yIndex);
387-
var counterPart = isX ? id.substr(yIndex) : id.substr(0, yIndex);
388-
389-
if(idPart === ax._id) {
390-
if(!nextBestMainSubplotID) nextBestMainSubplotID = id;
391-
var counterAx = Axes.getFromId(mockGd, counterPart);
392-
if(anchorID && counterAx.overlaying === anchorID) {
393-
mainSubplotID = id;
394-
break;
395-
}
396-
}
397-
}
398-
}
399-
400-
return mainSubplotID || nextBestMainSubplotID;
401-
}
402-
403353
function shouldShowLinesOrTicks(ax, subplot) {
404354
return (ax.ticks || ax.showline) &&
405355
(subplot === ax._mainSubplot || ax.mirror === 'all' || ax.mirror === 'allticks');
@@ -752,6 +702,8 @@ exports.doAutoRangeAndConstraints = function(gd) {
752702
for(var i = 0; i < axList.length; i++) {
753703
var ax = axList[i];
754704
cleanAxisConstraints(gd, ax);
705+
// in case margins changed, update scale
706+
ax.setScale();
755707
doAutoRange(gd, ax);
756708
}
757709

src/plots/cartesian/autorange.js

+6-9
Original file line numberDiff line numberDiff line change
@@ -237,10 +237,6 @@ function concatExtremes(gd, ax) {
237237
}
238238

239239
function doAutoRange(gd, ax) {
240-
if(!ax._length) ax.setScale();
241-
242-
var axIn;
243-
244240
if(ax.autorange) {
245241
ax.range = getAutoRange(gd, ax);
246242

@@ -250,7 +246,7 @@ function doAutoRange(gd, ax) {
250246
// doAutoRange will get called on fullLayout,
251247
// but we want to report its results back to layout
252248

253-
axIn = ax._input;
249+
var axIn = ax._input;
254250

255251
// before we edit _input, store preGUI values
256252
var edits = {};
@@ -262,15 +258,16 @@ function doAutoRange(gd, ax) {
262258
axIn.autorange = ax.autorange;
263259
}
264260

265-
if(ax._anchorAxis && ax._anchorAxis.rangeslider) {
266-
var axeRangeOpts = ax._anchorAxis.rangeslider[ax._name];
261+
var anchorAx = ax._anchorAxis;
262+
263+
if(anchorAx && anchorAx.rangeslider) {
264+
var axeRangeOpts = anchorAx.rangeslider[ax._name];
267265
if(axeRangeOpts) {
268266
if(axeRangeOpts.rangemode === 'auto') {
269267
axeRangeOpts.range = getAutoRange(gd, ax);
270268
}
271269
}
272-
axIn = ax._anchorAxis._input;
273-
axIn.rangeslider[ax._name] = Lib.extendFlat({}, axeRangeOpts);
270+
anchorAx._input.rangeslider[ax._name] = Lib.extendFlat({}, axeRangeOpts);
274271
}
275272
}
276273

0 commit comments

Comments
 (0)