Chartjs-Chartjs listening mouseup breaks legend click

1👍

All plugins can be configured with events option as array of events types to catch.

For your use case, I think it could be:

options: {
   // mouseup must be add to chart
   events: ['mousemove', 'mouseout', 'click', 'touchstart', 'touchmove', 'mouseup'],
   plugins: {
     legend: {
       events: ['mouseup'] // only mouseup is caught and managed by legend as click
     }
   }      
}

If you want to catch only click to legend (and ignore mouseup):

options: {
   // mouseup must be add to chart
   events: ['mousemove', 'mouseout', 'click', 'touchstart', 'touchmove', 'mouseup'],
   plugins: {
     legend: {
       events: ['click'] // only click is caught and managed by legend as click
     }
   }      
}

0👍

@user2057925 is right, and one should configure the events property as he says. In particular, without some of those events one will lose the tooltip. Indeed, I think you found a bug. Just in terms of a short explanation, there are two different problems exposed by your code

Problem 1 (strange behavior)

If options.plugins.legend.onClick is defined,
then the default ‘click’ behavior is not triggered (this
is reasonable), nor is there a documented way to do so (not so reasonable).

The solution is to search for the original onClick method
in the Chart object, using the source code:

onClick: (...args) => {
    console.log('legend click');
    
    // if using modules, import Legend with Chart
    // import {Chart, registrables, Legend} from './chart.js'
    Legend.defaults.onClick(...args);
    // // if using standard script tag with the chartjs umd just:
    // Chart.Legend.defaults.onClick(...args);
}

jsFiddle

Problem 2 (bug)

If the chart’s options.events contains both mouseup and click, then the click event is trigger twice, anywhere on
the chart, irrespective to the existence of plugins (one may comment the whole plugin section on OP’s code).

This is apparent for the legend for which the default behavior
is that the second click cancels the
effect of the first (hides and then shows the clicked
dataset) jsFiddle.

This is a bug, also in my opinion.

It is due to the function
_isClickEvent(e)
that returns true if e.type === 'mouseup'. The function is
called in the method
Chart#_handleEvent,
and although this is the only place it is called in the
chart.js main code, it is possible there are good reasons
for this behavior; but then the _handleEvent should take
into account that the user declared both event types in
options.events.

This behavior is not related to the plugins, however, the OP
found already the best solution: if the plugin handler returns false the situation is saved; this is the documented behavior, see
Plugin#beforeEvent:

If any plugin returns false, the event will be discarded.

although it does seem somewhat arbitrary — a plugin cancelling
an event globally might impact another plugin, messing
with a much-needed separation in design (a plugin implementer
can’t possibly know what other plugins are added
by a user).

I would not recommend the other obvious solution, to just exclude click from the options.events when one has already mouseup (since click will be triggered by mouseup anyway) — it’s difficult to take into consideration all possible interactions with all the components of the library.

Leave a comment