@@ -2843,10 +2843,176 @@ plots.doCalcdata = function(gd, traces) {
28432843
28442844 doCrossTraceCalc ( gd ) ;
28452845
2846+ // Sort axis categories per value if specified
2847+ var sorted = sortAxisCategoriesByValue ( axList , gd ) ;
2848+ if ( sorted . length ) {
2849+ // If a sort operation was performed, run calc() again
2850+ for ( i = 0 ; i < sorted . length ; i ++ ) calci ( sorted [ i ] , true ) ;
2851+ for ( i = 0 ; i < sorted . length ; i ++ ) calci ( sorted [ i ] , false ) ;
2852+ doCrossTraceCalc ( gd ) ;
2853+ }
2854+
28462855 Registry . getComponentMethod ( 'fx' , 'calc' ) ( gd ) ;
28472856 Registry . getComponentMethod ( 'errorbars' , 'calc' ) ( gd ) ;
28482857} ;
28492858
2859+ var sortAxisCategoriesByValueRegex = / ( v a l u e | s u m | m i n | m a x ) ( a s c e n d i n g | d e s c e n d i n g ) / ;
2860+
2861+ function sortAxisCategoriesByValue ( axList , gd ) {
2862+ var affectedTraces = [ ] ;
2863+ var i , j , k , l , o ;
2864+ for ( i = 0 ; i < axList . length ; i ++ ) {
2865+ var ax = axList [ i ] ;
2866+ if ( ax . type !== 'category' ) continue ;
2867+
2868+ // Order by value
2869+ var match = ax . categoryorder . match ( sortAxisCategoriesByValueRegex ) ;
2870+ if ( match ) {
2871+ // Store values associated with each category
2872+ var categoriesValue = [ ] ;
2873+ for ( j = 0 ; j < ax . _categories . length ; j ++ ) {
2874+ categoriesValue . push ( [ ax . _categories [ j ] , [ ] ] ) ;
2875+ }
2876+
2877+ // Collect values across traces
2878+ for ( j = 0 ; j < ax . _traceIndices . length ; j ++ ) {
2879+ var traceIndex = ax . _traceIndices [ j ] ;
2880+ var fullData = gd . _fullData [ traceIndex ] ;
2881+
2882+ // Skip over invisible traces
2883+ if ( fullData . visible !== true ) continue ;
2884+
2885+ var type = fullData . type ;
2886+ if ( type === 'histogram' ) delete fullData . _autoBinFinished ;
2887+
2888+ var cd = gd . calcdata [ traceIndex ] ;
2889+ for ( k = 0 ; k < cd . length ; k ++ ) {
2890+ var cdi = cd [ k ] ;
2891+ var cat , catIndex , value ;
2892+
2893+ // If `splom`, collect values across dimensions
2894+ if ( type === 'splom' ) {
2895+ // Find which dimension the current axis is representing
2896+ var currentDimensionIndex = cdi . trace [ ax . _id . charAt ( 0 ) + 'axes' ] . indexOf ( ax . _id ) ;
2897+
2898+ // Apply logic to associated x axis
2899+ if ( ax . _id . charAt ( 0 ) === 'y' ) {
2900+ var associatedXAxis = ax . _id . split ( '' ) ;
2901+ associatedXAxis [ 0 ] = 'x' ;
2902+ associatedXAxis = associatedXAxis . join ( '' ) ;
2903+ ax = gd . _fullLayout [ axisIDs . id2name ( associatedXAxis ) ] ;
2904+ }
2905+
2906+ var categories = cdi . trace . dimensions [ currentDimensionIndex ] . values ;
2907+ for ( l = 0 ; l < categories . length ; l ++ ) {
2908+ cat = categories [ l ] ;
2909+ catIndex = ax . _categoriesMap [ cat ] ;
2910+
2911+ // Collect values over all other dimensions
2912+ for ( o = 0 ; o < cdi . trace . dimensions . length ; o ++ ) {
2913+ if ( o === currentDimensionIndex ) continue ;
2914+ var dimension = cdi . trace . dimensions [ o ] ;
2915+ categoriesValue [ catIndex ] [ 1 ] . push ( dimension . values [ l ] ) ;
2916+ }
2917+ }
2918+ // If `scattergl`, collect all values stashed under cdi.t
2919+ } else if ( type === 'scattergl' ) {
2920+ for ( l = 0 ; l < cdi . t . x . length ; l ++ ) {
2921+ if ( ax . _id . charAt ( 0 ) === 'x' ) {
2922+ cat = cdi . t . x [ l ] ;
2923+ catIndex = cat ;
2924+ value = cdi . t . y [ l ] ;
2925+ }
2926+
2927+ if ( ax . _id . charAt ( 0 ) === 'y' ) {
2928+ cat = cdi . t . y [ l ] ;
2929+ catIndex = cat ;
2930+ value = cdi . t . x [ l ] ;
2931+ }
2932+ categoriesValue [ catIndex ] [ 1 ] . push ( value ) ;
2933+ }
2934+ // must clear scene 'batches', so that 2nd
2935+ // _module.calc call starts from scratch
2936+ if ( cdi . t && cdi . t . _scene ) {
2937+ delete cdi . t . _scene . dirty ;
2938+ }
2939+ // For all other 2d cartesian traces
2940+ } else {
2941+ if ( ax . _id . charAt ( 0 ) === 'x' ) {
2942+ cat = cdi . p + 1 ? cdi . p : cdi . x ;
2943+ value = cdi . s || cdi . v || cdi . y ;
2944+ } else if ( ax . _id . charAt ( 0 ) === 'y' ) {
2945+ cat = cdi . p + 1 ? cdi . p : cdi . y ;
2946+ value = cdi . s || cdi . v || cdi . x ;
2947+ }
2948+
2949+ // If 2dMap, collect values in `z`
2950+ if ( cdi . hasOwnProperty ( 'z' ) ) {
2951+ value = cdi . z ;
2952+
2953+ for ( l = 0 ; l < value . length ; l ++ ) {
2954+ for ( o = 0 ; o < value [ l ] . length ; o ++ ) {
2955+ catIndex = ax . _id . charAt ( 0 ) === 'y' ? l : o ;
2956+ categoriesValue [ catIndex ] [ 1 ] . push ( value [ l ] [ o ] ) ;
2957+ }
2958+ }
2959+ } else {
2960+ if ( ! Array . isArray ( value ) ) value = [ value ] ;
2961+ for ( l = 0 ; l < value . length ; l ++ ) {
2962+ categoriesValue [ cat ] [ 1 ] . push ( value [ l ] ) ;
2963+ }
2964+ }
2965+ }
2966+ }
2967+ }
2968+
2969+ // Aggregate values
2970+ var aggFn ;
2971+ switch ( match [ 1 ] ) {
2972+ case 'min' :
2973+ aggFn = Math . min ;
2974+ break ;
2975+ case 'max' :
2976+ aggFn = Math . max ;
2977+ break ;
2978+ default :
2979+ aggFn = function ( a , b ) { return a + b ; } ;
2980+ }
2981+
2982+ ax . _categoriesValue = categoriesValue ;
2983+
2984+ var categoriesAggregatedValue = [ ] ;
2985+ for ( j = 0 ; j < categoriesValue . length ; j ++ ) {
2986+ categoriesAggregatedValue . push ( [
2987+ categoriesValue [ j ] [ 0 ] ,
2988+ Lib . aggNums ( aggFn , null , categoriesValue [ j ] [ 1 ] )
2989+ ] ) ;
2990+ }
2991+
2992+ // Sort by aggregated value
2993+ categoriesAggregatedValue . sort ( function ( a , b ) {
2994+ return a [ 1 ] - b [ 1 ] ;
2995+ } ) ;
2996+
2997+ ax . _categoriesAggregatedValue = categoriesAggregatedValue ;
2998+
2999+ // Set new category order
3000+ ax . _initialCategories = categoriesAggregatedValue . map ( function ( c ) {
3001+ return c [ 0 ] ;
3002+ } ) ;
3003+
3004+ // Reverse if descending
3005+ if ( match [ 2 ] === 'descending' ) {
3006+ ax . _initialCategories . reverse ( ) ;
3007+ }
3008+
3009+ // Sort all matching axes
3010+ affectedTraces = affectedTraces . concat ( ax . sortByInitialCategories ( ) ) ;
3011+ }
3012+ }
3013+ return affectedTraces ;
3014+ }
3015+
28503016function setupAxisCategories ( axList , fullData ) {
28513017 for ( var i = 0 ; i < axList . length ; i ++ ) {
28523018 var ax = axList [ i ] ;
0 commit comments