@@ -40,7 +40,7 @@ sqlpage_chart = (() => {
40
40
/**
41
41
* Aligns series data points by their x-axis categories, ensuring all series have data points
42
42
* for each unique category. Missing values are filled with zeros.
43
- * Categories are ordered by their first appearance across all series .
43
+ * Categories are ordered by their name .
44
44
*
45
45
* @example
46
46
* // Input series:
@@ -49,31 +49,36 @@ sqlpage_chart = (() => {
49
49
* { name: "B", data: [{x: "X1", y: 25}, {x: "X2", y: 20}] }
50
50
* ];
51
51
*
52
- * // Output after align_categories (orderedCategories will be ["X2", "X3 ", "X1 "]):
52
+ * // Output after align_categories (orderedCategories will be ["X1","X2 ", "X3 "]):
53
53
* // [
54
- * // { name: "A", data: [{x: "X2 ", y: 10 }, {x: "X3 ", y: 30 }, {x: "X1 ", y: 0 }] },
55
- * // { name: "B", data: [{x: "X2 ", y: 20 }, {x: "X3 ", y: 0 }, {x: "X1 ", y: 25 }] }
54
+ * // { name: "A", data: [{x: "X1 ", y: 0 }, {x: "X2 ", y: 10 }, {x: "X3 ", y: 30 }] },
55
+ * // { name: "B", data: [{x: "X1 ", y: 25 }, {x: "X2 ", y: 20 }, {x: "X3 ", y: 0 }] }
56
56
* // ]
57
57
*
58
58
* @param {(Series[string])[] } series - Array of series objects, each containing name and data points
59
59
* @returns {Series[string][] } Aligned series with consistent categories across all series
60
60
*/
61
61
function align_categories ( series ) {
62
62
const categoriesSet = new Set ( ) ;
63
- const pointers = series . map ( ( _ ) => 0 ) ;
63
+ const pointers = series . map ( ( _ ) => 0 ) ; // Index of current data point in each series
64
+ const x_at = ( series_idx ) =>
65
+ series [ series_idx ] . data [ pointers [ series_idx ] ] . x ;
66
+ let series_idxs = Array . from ( { length : series . length } , ( _ , i ) => i ) ;
64
67
while ( true ) {
65
- const series_idxs = series . flatMap ( ( series , i ) =>
66
- pointers [ i ] < series . data . length ? [ i ] : [ ] ,
68
+ // indices of series that have data points left
69
+ series_idxs = series_idxs . filter (
70
+ ( i ) => pointers [ i ] < series [ i ] . data . length ,
67
71
) ;
68
72
if ( series_idxs . length === 0 ) break ;
69
- const min_ptr = Math . min ( ...series_idxs . map ( ( i ) => pointers [ i ] ) ) ;
70
- const min_series_idx =
71
- series_idxs . find ( ( i ) => pointers [ i ] === min_ptr ) | 0 ;
72
- const min_series = series [ min_series_idx ] ;
73
- const min_point = min_series . data [ min_ptr ] ;
74
- const new_category = min_point . x ;
73
+
74
+ let idx_of_xmin = series_idxs [ 0 ] ;
75
+ for ( const series_idx of series_idxs ) {
76
+ if ( x_at ( series_idx ) < x_at ( idx_of_xmin ) ) idx_of_xmin = series_idx ;
77
+ }
78
+
79
+ const new_category = x_at ( idx_of_xmin ) ;
75
80
if ( ! categoriesSet . has ( new_category ) ) categoriesSet . add ( new_category ) ;
76
- pointers [ min_series_idx ] ++ ;
81
+ pointers [ idx_of_xmin ] ++ ;
77
82
}
78
83
// Create a map of category -> value for each series and rebuild
79
84
return series . map ( ( s ) => {
@@ -164,7 +169,8 @@ sqlpage_chart = (() => {
164
169
: data . type === "pie"
165
170
? ( value , { seriesIndex, w } ) =>
166
171
`${ w . config . labels [ seriesIndex ] } : ${ value . toFixed ( ) } %`
167
- : ( value , { seriesIndex, w } ) => value ?. toLocaleString ?. ( ) || value ,
172
+ : ( value , { seriesIndex, w } ) =>
173
+ value ?. toLocaleString ?. ( ) || value ,
168
174
} ,
169
175
fill : {
170
176
type : data . type === "area" ? "gradient" : "solid" ,
0 commit comments