Skip to content

Commit

Permalink
Allow the events option to be changed at runtime (#8928)
Browse files Browse the repository at this point in the history
  • Loading branch information
etimberg committed Apr 17, 2021
1 parent ca50287 commit e29ba78
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 2 deletions.
13 changes: 11 additions & 2 deletions src/core/core.controller.js
Expand Up @@ -7,7 +7,7 @@ import PluginService from './core.plugins';
import registry from './core.registry';
import Config, {determineAxis, getIndexAxis} from './core.config';
import {retinaScale} from '../helpers/helpers.dom';
import {each, callback as callCallback, uid, valueOrDefault, _elementsEqual, isNullOrUndef} from '../helpers/helpers.core';
import {each, callback as callCallback, uid, valueOrDefault, _elementsEqual, isNullOrUndef, setsEqual} from '../helpers/helpers.core';
import {clearCanvas, clipArea, unclipArea, _isPointInArea} from '../helpers/helpers.canvas';
// @ts-ignore
import {version} from '../../package.json';
Expand Down Expand Up @@ -480,6 +480,15 @@ class Chart {
me.ensureScalesHaveIDs();
me.buildOrUpdateScales();

const existingEvents = new Set(Object.keys(me._listeners));
const newEvents = new Set(me.options.events);

if (!setsEqual(existingEvents, newEvents)) {
// The events array has changed. Rebind it
me.unbindEvents();
me.bindEvents();
}

// plugins options references might have change, let's invalidate the cache
// https://github.com/chartjs/Chart.js/issues/5111#issuecomment-355934167
me._plugins.invalidate();
Expand Down Expand Up @@ -953,7 +962,7 @@ class Chart {
return;
}

delete me._listeners;
me._listeners = {};
each(listeners, (listener, type) => {
me.platform.removeEventListener(me, type, listener);
});
Expand Down
15 changes: 15 additions & 0 deletions src/helpers/helpers.core.js
Expand Up @@ -325,3 +325,18 @@ export function _capitalize(str) {
export const defined = (value) => typeof value !== 'undefined';

export const isFunction = (value) => typeof value === 'function';

// Adapted from https://stackoverflow.com/questions/31128855/comparing-ecma6-sets-for-equality#31129384
export const setsEqual = (a, b) => {
if (a.size !== b.size) {
return false;
}

for (const item of a) {
if (!b.has(item)) {
return false;
}
}

return true;
};
27 changes: 27 additions & 0 deletions test/specs/core.controller.tests.js
Expand Up @@ -291,6 +291,33 @@ describe('Chart', function() {
expect(chart.getActiveElements()).toEqual([{datasetIndex: 0, index: 1, element: point}]);
});

it('should handle changing the events at runtime', async function() {
var chart = acquireChart({
type: 'line',
data: {
labels: ['A', 'B', 'C', 'D'],
datasets: [{
data: [10, 20, 30, 100]
}]
},
options: {
events: ['click']
}
});

var point1 = chart.getDatasetMeta(0).data[1];
var point2 = chart.getDatasetMeta(0).data[2];

await jasmine.triggerMouseEvent(chart, 'click', point1);
expect(chart.getActiveElements()).toEqual([{datasetIndex: 0, index: 1, element: point1}]);

chart.options.events = ['mousemove'];
chart.update();

await jasmine.triggerMouseEvent(chart, 'mousemove', point2);
expect(chart.getActiveElements()).toEqual([{datasetIndex: 0, index: 2, element: point2}]);
});

it('should activate element on hover when minPadding pixels outside chart area', async function() {
var chart = acquireChart({
type: 'line',
Expand Down
11 changes: 11 additions & 0 deletions test/specs/helpers.core.tests.js
Expand Up @@ -457,4 +457,15 @@ describe('Chart.helpers.core', function() {
expect(() => helpers.resolveObjectKey({}, 1)).toThrow();
});
});

describe('setsEqual', function() {
it('should handle set comparison', function() {
var a = new Set([1]);
var b = new Set(['1']);
var c = new Set([1]);

expect(helpers.setsEqual(a, b)).toBeFalse();
expect(helpers.setsEqual(a, c)).toBeTrue();
});
});
});
2 changes: 2 additions & 0 deletions types/helpers/helpers.core.d.ts
Expand Up @@ -136,3 +136,5 @@ export function mergeIf<T, S1, S2, S3, S4>(target: T, source: [S1, S2, S3, S4]):
export function mergeIf<T>(target: T, source: AnyObject[]): AnyObject;

export function resolveObjectKey(obj: AnyObject, key: string): AnyObject;

export function setsEqual(a: Set<unknown>, b: Set<unknown>): boolean;

0 comments on commit e29ba78

Please sign in to comment.