Skip to content

Commit e9a89c2

Browse files
committed
split out axis type defaults and calculate before anything else
1 parent 8782089 commit e9a89c2

File tree

7 files changed

+161
-121
lines changed

7 files changed

+161
-121
lines changed

src/components/colorbar/draw.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,10 @@ module.exports = function draw(gd, id) {
170170
anchor: 'free',
171171
position: 1
172172
},
173-
cbAxisOut = {},
173+
cbAxisOut = {
174+
type: 'linear',
175+
_id: 'y' + id
176+
},
174177
axisOptions = {
175178
letter: 'y',
176179
font: fullLayout.font,
@@ -188,8 +191,6 @@ module.exports = function draw(gd, id) {
188191
handleAxisDefaults(cbAxisIn, cbAxisOut, coerce, axisOptions, fullLayout);
189192
handleAxisPositionDefaults(cbAxisIn, cbAxisOut, coerce, axisOptions);
190193

191-
cbAxisOut._id = 'y' + id;
192-
193194
// position can't go in through supplyDefaults
194195
// because that restricts it to [0,1]
195196
cbAxisOut.position = opts.x + xpadFrac + thickFrac;

src/plots/cartesian/axis_defaults.js

Lines changed: 2 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -22,21 +22,18 @@ var handleTickLabelDefaults = require('./tick_label_defaults');
2222
var handleCategoryOrderDefaults = require('./category_order_defaults');
2323
var setConvert = require('./set_convert');
2424
var orderedCategories = require('./ordered_categories');
25-
var axisIds = require('./axis_ids');
26-
var autoType = require('./axis_autotype');
2725

2826

2927
/**
3028
* options: object containing:
3129
*
3230
* letter: 'x' or 'y'
3331
* title: name of the axis (ie 'Colorbar') to go in default title
34-
* name: axis object name (ie 'xaxis') if one should be stored
3532
* font: the default font to inherit
3633
* outerTicks: boolean, should ticks default to outside?
3734
* showGrid: boolean, should gridlines be shown by default?
3835
* noHover: boolean, this axis doesn't support hover effects?
39-
* data: the plot data to use in choosing auto type
36+
* data: the plot data, used to manage categories
4037
* bgColor: the plot background color, to calculate default gridline colors
4138
*/
4239
module.exports = function handleAxisDefaults(containerIn, containerOut, coerce, options, layoutOut) {
@@ -50,28 +47,7 @@ module.exports = function handleAxisDefaults(containerIn, containerOut, coerce,
5047
return Lib.coerce2(containerIn, containerOut, layoutAttributes, attr, dflt);
5148
}
5249

53-
// set up some private properties
54-
if(options.name) {
55-
containerOut._name = options.name;
56-
containerOut._id = axisIds.name2id(options.name);
57-
}
58-
59-
// now figure out type and do some more initialization
60-
var axType = coerce('type');
61-
if(axType === '-') {
62-
setAutoType(containerOut, options.data);
63-
64-
if(containerOut.type === '-') {
65-
containerOut.type = 'linear';
66-
}
67-
else {
68-
// copy autoType back to input axis
69-
// note that if this object didn't exist
70-
// in the input layout, we have to put it in
71-
// this happens in the main supplyDefaults function
72-
axType = containerIn.type = containerOut.type;
73-
}
74-
}
50+
var axType = containerOut.type;
7551

7652
if(axType === 'date') {
7753
var handleCalendarDefaults = Registry.getComponentMethod('calendars', 'handleDefaults');
@@ -140,87 +116,3 @@ module.exports = function handleAxisDefaults(containerIn, containerOut, coerce,
140116

141117
return containerOut;
142118
};
143-
144-
function setAutoType(ax, data) {
145-
// new logic: let people specify any type they want,
146-
// only autotype if type is '-'
147-
if(ax.type !== '-') return;
148-
149-
var id = ax._id,
150-
axLetter = id.charAt(0);
151-
152-
// support 3d
153-
if(id.indexOf('scene') !== -1) id = axLetter;
154-
155-
var d0 = getFirstNonEmptyTrace(data, id, axLetter);
156-
if(!d0) return;
157-
158-
// first check for histograms, as the count direction
159-
// should always default to a linear axis
160-
if(d0.type === 'histogram' &&
161-
axLetter === {v: 'y', h: 'x'}[d0.orientation || 'v']) {
162-
ax.type = 'linear';
163-
return;
164-
}
165-
166-
var calAttr = axLetter + 'calendar',
167-
calendar = d0[calAttr];
168-
169-
// check all boxes on this x axis to see
170-
// if they're dates, numbers, or categories
171-
if(isBoxWithoutPositionCoords(d0, axLetter)) {
172-
var posLetter = getBoxPosLetter(d0),
173-
boxPositions = [],
174-
trace;
175-
176-
for(var i = 0; i < data.length; i++) {
177-
trace = data[i];
178-
if(!Registry.traceIs(trace, 'box') ||
179-
(trace[axLetter + 'axis'] || axLetter) !== id) continue;
180-
181-
if(trace[posLetter] !== undefined) boxPositions.push(trace[posLetter][0]);
182-
else if(trace.name !== undefined) boxPositions.push(trace.name);
183-
else boxPositions.push('text');
184-
185-
if(trace[calAttr] !== calendar) calendar = undefined;
186-
}
187-
188-
ax.type = autoType(boxPositions, calendar);
189-
}
190-
else {
191-
ax.type = autoType(d0[axLetter] || [d0[axLetter + '0']], calendar);
192-
}
193-
}
194-
195-
function getBoxPosLetter(trace) {
196-
return {v: 'x', h: 'y'}[trace.orientation || 'v'];
197-
}
198-
199-
function isBoxWithoutPositionCoords(trace, axLetter) {
200-
var posLetter = getBoxPosLetter(trace),
201-
isBox = Registry.traceIs(trace, 'box'),
202-
isCandlestick = Registry.traceIs(trace._fullInput || {}, 'candlestick');
203-
204-
return (
205-
isBox &&
206-
!isCandlestick &&
207-
axLetter === posLetter &&
208-
trace[posLetter] === undefined &&
209-
trace[posLetter + '0'] === undefined
210-
);
211-
}
212-
213-
function getFirstNonEmptyTrace(data, id, axLetter) {
214-
for(var i = 0; i < data.length; i++) {
215-
var trace = data[i];
216-
217-
if((trace[axLetter + 'axis'] || axLetter) === id) {
218-
if(isBoxWithoutPositionCoords(trace, axLetter)) {
219-
return trace;
220-
}
221-
else if((trace[axLetter] || []).length || trace[axLetter + '0']) {
222-
return trace;
223-
}
224-
}
225-
}
226-
}

src/plots/cartesian/layout_defaults.js

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ var basePlotLayoutAttributes = require('../layout_attributes');
1616

1717
var constants = require('./constants');
1818
var layoutAttributes = require('./layout_attributes');
19+
var handleTypeDefaults = require('./type_defaults');
1920
var handleAxisDefaults = require('./axis_defaults');
2021
var handlePositionDefaults = require('./position_defaults');
2122
var axisIds = require('./axis_ids');
@@ -141,6 +142,12 @@ module.exports = function supplyLayoutDefaults(layoutIn, layoutOut, fullData) {
141142
return out;
142143
}
143144

145+
// sets of axes linked by `scalewith` along with the scaleratios compounded
146+
// together, populated in handleConstraintDefaults
147+
layoutOut._axisConstraintGroups = [];
148+
149+
// first pass creates the containers and determines types, because
150+
// we need to have all types predetermined before setting constraints
144151
for(i = 0; i < axesList.length; i++) {
145152
axName = axesList[i];
146153

@@ -151,14 +158,25 @@ module.exports = function supplyLayoutDefaults(layoutIn, layoutOut, fullData) {
151158
axLayoutIn = layoutIn[axName];
152159
axLayoutOut = layoutOut[axName] = {};
153160

161+
handleTypeDefaults(axLayoutIn, axLayoutOut, coerce, fullData, axName);
162+
}
163+
164+
// second pass handles most of the settings
165+
for(i = 0; i < axesList.length; i++) {
166+
axName = axesList[i];
167+
168+
axLayoutIn = layoutIn[axName];
169+
axLayoutOut = layoutOut[axName];
170+
154171
var axLetter = axName.charAt(0);
172+
var counterAxes = getCounterAxes(axLetter);
173+
var overlayableAxes = getOverlayableAxes(axLetter, axName);
155174

156175
var defaultOptions = {
157176
letter: axLetter,
158177
font: layoutOut.font,
159178
outerTicks: outerTicks[axName],
160179
showGrid: !noGrids[axName],
161-
name: axName,
162180
data: fullData,
163181
bgColor: bgColor,
164182
calendar: layoutOut.calendar
@@ -168,16 +186,16 @@ module.exports = function supplyLayoutDefaults(layoutIn, layoutOut, fullData) {
168186

169187
var positioningOptions = {
170188
letter: axLetter,
171-
counterAxes: getCounterAxes(axLetter),
172-
overlayableAxes: getOverlayableAxes(axLetter, axName)
189+
counterAxes: counterAxes,
190+
overlayableAxes: overlayableAxes
173191
};
174192

175193
handlePositionDefaults(axLayoutIn, axLayoutOut, coerce, positioningOptions);
176194

177195
axLayoutOut._input = axLayoutIn;
178196
}
179197

180-
// quick second pass for range slider and selector defaults
198+
// quick third pass for range slider and selector defaults
181199
var rangeSliderDefaults = Registry.getComponentMethod('rangeslider', 'handleDefaults'),
182200
rangeSelectorDefaults = Registry.getComponentMethod('rangeselector', 'handleDefaults');
183201

src/plots/cartesian/type_defaults.js

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
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+
10+
'use strict';
11+
12+
var Registry = require('../../registry');
13+
var autoType = require('./axis_autotype');
14+
var name2id = require('./axis_ids').name2id;
15+
16+
/*
17+
* data: the plot data to use in choosing auto type
18+
* name: axis object name (ie 'xaxis') if one should be stored
19+
*/
20+
module.exports = function handleTypeDefaults(containerIn, containerOut, coerce, data, name) {
21+
// set up some private properties
22+
if(name) {
23+
containerOut._name = name;
24+
containerOut._id = name2id(name);
25+
}
26+
27+
var axType = coerce('type');
28+
if(axType === '-') {
29+
setAutoType(containerOut, data);
30+
31+
if(containerOut.type === '-') {
32+
containerOut.type = 'linear';
33+
}
34+
else {
35+
// copy autoType back to input axis
36+
// note that if this object didn't exist
37+
// in the input layout, we have to put it in
38+
// this happens in the main supplyDefaults function
39+
containerIn.type = containerOut.type;
40+
}
41+
}
42+
};
43+
44+
function setAutoType(ax, data) {
45+
// new logic: let people specify any type they want,
46+
// only autotype if type is '-'
47+
if(ax.type !== '-') return;
48+
49+
var id = ax._id,
50+
axLetter = id.charAt(0);
51+
52+
// support 3d
53+
if(id.indexOf('scene') !== -1) id = axLetter;
54+
55+
var d0 = getFirstNonEmptyTrace(data, id, axLetter);
56+
if(!d0) return;
57+
58+
// first check for histograms, as the count direction
59+
// should always default to a linear axis
60+
if(d0.type === 'histogram' &&
61+
axLetter === {v: 'y', h: 'x'}[d0.orientation || 'v']) {
62+
ax.type = 'linear';
63+
return;
64+
}
65+
66+
var calAttr = axLetter + 'calendar',
67+
calendar = d0[calAttr];
68+
69+
// check all boxes on this x axis to see
70+
// if they're dates, numbers, or categories
71+
if(isBoxWithoutPositionCoords(d0, axLetter)) {
72+
var posLetter = getBoxPosLetter(d0),
73+
boxPositions = [],
74+
trace;
75+
76+
for(var i = 0; i < data.length; i++) {
77+
trace = data[i];
78+
if(!Registry.traceIs(trace, 'box') ||
79+
(trace[axLetter + 'axis'] || axLetter) !== id) continue;
80+
81+
if(trace[posLetter] !== undefined) boxPositions.push(trace[posLetter][0]);
82+
else if(trace.name !== undefined) boxPositions.push(trace.name);
83+
else boxPositions.push('text');
84+
85+
if(trace[calAttr] !== calendar) calendar = undefined;
86+
}
87+
88+
ax.type = autoType(boxPositions, calendar);
89+
}
90+
else {
91+
ax.type = autoType(d0[axLetter] || [d0[axLetter + '0']], calendar);
92+
}
93+
}
94+
95+
function getFirstNonEmptyTrace(data, id, axLetter) {
96+
for(var i = 0; i < data.length; i++) {
97+
var trace = data[i];
98+
99+
if((trace[axLetter + 'axis'] || axLetter) === id) {
100+
if(isBoxWithoutPositionCoords(trace, axLetter)) {
101+
return trace;
102+
}
103+
else if((trace[axLetter] || []).length || trace[axLetter + '0']) {
104+
return trace;
105+
}
106+
}
107+
}
108+
}
109+
110+
function getBoxPosLetter(trace) {
111+
return {v: 'x', h: 'y'}[trace.orientation || 'v'];
112+
}
113+
114+
function isBoxWithoutPositionCoords(trace, axLetter) {
115+
var posLetter = getBoxPosLetter(trace),
116+
isBox = Registry.traceIs(trace, 'box'),
117+
isCandlestick = Registry.traceIs(trace._fullInput || {}, 'candlestick');
118+
119+
return (
120+
isBox &&
121+
!isCandlestick &&
122+
axLetter === posLetter &&
123+
trace[posLetter] === undefined &&
124+
trace[posLetter + '0'] === undefined
125+
);
126+
}

src/plots/gl3d/layout/axis_defaults.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ var colorMix = require('tinycolor2').mix;
1414
var Lib = require('../../../lib');
1515

1616
var layoutAttributes = require('./axis_attributes');
17+
var handleTypeDefaults = require('../../cartesian/type_defaults');
1718
var handleAxisDefaults = require('../../cartesian/axis_defaults');
1819

1920
var axesNames = ['xaxis', 'yaxis', 'zaxis'];
@@ -33,12 +34,14 @@ module.exports = function supplyLayoutDefaults(layoutIn, layoutOut, options) {
3334
var axName = axesNames[j];
3435
containerIn = layoutIn[axName] || {};
3536

36-
containerOut = {
37+
containerOut = layoutOut[axName] = {
3738
_id: axName[0] + options.scene,
3839
_name: axName
3940
};
4041

41-
layoutOut[axName] = containerOut = handleAxisDefaults(
42+
handleTypeDefaults(containerIn, containerOut, coerce, options.data);
43+
44+
handleAxisDefaults(
4245
containerIn,
4346
containerOut,
4447
coerce, {

src/plots/ternary/layout/defaults.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ function handleTernaryDefaults(ternaryLayoutIn, ternaryLayoutOut, coerce, option
3939
for(var j = 0; j < axesNames.length; j++) {
4040
axName = axesNames[j];
4141
containerIn = ternaryLayoutIn[axName] || {};
42-
containerOut = ternaryLayoutOut[axName] = {_name: axName};
42+
containerOut = ternaryLayoutOut[axName] = {_name: axName, type: 'linear'};
4343

4444
handleAxisDefaults(containerIn, containerOut, options);
4545
}

src/traces/scattergl/convert.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -310,7 +310,7 @@ proto.update = function(options) {
310310
// representing the epoch milliseconds in a typed array;
311311
// also, perhaps the Python / R interfaces take care of String->Date conversions
312312
// such that there's no need to check for string dates in plotly.js)
313-
// Patterned from axis_defaults.js:moreDates
313+
// Patterned from axis_autotype.js:moreDates
314314
// Code DRYing is not done to preserve the most direct compilation possible for speed;
315315
// also, there are quite a few differences
316316
function allFastTypesLikely(a) {

0 commit comments

Comments
 (0)