Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Legend onClick callback supports arrow functions #7410

Merged
merged 4 commits into from May 24, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
30 changes: 15 additions & 15 deletions docs/docs/configuration/legend.md
Expand Up @@ -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.
Expand Down Expand Up @@ -134,31 +134,31 @@ 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;
}
}
```

Lets say we wanted instead to link the display of the first two datasets. We could change the click handler accordingly.

```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)
Expand Down
4 changes: 2 additions & 2 deletions docs/docs/general/interactions/events.md
Expand Up @@ -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:
Expand Down
3 changes: 3 additions & 0 deletions docs/docs/getting-started/v3-migration.md
Expand Up @@ -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

Expand Down Expand Up @@ -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

Expand Down
8 changes: 4 additions & 4 deletions samples/charts/multi-series-pie.html
Expand Up @@ -71,12 +71,12 @@
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: {
Expand Down
2 changes: 1 addition & 1 deletion samples/charts/pie.html
Expand Up @@ -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];
Expand Down
6 changes: 3 additions & 3 deletions src/controllers/controller.doughnut.js
Expand Up @@ -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();
}
},

Expand Down
6 changes: 3 additions & 3 deletions src/controllers/controller.polarArea.js
Expand Up @@ -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();
}
},

Expand Down
6 changes: 3 additions & 3 deletions src/core/core.controller.js
Expand Up @@ -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);
}
}

Expand Down
16 changes: 7 additions & 9 deletions src/plugins/plugin.legend.js
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
}
}
}
Expand Down
8 changes: 4 additions & 4 deletions test/specs/global.defaults.tests.js
Expand Up @@ -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);
});
});
Expand Down Expand Up @@ -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);
});
});
Expand Down