@@ -55,26 +55,9 @@ exports.handleDefaults = function(layoutIn, layoutOut, opts) {
5555 }
5656 stash ( matchGroups , '_matchGroup' ) ;
5757
58- // remove constraint groups that simply duplicate match groups
59- i = 0 ;
60- while ( i < constraintGroups . length ) {
61- group = constraintGroups [ i ] ;
62- for ( axId in group ) {
63- axOut = layoutOut [ id2name ( axId ) ] ;
64- if ( axOut . _matchGroup && Object . keys ( axOut . _matchGroup ) . length === Object . keys ( group ) . length ) {
65- constraintGroups . splice ( i , 1 ) ;
66- i -- ;
67- }
68- break ;
69- }
70- i ++ ;
71- }
72-
73- // save constraintGroup on each constrained axis
74- stash ( constraintGroups , '_constraintGroup' ) ;
75-
7658 // If any axis in a constraint group is fixedrange, they all get fixed
77- // This covers matches axes, as they're now in the constraintgroup too.
59+ // This covers matches axes, as they're now in the constraintgroup too
60+ // and have not yet been removed (if the group is *only* matching)
7861 for ( i = 0 ; i < constraintGroups . length ; i ++ ) {
7962 group = constraintGroups [ i ] ;
8063 for ( axId in group ) {
@@ -89,33 +72,53 @@ exports.handleDefaults = function(layoutIn, layoutOut, opts) {
8972 'axis in its constraint group has fixedrange true'
9073 ) ;
9174 }
92- layoutOut [ id2name ( axId2 ) ] . fixedrange = true ;
75+ layoutOut [ axName2 ] . fixedrange = true ;
9376 }
9477 break ;
9578 }
9679 }
9780 }
9881
82+ // remove constraint groups that simply duplicate match groups
83+ i = 0 ;
84+ while ( i < constraintGroups . length ) {
85+ group = constraintGroups [ i ] ;
86+ for ( axId in group ) {
87+ axOut = layoutOut [ id2name ( axId ) ] ;
88+ if ( axOut . _matchGroup && Object . keys ( axOut . _matchGroup ) . length === Object . keys ( group ) . length ) {
89+ constraintGroups . splice ( i , 1 ) ;
90+ i -- ;
91+ }
92+ break ;
93+ }
94+ i ++ ;
95+ }
96+
97+ // save constraintGroup on each constrained axis
98+ stash ( constraintGroups , '_constraintGroup' ) ;
99+
99100 // make sure `matching` axes share values of necessary attributes
100101 // Precedence (base axis is the one that doesn't list a `matches`, ie others
101102 // all point to it):
102103 // (1) explicitly defined value in the base axis
103104 // (2) explicitly defined in another axis (arbitrary order)
104105 // (3) default in the base axis
105- var matchAttrs = {
106- constrain : 1 ,
107- range : 1 ,
108- autorange : 1 ,
109- rangemode : 1 ,
110- rangebreaks : 1 ,
111- categoryorder : 1 ,
112- categoryarray : 1
113- } ;
106+ var matchAttrs = [
107+ 'constrain' ,
108+ 'range' ,
109+ 'autorange' ,
110+ 'rangemode' ,
111+ 'rangebreaks' ,
112+ 'categoryorder' ,
113+ 'categoryarray'
114+ ] ;
115+ var hasRange = false ;
114116 for ( i = 0 ; i < matchGroups . length ; i ++ ) {
115117 group = matchGroups [ i ] ;
116118
117119 // find 'matching' range attrs
118- for ( var attr in matchAttrs ) {
120+ for ( var j = 0 ; j < matchAttrs . length ; j ++ ) {
121+ var attr = matchAttrs [ j ] ;
119122 var val = null ;
120123 var baseAx ;
121124 for ( axId in group ) {
@@ -138,6 +141,17 @@ exports.handleDefaults = function(layoutIn, layoutOut, opts) {
138141 val = axOut [ attr ] ;
139142 }
140143 }
144+
145+ // special logic for coupling of range and autorange
146+ // if nobody explicitly specifies autorange, but someone does
147+ // explicitly specify range, autorange must be disabled.
148+ if ( attr === 'range' && val ) {
149+ hasRange = true ;
150+ }
151+ if ( attr === 'autorange' && val === null && hasRange ) {
152+ val = false ;
153+ }
154+
141155 if ( val === null && attr in baseAx ) {
142156 // fallback: default value in base axis
143157 val = baseAx [ attr ] ;
@@ -244,7 +258,7 @@ function handleOneAxDefaults(axIn, axOut, opts) {
244258
245259 // Also include match constraints in the scale groups
246260 var matchedAx = layoutOut [ id2name ( matches ) ] ;
247- var matchRatio = extent ( axOut ) / extent ( matchedAx ) ;
261+ var matchRatio = extent ( layoutOut , axOut ) / extent ( layoutOut , matchedAx ) ;
248262 if ( isX !== ( matches . charAt ( 0 ) === 'x' ) ) {
249263 // We don't yet know the actual scale ratio of x/y matches constraints,
250264 // due to possible automargins, so just leave a placeholder for this:
@@ -277,8 +291,14 @@ function handleOneAxDefaults(axIn, axOut, opts) {
277291 }
278292}
279293
280- function extent ( ax ) {
281- return ax . domain [ 1 ] - ax . domain [ 0 ] ;
294+ function extent ( layoutOut , ax ) {
295+ var domain = ax . domain ;
296+ if ( ! domain ) {
297+ // at this point overlaying axes haven't yet inherited their main domains
298+ // TODO: constrain: domain with overlaying axes is likely a bug.
299+ domain = layoutOut [ id2name ( ax . overlaying ) ] . domain ;
300+ }
301+ return domain [ 1 ] - domain [ 0 ] ;
282302}
283303
284304function getConstraintGroup ( groups , thisID ) {
0 commit comments