@@ -24,6 +24,8 @@ var axisIds = require('./axis_ids');
2424var id2name = axisIds . id2name ;
2525var name2id = axisIds . name2id ;
2626
27+ var AX_ID_PATTERN = require ( './constants' ) . AX_ID_PATTERN ;
28+
2729var Registry = require ( '../../registry' ) ;
2830var traceIs = Registry . traceIs ;
2931var getComponentMethod = Registry . getComponentMethod ;
@@ -133,7 +135,28 @@ module.exports = function supplyLayoutDefaults(layoutIn, layoutOut, fullData) {
133135
134136 var bgColor = Color . combine ( plotBgColor , layoutOut . paper_bgcolor ) ;
135137
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+ }
137160
138161 function coerce ( attr , dflt ) {
139162 return Lib . coerce ( axLayoutIn , axLayoutOut , layoutAttributes , attr , dflt ) ;
@@ -147,9 +170,6 @@ module.exports = function supplyLayoutDefaults(layoutIn, layoutOut, fullData) {
147170 return ( axLetter === 'x' ) ? yIds : xIds ;
148171 }
149172
150- var counterAxes = { x : getCounterAxes ( 'x' ) , y : getCounterAxes ( 'y' ) } ;
151- var allAxisIds = counterAxes . x . concat ( counterAxes . y ) ;
152-
153173 function getOverlayableAxes ( axLetter , axName ) {
154174 var list = ( axLetter === 'x' ) ? xNames : yNames ;
155175 var out = [ ] ;
@@ -165,9 +185,26 @@ module.exports = function supplyLayoutDefaults(layoutIn, layoutOut, fullData) {
165185 return out ;
166186 }
167187
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+ // list of axis ids that axes in axNames have a reference to,
193+ // even though they are missing from allAxisIds
194+ var missingMatchedAxisIds = [ ] ;
195+
196+ // fill in 'missing' axis list when an axis is set to match an axis
197+ // not part of the allAxisIds list
198+ function addMissingMatchedAxis ( matchesIn ) {
199+ if ( AX_ID_PATTERN . test ( matchesIn ) && allAxisIds . indexOf ( matchesIn ) === - 1 ) {
200+ Lib . pushUnique ( missingMatchedAxisIds , matchesIn ) ;
201+ }
202+ }
203+
168204 // first pass creates the containers, determines types, and handles most of the settings
169205 for ( i = 0 ; i < axNames . length ; i ++ ) {
170206 axName = axNames [ i ] ;
207+ axId = name2id ( axName ) ;
171208 axLetter = axName . charAt ( 0 ) ;
172209
173210 if ( ! Lib . isPlainObject ( layoutIn [ axName ] ) ) {
@@ -176,20 +213,7 @@ module.exports = function supplyLayoutDefaults(layoutIn, layoutOut, fullData) {
176213
177214 axLayoutIn = layoutIn [ axName ] ;
178215 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 ) ;
216+ newAxLayoutOut ( ) ;
193217
194218 var visibleDflt =
195219 ( axLetter === 'x' && ! xaMustDisplay [ axName ] && xaMayHide [ axName ] ) ||
@@ -207,13 +231,13 @@ module.exports = function supplyLayoutDefaults(layoutIn, layoutOut, fullData) {
207231 font : layoutOut . font ,
208232 outerTicks : outerTicks [ axName ] ,
209233 showGrid : ! noGrids [ axName ] ,
210- data : traces ,
234+ data : ax2traces [ axName ] || [ ] ,
211235 bgColor : bgColor ,
212236 calendar : layoutOut . calendar ,
213237 automargin : true ,
214238 visibleDflt : visibleDflt ,
215239 reverseDflt : reverseDflt ,
216- splomStash : ( ( layoutOut . _splomAxes || { } ) [ axLetter ] || { } ) [ id ]
240+ splomStash : ( ( layoutOut . _splomAxes || { } ) [ axLetter ] || { } ) [ axId ]
217241 } ;
218242
219243 coerce ( 'uirevision' , layoutOut . uirevision ) ;
@@ -239,12 +263,60 @@ module.exports = function supplyLayoutDefaults(layoutIn, layoutOut, fullData) {
239263 handlePositionDefaults ( axLayoutIn , axLayoutOut , coerce , {
240264 letter : axLetter ,
241265 counterAxes : counterAxes [ axLetter ] ,
242- overlayableAxes : overlayableAxes ,
266+ overlayableAxes : getOverlayableAxes ( axLetter , axName ) ,
243267 grid : layoutOut . grid
244268 } ) ;
245269
246270 coerce ( 'title.standoff' ) ;
247271
272+ addMissingMatchedAxis ( axLayoutIn . matches ) ;
273+
274+ axLayoutOut . _input = axLayoutIn ;
275+ }
276+
277+ // coerce the 'missing' axes
278+ i = 0 ;
279+ while ( i < missingMatchedAxisIds . length ) {
280+ axId = missingMatchedAxisIds [ i ++ ] ;
281+ axName = id2name ( axId ) ;
282+ axLetter = axName . charAt ( 0 ) ;
283+
284+ if ( ! Lib . isPlainObject ( layoutIn [ axName ] ) ) {
285+ layoutIn [ axName ] = { } ;
286+ }
287+
288+ axLayoutIn = layoutIn [ axName ] ;
289+ axLayoutOut = Template . newContainer ( layoutOut , axName , axLetter + 'axis' ) ;
290+ newAxLayoutOut ( ) ;
291+
292+ var defaultOptions2 = {
293+ letter : axLetter ,
294+ font : layoutOut . font ,
295+ outerTicks : outerTicks [ axName ] ,
296+ showGrid : ! noGrids [ axName ] ,
297+ data : [ ] ,
298+ bgColor : bgColor ,
299+ calendar : layoutOut . calendar ,
300+ automargin : true ,
301+ visibleDflt : false ,
302+ reverseDflt : false ,
303+ splomStash : ( ( layoutOut . _splomAxes || { } ) [ axLetter ] || { } ) [ axId ]
304+ } ;
305+
306+ coerce ( 'uirevision' , layoutOut . uirevision ) ;
307+
308+ handleTypeDefaults ( axLayoutIn , axLayoutOut , coerce , defaultOptions2 ) ;
309+ handleAxisDefaults ( axLayoutIn , axLayoutOut , coerce , defaultOptions2 , layoutOut ) ;
310+
311+ handlePositionDefaults ( axLayoutIn , axLayoutOut , coerce , {
312+ letter : axLetter ,
313+ counterAxes : counterAxes [ axLetter ] ,
314+ overlayableAxes : getOverlayableAxes ( axLetter , axName ) ,
315+ grid : layoutOut . grid
316+ } ) ;
317+
318+ addMissingMatchedAxis ( axLayoutIn . matches ) ;
319+
248320 axLayoutOut . _input = axLayoutIn ;
249321 }
250322
@@ -295,9 +367,12 @@ module.exports = function supplyLayoutDefaults(layoutIn, layoutOut, fullData) {
295367 var constraintGroups = layoutOut . _axisConstraintGroups = [ ] ;
296368 // similar to _axisConstraintGroups, but for matching axes
297369 var matchGroups = layoutOut . _axisMatchGroups = [ ] ;
370+ // make sure to include 'missing' axes here
371+ var allAxisIdsIncludingMissing = allAxisIds . concat ( missingMatchedAxisIds ) ;
372+ var axNamesIncludingMissing = axNames . concat ( Lib . simpleMap ( missingMatchedAxisIds , id2name ) ) ;
298373
299- for ( i = 0 ; i < axNames . length ; i ++ ) {
300- axName = axNames [ i ] ;
374+ for ( i = 0 ; i < axNamesIncludingMissing . length ; i ++ ) {
375+ axName = axNamesIncludingMissing [ i ] ;
301376 axLetter = axName . charAt ( 0 ) ;
302377 axLayoutIn = layoutIn [ axName ] ;
303378 axLayoutOut = layoutOut [ axName ] ;
@@ -317,7 +392,7 @@ module.exports = function supplyLayoutDefaults(layoutIn, layoutOut, fullData) {
317392 }
318393
319394 handleConstraintDefaults ( axLayoutIn , axLayoutOut , coerce , {
320- allAxisIds : allAxisIds ,
395+ allAxisIds : allAxisIdsIncludingMissing ,
321396 layoutOut : layoutOut ,
322397 scaleanchorDflt : scaleanchorDflt ,
323398 constrainDflt : constrainDflt
@@ -328,7 +403,6 @@ module.exports = function supplyLayoutDefaults(layoutIn, layoutOut, fullData) {
328403 var group = matchGroups [ i ] ;
329404 var rng = null ;
330405 var autorange = null ;
331- var axId ;
332406
333407 // find 'matching' range attrs
334408 for ( axId in group ) {
0 commit comments