]> git.ipfire.org Git - thirdparty/Chart.js.git/commitdiff
Legend onClick callback supports arrow functions (#7410)
authorEvert Timberg <evert.timberg+github@gmail.com>
Sun, 24 May 2020 14:28:41 +0000 (10:28 -0400)
committerGitHub <noreply@github.com>
Sun, 24 May 2020 14:28:41 +0000 (10:28 -0400)
#7409 Legend callbacks support arrow functions
The `Legend` is no longer implicitly found through `this` and instead
passed as an explicit argument to the callback functions.

docs/docs/configuration/legend.md
docs/docs/general/interactions/events.md
docs/docs/getting-started/v3-migration.md
samples/charts/multi-series-pie.html
samples/charts/pie.html
src/controllers/controller.doughnut.js
src/controllers/controller.polarArea.js
src/core/core.controller.js
src/plugins/plugin.legend.js
test/specs/global.defaults.tests.js

index 2d7f0a6589e13ac3dd008bbc2b2e2a71e6ac4985..a0b9523c51fdcf447f63ab7f02cf67a8266594b4 100644 (file)
@@ -14,9 +14,9 @@ The legend configuration is passed into the `options.legend` namespace. The glob
 | `position` | `string` | `'top'` | Position of the legend. [more...](#position)
 | `align` | `string` | `'center'` | Alignment of the legend. [more...](#align)
 | `fullWidth` | `boolean` | `true` | Marks that this box should take the full width of the canvas (pushing down other boxes). This is unlikely to need to be changed in day-to-day use.
-| `onClick` | `function` | | A callback that is called when a click event is registered on a label item.
-| `onHover` | `function` | | A callback that is called when a 'mousemove' event is registered on top of a label item.
-| `onLeave` | `function` | | A callback that is called when a 'mousemove' event is registered outside of a previously hovered label item.
+| `onClick` | `function` | | A callback that is called when a click event is registered on a label item. Arguments: `[event, legendItem, legend]`.
+| `onHover` | `function` | | A callback that is called when a 'mousemove' event is registered on top of a label item. Arguments: `[event, legendItem, legend]`.
+| `onLeave` | `function` | | A callback that is called when a 'mousemove' event is registered outside of a previously hovered label item. Arguments: `[event, legendItem, legend]`.
 | `reverse` | `boolean` | `false` | Legend will show datasets in reverse order.
 | `labels` | `object` | | See the [Legend Label Configuration](#legend-label-configuration) section below.
 | `rtl` | `boolean` | | `true` for rendering the legends from right to left.
@@ -134,16 +134,16 @@ It can be common to want to trigger different behaviour when clicking an item in
 The default legend click handler is:
 
 ```javascript
-function(e, legendItem) {
-    var index = legendItem.datasetIndex;
-    var ci = this.chart;
-    var meta = ci.getDatasetMeta(index);
-
-    // See controller.isDatasetVisible comment
-    meta.hidden = meta.hidden === null ? !ci.data.datasets[index].hidden : null;
-
-    // We hid a dataset ... rerender the chart
-    ci.update();
+function(e, legendItem, legend) {
+    const index = legendItem.datasetIndex;
+    const ci = legend.chart;
+    if (ci.isDatasetVisible(index)) {
+        ci.hide(index);
+        legendItem.hidden = true;
+    } else {
+        ci.show(index);
+        legendItem.hidden = false;
+    }
 }
 ```
 
@@ -151,14 +151,14 @@ Lets say we wanted instead to link the display of the first two datasets. We cou
 
 ```javascript
 var defaultLegendClickHandler = Chart.defaults.legend.onClick;
-var newLegendClickHandler = function (e, legendItem) {
+var newLegendClickHandler = function (e, legendItem, legend) {
     var index = legendItem.datasetIndex;
 
     if (index > 1) {
         // Do the original logic
         defaultLegendClickHandler(e, legendItem);
     } else {
-        let ci = this.chart;
+        let ci = legend.chart;
         [
             ci.getDatasetMeta(0),
             ci.getDatasetMeta(1)
index a59c20726db6b8338896029557ac338e11e9300e..b7a6cb1674e54cc6a04903188be5c6e592f8f302 100644 (file)
@@ -7,8 +7,8 @@ The following properties define how the chart interacts with events.
 | Name | Type | Default | Description
 | ---- | ---- | ------- | -----------
 | `events` | `string[]` | `['mousemove', 'mouseout', 'click', 'touchstart', 'touchmove']` | The `events` option defines the browser events that the chart should listen to for tooltips and hovering. [more...](#event-option)
-| `onHover` | `function` | `null` | Called when any of the events fire. Called in the context of the chart and passed the event and an array of active elements (bars, points, etc).
-| `onClick` | `function` | `null` | Called if the event is of type `'mouseup'` or `'click'`. Called in the context of the chart and passed the event and an array of active elements.
+| `onHover` | `function` | `null` | Called when any of the events fire. Passed the event, an array of active elements (bars, points, etc), and the chart.
+| `onClick` | `function` | `null` | Called if the event is of type `'mouseup'` or `'click'`. Passed the event, an array of active elements, and the chart.
 
 ## Event Option
 For example, to have the chart only respond to click events, you could do:
index fd70ab59c1dbad0d3cfcb61f81f4f0df048364ae..a1de622e1a774c9335fd614eb47dd50953f891eb 100644 (file)
@@ -157,6 +157,7 @@ Animation system was completely rewritten in Chart.js v3. Each property can now
 * `{mode: 'single'}` was replaced with `{mode: 'nearest', intersect: true}`
 * `modes['X-axis']` was replaced with `{mode: 'index', intersect: false}`
 * `options.onClick` is now limited to the chart area
+* `options.onClick` and `options.onHover` now receive the `chart` instance as a 3rd argument
 
 #### Ticks
 
@@ -279,6 +280,8 @@ The following properties and methods were removed:
 
 * `IPlugin.afterScaleUpdate`. Use `afterLayout` instead
 * `Legend.margins` is now private
+* Legend `onClick`, `onHover`, and `onLeave` options now receive the legend as the 3rd argument in addition to implicitly via `this`
+* Legend `onClick`, `onHover`, and `onLeave` options now receive a wrapped `event` as the first parameter. The previous first parameter value is accessible via `event.native`.
 * `Title.margins` is now private
 * The tooltip item's `x` and `y` attributes were removed. Use `datasetIndex` and `index` to get the element and any corresponding data from it
 
index 4a61c420b177c6c56ce591ef51b46beaba6ec9b3..546676094ad516c6075678022d5c8ceefe5d7c84 100644 (file)
                                                        return labels;
                                                }
                                        },
-                                       onClick: function(mouseEvent, legendItem) {
+                                       onClick: function(mouseEvent, legendItem, legend) {
                                                // toggle the visibility of the dataset from what it currently is
-                                               this.chart.getDatasetMeta(
+                                               legend.chart.getDatasetMeta(
                                                        legendItem.datasetIndex
-                                               ).hidden = this.chart.isDatasetVisible(legendItem.datasetIndex);
-                                               this.chart.update();
+                                               ).hidden = legend.chart.isDatasetVisible(legendItem.datasetIndex);
+                                               legend.chart.update();
                                        }
                                },
                                tooltips: {
index b994c338a85a412bb0190352f85c8f160454f18f..7dbc148e36a335f954741a9e81cfc057c54ddfd8 100644 (file)
@@ -75,7 +75,7 @@
                                label: 'New dataset ' + config.data.datasets.length,
                        };
 
-                       for (var index = 0; index < config.data.labels.length; ++index) {
+                       for (var index = 0; index < 10; ++index) {
                                newDataset.data.push(randomScalingFactor());
 
                                var colorName = colorNames[index % colorNames.length];
index 361322de960179b9b31487b6e69646c1eea752d4..2d0c5468c76332453d5d02d776e8a9ab63448884 100644 (file)
@@ -47,9 +47,9 @@ defaults.set('doughnut', {
                        }
                },
 
-               onClick(e, legendItem) {
-                       this.chart.toggleDataVisibility(legendItem.index);
-                       this.chart.update();
+               onClick(e, legendItem, legend) {
+                       legend.chart.toggleDataVisibility(legendItem.index);
+                       legend.chart.update();
                }
        },
 
index 3d633160234779ad3408a00e02c1a4933eb7c5e3..c44cec8cbc2d44a8cee2c5265abfac3cadfb4e26 100644 (file)
@@ -55,9 +55,9 @@ defaults.set('polarArea', {
                        }
                },
 
-               onClick(e, legendItem) {
-                       this.chart.toggleDataVisibility(legendItem.index);
-                       this.chart.update();
+               onClick(e, legendItem, legend) {
+                       legend.chart.toggleDataVisibility(legendItem.index);
+                       legend.chart.update();
                }
        },
 
index cdcc1d7af02e4838448e874f9b280c94d2f8a5d4..220fa198fec7299962072d731d1e9c0be58bbb35 100644 (file)
@@ -1108,12 +1108,12 @@ export default class Chart {
 
                // Invoke onHover hook
                // Need to call with native event here to not break backwards compatibility
-               callCallback(options.onHover || options.hover.onHover, [e.native, me.active], me);
+               callCallback(options.onHover || options.hover.onHover, [e.native, me.active, me], me);
 
                if (e.type === 'mouseup' || e.type === 'click') {
-                       if (options.onClick && _isPointInArea(e, me.chartArea)) {
+                       if (_isPointInArea(e, me.chartArea)) {
                                // Use e.native here for backwards compatibility
-                               options.onClick.call(me, e.native, me.active);
+                               callCallback(options.onClick, [e, me.active, me], me);
                        }
                }
 
index 79f61db6e50b44343fc426e0f01adc77d9f03434..0faddddd96b7d4dcb1e5bb0b379314355608ff87 100644 (file)
@@ -19,9 +19,9 @@ defaults.set('legend', {
        weight: 1000,
 
        // a callback that will handle
-       onClick(e, legendItem) {
+       onClick(e, legendItem, legend) {
                const index = legendItem.datasetIndex;
-               const ci = this.chart;
+               const ci = legend.chart;
                if (ci.isDatasetVisible(index)) {
                        ci.hide(index);
                        legendItem.hidden = true;
@@ -659,21 +659,19 @@ export class Legend extends Element {
                const hoveredItem = me._getLegendItemAt(e.x, e.y);
 
                if (type === 'click') {
-                       if (hoveredItem && opts.onClick) {
-                               // use e.native for backwards compatibility
-                               opts.onClick.call(me, e.native, hoveredItem);
+                       if (hoveredItem) {
+                               call(opts.onClick, [e, hoveredItem, me], me);
                        }
                } else {
                        if (opts.onLeave && hoveredItem !== me._hoveredItem) {
                                if (me._hoveredItem) {
-                                       opts.onLeave.call(me, e.native, me._hoveredItem);
+                                       call(opts.onLeave, [e, me._hoveredItem, me], me);
                                }
                                me._hoveredItem = hoveredItem;
                        }
 
-                       if (opts.onHover && hoveredItem) {
-                               // use e.native for backwards compatibility
-                               opts.onHover.call(me, e.native, hoveredItem);
+                       if (hoveredItem) {
+                               call(opts.onHover, [e, hoveredItem, me], me);
                        }
                }
        }
index 30652473ae7aec21c5b21e9398aa6d1688dccf76..ccbbea180a504001513d6afc85fcd8dc5ca76b6c 100644 (file)
@@ -147,12 +147,12 @@ describe('Default Configs', function() {
                        spyOn(chart, 'update').and.callThrough();
 
                        var legendItem = chart.legend.legendItems[0];
-                       config.legend.onClick.call(chart.legend, null, legendItem);
+                       config.legend.onClick(null, legendItem, chart.legend);
 
                        expect(chart.getDataVisibility(0)).toBe(false);
                        expect(chart.update).toHaveBeenCalled();
 
-                       config.legend.onClick.call(chart.legend, null, legendItem);
+                       config.legend.onClick(null, legendItem, chart.legend);
                        expect(chart.getDataVisibility(0)).toBe(true);
                });
        });
@@ -243,12 +243,12 @@ describe('Default Configs', function() {
                        spyOn(chart, 'update').and.callThrough();
 
                        var legendItem = chart.legend.legendItems[0];
-                       config.legend.onClick.call(chart.legend, null, legendItem);
+                       config.legend.onClick(null, legendItem, chart.legend);
 
                        expect(chart.getDataVisibility(0)).toBe(false);
                        expect(chart.update).toHaveBeenCalled();
 
-                       config.legend.onClick.call(chart.legend, null, legendItem);
+                       config.legend.onClick(null, legendItem, chart.legend);
                        expect(chart.getDataVisibility(0)).toBe(true);
                });
        });