1
- async function renderChart ( ) {
2
- try {
3
- const response = await fetch ( 'last_week_tracks.json' ) ;
4
- const tracks = await response . json ( ) ;
5
-
6
- const playCounts = { } ;
7
- const labels = [ ] ;
1
+ // Single global chart instance
2
+ let listeningChart = null ;
8
3
9
-
10
- tracks . forEach ( track => {
11
- const trackDate = new Date ( track . date [ '#text' ] ) . toLocaleDateString ( ) ;
12
- playCounts [ trackDate ] = ( playCounts [ trackDate ] || 0 ) + 1 ;
13
- } ) ;
4
+ // Function to create or update the chart
5
+ async function initializeChart ( ) {
6
+ try {
7
+ // Get canvas context
8
+ const canvas = document . getElementById ( 'listening-chart' ) ;
9
+ if ( ! canvas ) {
10
+ console . error ( 'Canvas element not found' ) ;
11
+ return ;
12
+ }
14
13
15
-
16
- for ( const [ date , count ] of Object . entries ( playCounts ) ) {
17
- labels . push ( date ) ;
14
+ // Destroy existing chart if it exists
15
+ if ( listeningChart instanceof Chart ) {
16
+ listeningChart . destroy ( ) ;
18
17
}
19
18
20
- const data = {
21
- labels : labels ,
22
- datasets : [ {
23
- label : 'Plays Over the Last Week' ,
24
- data : Object . values ( playCounts ) ,
25
- backgroundColor : 'rgba(142, 141, 190, 0.0)' ,
26
- borderColor : 'rgba(142, 141, 190, 1)' ,
27
- borderWidth : 2 ,
28
- fill : true ,
29
- pointRadius : 0 ,
30
- tension : 0.3
31
- } ]
32
- } ;
19
+ // Fetch new data
20
+ const response = await fetch ( 'weekly_chart.json' ) ;
21
+ if ( ! response . ok ) {
22
+ throw new Error ( `Failed to fetch chart data: ${ response . status } ${ response . statusText } ` ) ;
23
+ }
24
+ const chartData = await response . json ( ) ;
25
+ console . log ( 'Chart data:' , chartData ) ;
33
26
34
- const config = {
35
- type : 'line' ,
36
- data : data ,
27
+ // Chart configuration
28
+ const chartConfig = {
29
+ type : 'line' ,
30
+ data : {
31
+ labels : chartData . data . map ( d => d . day ) ,
32
+ datasets : [ {
33
+ label : 'Tracks Played' ,
34
+ data : chartData . data . map ( d => ( {
35
+ x : d . day ,
36
+ y : d . count ,
37
+ date : d . date // Store date for tooltip
38
+ } ) ) ,
39
+ backgroundColor : 'rgba(142, 141, 190, 0.0)' ,
40
+ borderColor : 'rgba(142, 141, 190, 1)' ,
41
+ borderWidth : 2 ,
42
+ tension : 0.4 ,
43
+ fill : true ,
44
+ pointRadius : 0
45
+ } ]
46
+ } ,
37
47
options : {
38
48
responsive : true ,
39
- maintainAspectRatio : false ,
49
+ maintainAspectRatio : false ,
40
50
scales : {
41
51
y : {
42
52
beginAtZero : true ,
43
53
grid : {
44
- display : false
54
+ display : false
55
+ } ,
56
+ ticks : {
57
+ stepSize : 20 ,
58
+ font : {
59
+ size : 10
60
+ } ,
61
+ color : '#666'
45
62
}
46
63
} ,
47
64
x : {
48
65
grid : {
49
- display : false
66
+ display : false
50
67
} ,
51
- reverse : true
68
+ ticks : {
69
+ font : {
70
+ size : 10
71
+ } ,
72
+ color : '#666'
73
+ }
52
74
}
53
75
} ,
54
76
plugins : {
55
77
legend : {
56
- display : false
78
+ display : false
57
79
} ,
58
80
tooltip : {
59
- enabled : true
81
+ enabled : true ,
82
+ mode : 'index' ,
83
+ intersect : false ,
84
+ callbacks : {
85
+ label : function ( context ) {
86
+ const point = context . raw ;
87
+ const date = new Date ( point . date ) . toLocaleDateString ( 'en-US' , {
88
+ month : 'short' ,
89
+ day : 'numeric'
90
+ } ) ;
91
+ return `${ point . y } tracks on ${ date } ` ;
92
+ }
93
+ }
60
94
}
61
95
}
62
96
}
63
97
} ;
64
98
65
- const playsChart = new Chart (
66
- document . getElementById ( 'listening-chart' ) ,
67
- config
68
- ) ;
69
-
70
- // Add hover effects
71
- const musicBox = document . getElementById ( 'box-lastfm' ) ;
72
-
73
- musicBox . addEventListener ( 'mouseenter' , ( ) => {
74
- playsChart . data . datasets [ 0 ] . backgroundColor = 'rgba(142, 141, 190, 0.2)' ;
75
- playsChart . update ( 'none' ) ; // Use 'none' for smoother transition
76
- } ) ;
77
-
78
- musicBox . addEventListener ( 'mouseleave' , ( ) => {
79
- playsChart . data . datasets [ 0 ] . backgroundColor = 'rgba(142, 141, 190, 0.0)' ;
80
- playsChart . update ( 'none' ) ; // Use 'none' for smoother transition
81
- } ) ;
82
-
99
+ // Create new chart
100
+ listeningChart = new Chart ( canvas , chartConfig ) ;
101
+ console . log ( 'Chart initialized:' , listeningChart ) ;
102
+
103
+ // Setup hover effects
104
+ setupHoverEffects ( ) ;
105
+
83
106
} catch ( error ) {
84
- console . error ( 'Error rendering chart:' , error ) ;
107
+ console . error ( 'Failed to initialize chart:' , error ) ;
85
108
}
86
109
}
87
110
88
- renderChart ( ) ;
111
+ // Function to handle hover effects
112
+ function setupHoverEffects ( ) {
113
+ const musicBox = document . getElementById ( 'box-lastfm' ) ;
114
+ if ( ! musicBox ) {
115
+ console . error ( 'Music box element not found' ) ;
116
+ return ;
117
+ }
118
+
119
+ // Add mouseenter event
120
+ musicBox . addEventListener ( 'mouseenter' , ( ) => {
121
+ if ( listeningChart ) {
122
+ listeningChart . data . datasets [ 0 ] . backgroundColor = 'rgba(142, 141, 190, 0.2)' ;
123
+ listeningChart . update ( 'none' ) ;
124
+ }
125
+ } ) ;
126
+
127
+ // Add mouseleave event
128
+ musicBox . addEventListener ( 'mouseleave' , ( ) => {
129
+ if ( listeningChart ) {
130
+ listeningChart . data . datasets [ 0 ] . backgroundColor = 'rgba(142, 141, 190, 0.0)' ;
131
+ listeningChart . update ( 'none' ) ;
132
+ }
133
+ } ) ;
134
+ }
135
+
136
+ // Initialize chart when DOM is ready
137
+ if ( document . readyState === 'loading' ) {
138
+ document . addEventListener ( 'DOMContentLoaded' , initializeChart ) ;
139
+ } else {
140
+ initializeChart ( ) ;
141
+ }
142
+
143
+ // Export for external use
144
+ window . updateChart = initializeChart ;
0 commit comments