@@ -24,6 +24,8 @@ var axisIds = require('./axis_ids');
24
24
var id2name = axisIds . id2name ;
25
25
var name2id = axisIds . name2id ;
26
26
27
+ var AX_ID_PATTERN = require ( './constants' ) . AX_ID_PATTERN ;
28
+
27
29
var Registry = require ( '../../registry' ) ;
28
30
var traceIs = Registry . traceIs ;
29
31
var getComponentMethod = Registry . getComponentMethod ;
@@ -133,7 +135,28 @@ module.exports = function supplyLayoutDefaults(layoutIn, layoutOut, fullData) {
133
135
134
136
var bgColor = Color . combine ( plotBgColor , layoutOut . paper_bgcolor ) ;
135
137
136
- var axName , axLetter , axLayoutIn , axLayoutOut ;
138
+ // name of single axis (e.g. 'xaxis', 'yaxis2')
139
+ var axName ;
140
+ // id of single axis (e.g. 'y', 'x5')
141
+ var axId ;
142
+ // 'x' or 'y'
143
+ var axLetter ;
144
+ // input layout axis container
145
+ var axLayoutIn ;
146
+ // full layout axis container
147
+ var axLayoutOut ;
148
+
149
+ function newAxLayoutOut ( ) {
150
+ var traces = ax2traces [ axName ] || [ ] ;
151
+ axLayoutOut . _traceIndices = traces . map ( function ( t ) { return t . _expandedIndex ; } ) ;
152
+ axLayoutOut . _annIndices = [ ] ;
153
+ axLayoutOut . _shapeIndices = [ ] ;
154
+ axLayoutOut . _imgIndices = [ ] ;
155
+ axLayoutOut . _subplotsWith = [ ] ;
156
+ axLayoutOut . _counterAxes = [ ] ;
157
+ axLayoutOut . _name = axLayoutOut . _attr = axName ;
158
+ axLayoutOut . _id = axId ;
159
+ }
137
160
138
161
function coerce ( attr , dflt ) {
139
162
return Lib . coerce ( axLayoutIn , axLayoutOut , layoutAttributes , attr , dflt ) ;
@@ -147,9 +170,6 @@ module.exports = function supplyLayoutDefaults(layoutIn, layoutOut, fullData) {
147
170
return ( axLetter === 'x' ) ? yIds : xIds ;
148
171
}
149
172
150
- var counterAxes = { x : getCounterAxes ( 'x' ) , y : getCounterAxes ( 'y' ) } ;
151
- var allAxisIds = counterAxes . x . concat ( counterAxes . y ) ;
152
-
153
173
function getOverlayableAxes ( axLetter , axName ) {
154
174
var list = ( axLetter === 'x' ) ? xNames : yNames ;
155
175
var out = [ ] ;
@@ -165,9 +185,30 @@ module.exports = function supplyLayoutDefaults(layoutIn, layoutOut, fullData) {
165
185
return out ;
166
186
}
167
187
188
+ // list of available counter axis names
189
+ var counterAxes = { x : getCounterAxes ( 'x' ) , y : getCounterAxes ( 'y' ) } ;
190
+ // list of all x AND y axis ids
191
+ var allAxisIds = counterAxes . x . concat ( counterAxes . y ) ;
192
+ // lookup and list of axis ids that axes in axNames have a reference to,
193
+ // even though they are missing from allAxisIds
194
+ var missingMatchedAxisIdsLookup = { } ;
195
+ var missingMatchedAxisIds = [ ] ;
196
+
197
+ // fill in 'missing' axis lookup when an axis is set to match an axis
198
+ // not part of the allAxisIds list, save axis type so that we can propagate
199
+ // it to the missing axes
200
+ function addMissingMatchedAxis ( ) {
201
+ var matchesIn = axLayoutIn . matches ;
202
+ if ( AX_ID_PATTERN . test ( matchesIn ) && allAxisIds . indexOf ( matchesIn ) === - 1 ) {
203
+ missingMatchedAxisIdsLookup [ matchesIn ] = axLayoutIn . type ;
204
+ missingMatchedAxisIds = Object . keys ( missingMatchedAxisIdsLookup ) ;
205
+ }
206
+ }
207
+
168
208
// first pass creates the containers, determines types, and handles most of the settings
169
209
for ( i = 0 ; i < axNames . length ; i ++ ) {
170
210
axName = axNames [ i ] ;
211
+ axId = name2id ( axName ) ;
171
212
axLetter = axName . charAt ( 0 ) ;
172
213
173
214
if ( ! Lib . isPlainObject ( layoutIn [ axName ] ) ) {
@@ -176,20 +217,7 @@ module.exports = function supplyLayoutDefaults(layoutIn, layoutOut, fullData) {
176
217
177
218
axLayoutIn = layoutIn [ axName ] ;
178
219
axLayoutOut = Template . newContainer ( layoutOut , axName , axLetter + 'axis' ) ;
179
-
180
- var traces = ax2traces [ axName ] || [ ] ;
181
- axLayoutOut . _traceIndices = traces . map ( function ( t ) { return t . _expandedIndex ; } ) ;
182
- axLayoutOut . _annIndices = [ ] ;
183
- axLayoutOut . _shapeIndices = [ ] ;
184
- axLayoutOut . _imgIndices = [ ] ;
185
- axLayoutOut . _subplotsWith = [ ] ;
186
- axLayoutOut . _counterAxes = [ ] ;
187
-
188
- // set up some private properties
189
- axLayoutOut . _name = axLayoutOut . _attr = axName ;
190
- var id = axLayoutOut . _id = name2id ( axName ) ;
191
-
192
- var overlayableAxes = getOverlayableAxes ( axLetter , axName ) ;
220
+ newAxLayoutOut ( ) ;
193
221
194
222
var visibleDflt =
195
223
( axLetter === 'x' && ! xaMustDisplay [ axName ] && xaMayHide [ axName ] ) ||
@@ -207,13 +235,13 @@ module.exports = function supplyLayoutDefaults(layoutIn, layoutOut, fullData) {
207
235
font : layoutOut . font ,
208
236
outerTicks : outerTicks [ axName ] ,
209
237
showGrid : ! noGrids [ axName ] ,
210
- data : traces ,
238
+ data : ax2traces [ axName ] || [ ] ,
211
239
bgColor : bgColor ,
212
240
calendar : layoutOut . calendar ,
213
241
automargin : true ,
214
242
visibleDflt : visibleDflt ,
215
243
reverseDflt : reverseDflt ,
216
- splomStash : ( ( layoutOut . _splomAxes || { } ) [ axLetter ] || { } ) [ id ]
244
+ splomStash : ( ( layoutOut . _splomAxes || { } ) [ axLetter ] || { } ) [ axId ]
217
245
} ;
218
246
219
247
coerce ( 'uirevision' , layoutOut . uirevision ) ;
@@ -239,12 +267,63 @@ module.exports = function supplyLayoutDefaults(layoutIn, layoutOut, fullData) {
239
267
handlePositionDefaults ( axLayoutIn , axLayoutOut , coerce , {
240
268
letter : axLetter ,
241
269
counterAxes : counterAxes [ axLetter ] ,
242
- overlayableAxes : overlayableAxes ,
270
+ overlayableAxes : getOverlayableAxes ( axLetter , axName ) ,
243
271
grid : layoutOut . grid
244
272
} ) ;
245
273
246
274
coerce ( 'title.standoff' ) ;
247
275
276
+ addMissingMatchedAxis ( ) ;
277
+
278
+ axLayoutOut . _input = axLayoutIn ;
279
+ }
280
+
281
+ // coerce the 'missing' axes
282
+ i = 0 ;
283
+ while ( i < missingMatchedAxisIds . length ) {
284
+ axId = missingMatchedAxisIds [ i ++ ] ;
285
+ axName = id2name ( axId ) ;
286
+ axLetter = axName . charAt ( 0 ) ;
287
+
288
+ if ( ! Lib . isPlainObject ( layoutIn [ axName ] ) ) {
289
+ layoutIn [ axName ] = { } ;
290
+ }
291
+
292
+ axLayoutIn = layoutIn [ axName ] ;
293
+ axLayoutOut = Template . newContainer ( layoutOut , axName , axLetter + 'axis' ) ;
294
+ newAxLayoutOut ( ) ;
295
+
296
+ var defaultOptions2 = {
297
+ letter : axLetter ,
298
+ font : layoutOut . font ,
299
+ outerTicks : outerTicks [ axName ] ,
300
+ showGrid : ! noGrids [ axName ] ,
301
+ data : [ ] ,
302
+ bgColor : bgColor ,
303
+ calendar : layoutOut . calendar ,
304
+ automargin : true ,
305
+ visibleDflt : false ,
306
+ reverseDflt : false ,
307
+ splomStash : ( ( layoutOut . _splomAxes || { } ) [ axLetter ] || { } ) [ axId ]
308
+ } ;
309
+
310
+ coerce ( 'uirevision' , layoutOut . uirevision ) ;
311
+
312
+ axLayoutOut . type = missingMatchedAxisIdsLookup [ axId ] || 'linear' ;
313
+
314
+ handleAxisDefaults ( axLayoutIn , axLayoutOut , coerce , defaultOptions2 , layoutOut ) ;
315
+
316
+ handlePositionDefaults ( axLayoutIn , axLayoutOut , coerce , {
317
+ letter : axLetter ,
318
+ counterAxes : counterAxes [ axLetter ] ,
319
+ overlayableAxes : getOverlayableAxes ( axLetter , axName ) ,
320
+ grid : layoutOut . grid
321
+ } ) ;
322
+
323
+ coerce ( 'fixedrange' ) ;
324
+
325
+ addMissingMatchedAxis ( ) ;
326
+
248
327
axLayoutOut . _input = axLayoutIn ;
249
328
}
250
329
@@ -295,25 +374,32 @@ module.exports = function supplyLayoutDefaults(layoutIn, layoutOut, fullData) {
295
374
var constraintGroups = layoutOut . _axisConstraintGroups = [ ] ;
296
375
// similar to _axisConstraintGroups, but for matching axes
297
376
var matchGroups = layoutOut . _axisMatchGroups = [ ] ;
377
+ // make sure to include 'missing' axes here
378
+ var allAxisIdsIncludingMissing = allAxisIds . concat ( missingMatchedAxisIds ) ;
379
+ var axNamesIncludingMissing = axNames . concat ( Lib . simpleMap ( missingMatchedAxisIds , id2name ) ) ;
298
380
299
- for ( i = 0 ; i < axNames . length ; i ++ ) {
300
- axName = axNames [ i ] ;
381
+ for ( i = 0 ; i < axNamesIncludingMissing . length ; i ++ ) {
382
+ axName = axNamesIncludingMissing [ i ] ;
301
383
axLetter = axName . charAt ( 0 ) ;
302
384
axLayoutIn = layoutIn [ axName ] ;
303
385
axLayoutOut = layoutOut [ axName ] ;
304
386
305
387
var scaleanchorDflt ;
306
388
if ( axLetter === 'y' && ! axLayoutIn . hasOwnProperty ( 'scaleanchor' ) && axHasImage [ axName ] ) {
307
389
scaleanchorDflt = axLayoutOut . anchor ;
308
- } else { scaleanchorDflt = undefined ; }
390
+ } else {
391
+ scaleanchorDflt = undefined ;
392
+ }
309
393
310
394
var constrainDflt ;
311
395
if ( ! axLayoutIn . hasOwnProperty ( 'constrain' ) && axHasImage [ axName ] ) {
312
396
constrainDflt = 'domain' ;
313
- } else { constrainDflt = undefined ; }
397
+ } else {
398
+ constrainDflt = undefined ;
399
+ }
314
400
315
401
handleConstraintDefaults ( axLayoutIn , axLayoutOut , coerce , {
316
- allAxisIds : allAxisIds ,
402
+ allAxisIds : allAxisIdsIncludingMissing ,
317
403
layoutOut : layoutOut ,
318
404
scaleanchorDflt : scaleanchorDflt ,
319
405
constrainDflt : constrainDflt
@@ -324,7 +410,6 @@ module.exports = function supplyLayoutDefaults(layoutIn, layoutOut, fullData) {
324
410
var group = matchGroups [ i ] ;
325
411
var rng = null ;
326
412
var autorange = null ;
327
- var axId ;
328
413
329
414
// find 'matching' range attrs
330
415
for ( axId in group ) {
0 commit comments