@@ -39,36 +39,48 @@ sqlpage_chart = (() => {
39
39
40
40
/**
41
41
* Aligns series data points by their x-axis categories, ensuring all series have data points
42
- * for each unique category. Missing values are filled with zeros. Categories are sorted.
42
+ * for each unique category. Missing values are filled with zeros.
43
+ * Categories are ordered by their first appearance across all series.
43
44
*
44
45
* @example
45
46
* // Input series:
46
47
* const series = [
47
- * { name: "A", data: [{x: "Jan ", y: 10}, {x: "Mar ", y: 30}] },
48
- * { name: "B", data: [{x: "Jan ", y: 20 }, {x: "Feb ", y: 25 }] }
48
+ * { name: "A", data: [{x: "X2 ", y: 10}, {x: "X3 ", y: 30}] },
49
+ * { name: "B", data: [{x: "X1 ", y: 25 }, {x: "X2 ", y: 20 }] }
49
50
* ];
50
51
*
51
- * // Output after align_categories:
52
+ * // Output after align_categories (orderedCategories will be ["X2", "X3", "X1"]) :
52
53
* // [
53
- * // { name: "A", data: [{x: "Feb ", y: 0 }, {x: "Jan ", y: 10 }, {x: "Mar ", y: 30 }] },
54
- * // { name: "B", data: [{x: "Feb ", y: 25 }, {x: "Jan ", y: 20 }, {x: "Mar ", y: 0 }] }
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 }] }
55
56
* // ]
56
57
*
57
- * @param {Series[string][] } series - Array of series objects, each containing name and data points
58
+ * @param {( Series[string]) [] } series - Array of series objects, each containing name and data points
58
59
* @returns {Series[string][] } Aligned series with consistent categories across all series
59
60
*/
60
61
function align_categories ( series ) {
61
- // Collect all unique categories
62
- const categories = new Set ( series . flatMap ( ( s ) => s . data . map ( ( p ) => p . x ) ) ) ;
63
- const sortedCategories = Array . from ( categories ) . sort ( ) ;
64
-
65
- // Create a map of category -> value for each series
62
+ const categoriesSet = new Set ( ) ;
63
+ const pointers = series . map ( ( _ ) => 0 ) ;
64
+ while ( true ) {
65
+ const series_idxs = series . flatMap ( ( series , i ) =>
66
+ pointers [ i ] < series . data . length ? [ i ] : [ ] ,
67
+ ) ;
68
+ 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 ;
75
+ if ( ! categoriesSet . has ( new_category ) ) categoriesSet . add ( new_category ) ;
76
+ pointers [ min_series_idx ] ++ ;
77
+ }
78
+ // Create a map of category -> value for each series and rebuild
66
79
return series . map ( ( s ) => {
67
80
const valueMap = new Map ( s . data . map ( ( point ) => [ point . x , point . y ] ) ) ;
68
-
69
81
return {
70
82
name : s . name ,
71
- data : sortedCategories . map ( ( category ) => ( {
83
+ data : Array . from ( categoriesSet , ( category ) => ( {
72
84
x : category ,
73
85
y : valueMap . get ( category ) || 0 ,
74
86
} ) ) ,
@@ -116,7 +128,7 @@ sqlpage_chart = (() => {
116
128
if ( data . type === "pie" ) {
117
129
labels = data . points . map ( ( [ name , x , y ] ) => x || name ) ;
118
130
series = data . points . map ( ( [ name , x , y ] ) => y ) ;
119
- } else if ( categories && data . type === "bar" )
131
+ } else if ( categories && data . type === "bar" && series . length > 1 )
120
132
series = align_categories ( series ) ;
121
133
122
134
const chart_type = data . type || "line" ;
0 commit comments