@@ -78,12 +78,7 @@ async function create_mood_chart(data, rollingAverage, displayAverage, displayYe
7878 else if ( timeOption === "words" ) { // number of words
7979 rawScores = data . map ( entry => {
8080 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 ;
81+ return entry . notes . split ( / \s + / ) . length ;
8782 } ) ;
8883 minValue = maximum ( rawScores ) ;
8984 maxValue = minimum ( rawScores ) ;
@@ -241,11 +236,13 @@ async function create_tag_frequency_chart(isPercentage, maxTags) {
241236 const tagCounts = tag_stats . counts ;
242237 const nbPixels = tag_stats . totalPixels ;
243238 const sortedTags = Object . entries ( tagCounts )
239+ . filter ( tag => ( tagCategory === "All" ) || ( tagCategory === tag_stats . categories [ tag [ 0 ] ] ) )
244240 . sort ( ( [ , a ] , [ , b ] ) => b - a )
245241 . slice ( 0 , maxTags ) ;
246242
247243 if ( sortedTags . length > 0 ) {
248244 if ( tags_frequency_chart_instance ) {
245+ detach_chart_hover ( tags_frequency_chart_instance ) ;
249246 tags_frequency_chart_instance . destroy ( ) ;
250247 }
251248
@@ -279,12 +276,14 @@ async function create_tag_frequency_chart(isPercentage, maxTags) {
279276async function create_tag_score_chart ( maxTags ) {
280277 const tagScores = tag_stats . scores ;
281278 const averages = Object . entries ( tagScores )
279+ . filter ( tag => ( tagCategory === "All" ) || ( tagCategory === tag_stats . categories [ tag [ 0 ] ] ) )
282280 . map ( ( [ tag , { total, count } ] ) => ( [ tag , total / count ] ) )
283281 . sort ( ( [ , a ] , [ , b ] ) => b - a )
284282 . slice ( 0 , maxTags ) ;
285283
286284 if ( averages . length > 0 ) {
287285 if ( tags_score_chart_instance ) {
286+ detach_chart_hover ( tags_score_chart_instance ) ;
288287 tags_score_chart_instance . destroy ( ) ;
289288 }
290289
@@ -321,6 +320,72 @@ async function create_tag_score_chart(maxTags) {
321320} ;
322321
323322
323+ function sync_tag_hover ( sourceChart , targetChart ) {
324+ function remove_tooltip_target ( ) {
325+ targetChart . setActiveElements ( [ ] ) ;
326+ targetChart . tooltip . setActiveElements ( [ ] , { } ) ;
327+ targetChart . draw ( ) ;
328+ }
329+
330+ function set_tooltip_target ( e ) {
331+ // check if sourceChart still exists
332+ if ( ! sourceChart ?. canvas ) {
333+ return ;
334+ }
335+ const tooltipActive = sourceChart . tooltip . getActiveElements ( ) ;
336+ const activePoints = sourceChart . getElementsAtEventForMode ( e , "index" , { intersect : false , axis : "y" } , false ) ;
337+ if ( ( tooltipActive . length === 0 ) || ( activePoints . length === 0 ) ) {
338+ remove_tooltip_target ( ) ;
339+ return ;
340+ }
341+
342+ const index = activePoints [ 0 ] . index ;
343+ const label = sourceChart . data . labels [ index ] ;
344+ const targetIndex = targetChart . data . labels . indexOf ( label ) ;
345+ if ( targetIndex === - 1 ) { return ; }
346+
347+ const canvasRect = targetChart . canvas . getBoundingClientRect ( ) ;
348+ const sourceRect = sourceChart . canvas . getBoundingClientRect ( ) ;
349+ const relativeY = e . clientY - sourceRect . top ;
350+ const centerX = canvasRect . left + canvasRect . width / 2 ;
351+
352+ targetChart . setActiveElements ( [ { datasetIndex : 0 , index : targetIndex } ] ) ;
353+ targetChart . tooltip . setActiveElements (
354+ [ { datasetIndex : 0 , index : targetIndex } ] ,
355+ { x : centerX , y : canvasRect . top + relativeY }
356+ ) ;
357+ targetChart . update ( ) ;
358+ }
359+
360+ sourceChart . canvas . addEventListener ( "mousemove" , set_tooltip_target ) ;
361+ sourceChart . canvas . addEventListener ( "mouseleave" , remove_tooltip_target ) ;
362+
363+ // Add hover handlers to the source chart
364+ sourceChart . _hoverHandlers = {
365+ mousemove : set_tooltip_target ,
366+ mouseleave : remove_tooltip_target
367+ } ;
368+ }
369+
370+
371+ function detach_chart_hover ( chartInstance ) {
372+ const handlers = chartInstance . _hoverHandlers ;
373+ if ( handlers ) {
374+ chartInstance . canvas . removeEventListener ( "mousemove" , handlers . mousemove ) ;
375+ chartInstance . canvas . removeEventListener ( "mouseleave" , handlers . mouseleave ) ;
376+ delete chartInstance . _hoverHandlers ;
377+ }
378+ }
379+
380+
381+ async function sync_tag_charts_hover ( ) {
382+ if ( tags_frequency_chart_instance && tags_score_chart_instance ) {
383+ sync_tag_hover ( tags_frequency_chart_instance , tags_score_chart_instance ) ;
384+ sync_tag_hover ( tags_score_chart_instance , tags_frequency_chart_instance ) ;
385+ }
386+ }
387+
388+
324389async function create_weekday_chart ( firstDayOfWeek ) {
325390 let daysOfWeek = [ "Sunday" , "Monday" , "Tuesday" , "Wednesday" , "Thursday" , "Friday" , "Saturday" ] ;
326391 daysOfWeek = daysOfWeek . slice ( firstDayOfWeek ) . concat ( daysOfWeek . slice ( 0 , firstDayOfWeek ) ) ;
0 commit comments