@@ -17,6 +17,7 @@ var cleanNumber = Lib.cleanNumber;
1717var ms2DateTime = Lib . ms2DateTime ;
1818var dateTime2ms = Lib . dateTime2ms ;
1919var ensureNumber = Lib . ensureNumber ;
20+ var isArrayOrTypedArray = Lib . isArrayOrTypedArray ;
2021
2122var numConstants = require ( '../../constants/numerical' ) ;
2223var FP_SAFE = numConstants . FP_SAFE ;
@@ -148,43 +149,11 @@ module.exports = function setConvert(ax, fullLayout) {
148149
149150 function setMultiCategoryIndex ( arrayIn , len ) {
150151 var arrayOut = new Array ( len ) ;
151- var i ;
152152
153- // [ [arrayIn[0][i], arrayIn[1][i]], for i .. len ]
154- var tmp = new Array ( len ) ;
155- // [ [cnt, {$cat: index}], for j .. arrayIn.length ]
156- var seen = [ [ 0 , { } ] , [ 0 , { } ] ] ;
157-
158- if ( Lib . isArrayOrTypedArray ( arrayIn [ 0 ] ) && Lib . isArrayOrTypedArray ( arrayIn [ 1 ] ) ) {
159- for ( i = 0 ; i < len ; i ++ ) {
160- var v0 = arrayIn [ 0 ] [ i ] ;
161- var v1 = arrayIn [ 1 ] [ i ] ;
162- if ( isValidCategory ( v0 ) && isValidCategory ( v1 ) ) {
163- tmp [ i ] = [ v0 , v1 ] ;
164- if ( ! ( v0 in seen [ 0 ] [ 1 ] ) ) {
165- seen [ 0 ] [ 1 ] [ v0 ] = seen [ 0 ] [ 0 ] ++ ;
166- }
167- if ( ! ( v1 in seen [ 1 ] [ 1 ] ) ) {
168- seen [ 1 ] [ 1 ] [ v1 ] = seen [ 1 ] [ 0 ] ++ ;
169- }
170- }
171- }
172-
173- tmp . sort ( function ( a , b ) {
174- var ind0 = seen [ 0 ] [ 1 ] ;
175- var d = ind0 [ a [ 0 ] ] - ind0 [ b [ 0 ] ] ;
176- if ( d ) return d ;
177-
178- var ind1 = seen [ 1 ] [ 1 ] ;
179- return ind1 [ a [ 1 ] ] - ind1 [ b [ 1 ] ] ;
180- } ) ;
181-
182- for ( i = 0 ; i < len ; i ++ ) {
183- setCategoryIndex ( tmp [ i ] ) ;
184- }
185- for ( i = 0 ; i < len ; i ++ ) {
186- arrayOut [ i ] = getCategoryIndex ( [ arrayIn [ 0 ] [ i ] , arrayIn [ 1 ] [ i ] ] ) ;
187- }
153+ for ( var i = 0 ; i < len ; i ++ ) {
154+ var v0 = ( arrayIn [ 0 ] || [ ] ) [ i ] ;
155+ var v1 = ( arrayIn [ 1 ] || [ ] ) [ i ] ;
156+ arrayOut [ i ] = getCategoryIndex ( [ v0 , v1 ] ) ;
188157 }
189158
190159 return arrayOut ;
@@ -333,6 +302,56 @@ module.exports = function setConvert(ax, fullLayout) {
333302 if ( Array . isArray ( v ) || ( typeof v === 'string' && v !== '' ) ) return v ;
334303 return ensureNumber ( v ) ;
335304 } ;
305+
306+ ax . setupMultiCategory = function ( fullData ) {
307+ var traceIndices = ax . _traceIndices ;
308+ var i , j ;
309+
310+ // [ [cnt, {$cat: index}], for 1,2 ]
311+ var seen = ax . _multicatSeen = [ [ 0 , { } ] , [ 0 , { } ] ] ;
312+ // [ [arrayIn[0][i], arrayIn[1][i]], for i .. N ]
313+ var list = ax . _multicatList = [ ] ;
314+
315+ for ( i = 0 ; i < traceIndices . length ; i ++ ) {
316+ var trace = fullData [ traceIndices [ i ] ] ;
317+
318+ if ( axLetter in trace ) {
319+ var arrayIn = trace [ axLetter ] ;
320+ var len = trace . _length || Lib . minRowLength ( arrayIn ) ;
321+
322+ if ( isArrayOrTypedArray ( arrayIn [ 0 ] ) && isArrayOrTypedArray ( arrayIn [ 1 ] ) ) {
323+ for ( j = 0 ; j < len ; j ++ ) {
324+ var v0 = arrayIn [ 0 ] [ j ] ;
325+ var v1 = arrayIn [ 1 ] [ j ] ;
326+
327+ if ( isValidCategory ( v0 ) && isValidCategory ( v1 ) ) {
328+ list . push ( [ v0 , v1 ] ) ;
329+
330+ if ( ! ( v0 in seen [ 0 ] [ 1 ] ) ) {
331+ seen [ 0 ] [ 1 ] [ v0 ] = seen [ 0 ] [ 0 ] ++ ;
332+ }
333+ if ( ! ( v1 in seen [ 1 ] [ 1 ] ) ) {
334+ seen [ 1 ] [ 1 ] [ v1 ] = seen [ 1 ] [ 0 ] ++ ;
335+ }
336+ }
337+ }
338+ }
339+ }
340+ }
341+
342+ list . sort ( function ( a , b ) {
343+ var ind0 = seen [ 0 ] [ 1 ] ;
344+ var d = ind0 [ a [ 0 ] ] - ind0 [ b [ 0 ] ] ;
345+ if ( d ) return d ;
346+
347+ var ind1 = seen [ 1 ] [ 1 ] ;
348+ return ind1 [ a [ 1 ] ] - ind1 [ b [ 1 ] ] ;
349+ } ) ;
350+
351+ for ( i = 0 ; i < list . length ; i ++ ) {
352+ setCategoryIndex ( list [ i ] ) ;
353+ }
354+ } ;
336355 }
337356
338357 // find the range value at the specified (linear) fraction of the axis
0 commit comments