@@ -18,6 +18,9 @@ let tags_score_chart_instance = null;
1818let week_score_chart_instance = null ;
1919let month_score_chart_instance = null ;
2020
21+ let isCardPinned = false ;
22+ let hoverDelay = false ;
23+
2124
2225
2326
@@ -63,17 +66,67 @@ function fill_missing_dates(data) {
6366async function create_mood_chart ( data , rollingAverage , displayAverage , displayYears ) {
6467 data = fill_missing_dates ( data ) ;
6568 const dates = data . map ( entry => entry . date ) ;
66- const rawScores = data . map ( entry => average ( entry . scores ) ) ;
69+
70+ let rawScores ;
71+ let minValue ;
72+ let maxValue ;
73+ if ( timeOption === "mood" ) {
74+ rawScores = data . map ( entry => average ( entry . scores ) ) ;
75+ minValue = 1 ;
76+ maxValue = 5 ;
77+ }
78+ else if ( timeOption === "words" ) { // number of words
79+ rawScores = data . map ( entry => {
80+ if ( ! entry || ! entry . notes ) { return null ; }
81+ const words = entry . notes
82+ . toLowerCase ( )
83+ . replace ( / [ ^ a - z A - Z 0 - 9 ] + / g, " " )
84+ . split ( / \s + / )
85+ . filter ( word => word . replace ( / [ ^ a - z A - Z ] / g, "" ) . length >= 3 ) ;
86+ return words . length ;
87+ } ) ;
88+ minValue = maximum ( rawScores ) ;
89+ maxValue = minimum ( rawScores ) ;
90+ }
91+ else if ( timeOption === "tags" ) { // number of tags
92+ rawScores = data . map ( entry => {
93+ if ( ! entry || ! entry . tags ) { return null ; }
94+ return entry . tags . reduce ( ( count , tag ) => {
95+ if ( ! Array . isArray ( tag . entries ) ) return count ;
96+ return count + tag . entries . length ;
97+ } , 0 ) ;
98+ } ) ;
99+ minValue = maximum ( rawScores ) ;
100+ maxValue = minimum ( rawScores ) ;
101+ }
67102
68103 const annotations = { } ;
69104 if ( displayAverage ) {
70105 annotations [ "mean" ] = {
71106 type : "line" ,
72107 mode : "horizontal" ,
73108 scaleID : "y" ,
74- value : average ( data . map ( entry => average ( entry . scores ) ) ) ,
109+ value : average ( rawScores . filter ( score => ( score !== null ) ) ) ,
75110 borderColor : "#ff4444" ,
76111 borderWidth : 2 ,
112+ label : {
113+ enabled : false ,
114+ content : `Mean: ${ average ( rawScores . filter ( score => ( score !== null ) ) ) . toFixed ( 2 ) } ` ,
115+ position : "top" ,
116+ backgroundColor : "rgba(0,0,0,0.6)" ,
117+ font : {
118+ size : 10 ,
119+ weight : "bold"
120+ }
121+ } ,
122+ enter ( ctx ) {
123+ ctx . element . options . label . enabled = true ;
124+ ctx . chart . draw ( ) ;
125+ } ,
126+ leave ( ctx ) {
127+ ctx . element . options . label . enabled = false ;
128+ ctx . chart . draw ( ) ;
129+ }
77130 }
78131 }
79132
@@ -146,11 +199,13 @@ async function create_mood_chart(data, rollingAverage, displayAverage, displayYe
146199 scales : {
147200 y : {
148201 beginAtZero : true ,
149- min : 1 ,
150- max : 5
202+ min : minValue ,
203+ max : maxValue
151204 }
152205 } ,
153- onClick : ( event , elements ) => {
206+ onClick : async ( event , chartElement ) => {
207+ // Legacy function to scroll to Pixel card
208+ /*
154209 const points = mood_chart_instance.getElementsAtEventForMode(event, 'nearest', { intersect: true }, true);
155210 if (points.length > 0) {
156211 const pointIndex = points[0].index;
@@ -159,6 +214,15 @@ async function create_mood_chart(data, rollingAverage, displayAverage, displayYe
159214
160215 show_pixel_card(dateText, scroll=true);
161216 }
217+ */
218+ display_floating_card ( data , chartElement , pinCard = true ) ;
219+
220+ hoverDelay = true ;
221+ setTimeout ( ( ) => { hoverDelay = false } , 1000 ) ;
222+ } ,
223+ onHover : async function ( event , chartElement ) {
224+ if ( ! showPixelCard ) { return ; }
225+ display_floating_card ( data , chartElement ) ;
162226 } ,
163227 plugins : {
164228 legend : {
@@ -351,4 +415,32 @@ async function create_month_chart(colorsByMonth) {
351415 }
352416 }
353417 } ) ;
354- }
418+ }
419+
420+
421+
422+
423+ canvas_mood . addEventListener ( "mousemove" , async ( e ) => {
424+ if ( isCardPinned || hoverDelay ) { return ; }
425+ const x = e . clientX + window . scrollX ;
426+ const y = e . clientY + window . scrollY ;
427+ const margin = - 10 ;
428+
429+ container_floating_card . style . top = `${ y + margin } px` ;
430+ if ( 2 * x > window . innerWidth ) {
431+ container_floating_card . style . right = `${ window . innerWidth - x + margin } px` ;
432+ container_floating_card . style . left = "auto" ;
433+ }
434+ else {
435+ container_floating_card . style . left = `${ x + margin } px` ;
436+ container_floating_card . style . right = "auto" ;
437+ }
438+ } ) ;
439+
440+
441+ container_floating_card . addEventListener ( "mouseleave" , ( ) => {
442+ if ( ! hoverDelay ) {
443+ container_floating_card . style . display = "none" ;
444+ container_floating_card . innerHTML = "" ;
445+ }
446+ } ) ;
0 commit comments