mirror of
https://github.com/chartjs/Chart.js.git
synced 2026-03-06 08:24:05 +01:00
Registry fixes (#7617)
* Fix documentation for classical extensions * Tests and fixes for registry
This commit is contained in:
@@ -17,6 +17,8 @@ function MyScale() {
|
||||
Chart.Scale.call(this, arguments);
|
||||
// constructor stuff
|
||||
}
|
||||
MyScale.prototype = Object.create(Chart.Scale.prototype);
|
||||
MyScale.prototype.constructor = MyScale;
|
||||
|
||||
MyScale.prototype.draw = function(ctx) {
|
||||
Chart.Scale.prototype.draw.call(this, arguments);
|
||||
|
||||
@@ -112,12 +112,14 @@ Same example in classic style
|
||||
|
||||
```javascript
|
||||
function Custom() {
|
||||
Chart.controllers.bubble.call(this, arguments);
|
||||
Chart.controllers.bubble.apply(this, arguments);
|
||||
// constructor stuff
|
||||
}
|
||||
Custom.prototype = Object.create(Chart.controllers.bubble.prototype);
|
||||
Custom.prototype.constructor = Custom;
|
||||
|
||||
Custom.prototype.draw = function(ctx) {
|
||||
Chart.controllers.bubble.prototype.draw.call(this, arguments);
|
||||
Chart.controllers.bubble.prototype.draw.apply(this, arguments);
|
||||
|
||||
var meta = this.getMeta();
|
||||
var pt0 = meta.data[0];
|
||||
@@ -134,9 +136,7 @@ Custom.prototype.draw = function(ctx) {
|
||||
Custom.id = 'derivedBubble';
|
||||
Custom.defaults = Chart.defaults.bubble;
|
||||
|
||||
// Prototype chain can not be used to detect we are trying to register a controller, so we need
|
||||
// to be explicit
|
||||
Chart.registry.addControllers(Custom);
|
||||
Chart.register(Custom);
|
||||
|
||||
// Now we can create and use our new chart type
|
||||
new Chart(ctx, {
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import defaults from './core.defaults';
|
||||
import {valueOrDefault} from '../helpers/helpers.core';
|
||||
|
||||
/**
|
||||
* @typedef {{id: string, defaults: any, defaultRoutes: any}} IChartComponent
|
||||
@@ -13,15 +12,14 @@ export default class TypedRegistry {
|
||||
}
|
||||
|
||||
isForType(type) {
|
||||
return Object.prototype.isPrototypeOf.call(this.type, type);
|
||||
return Object.prototype.isPrototypeOf.call(this.type.prototype, type.prototype);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {IChartComponent} item
|
||||
* @param {string} [scopeOverride]
|
||||
* @returns {string} The scope where items defaults were registered to.
|
||||
*/
|
||||
register(item, scopeOverride) {
|
||||
register(item) {
|
||||
const proto = Object.getPrototypeOf(item);
|
||||
let parentScope;
|
||||
|
||||
@@ -32,11 +30,11 @@ export default class TypedRegistry {
|
||||
|
||||
const items = this.items;
|
||||
const id = item.id;
|
||||
const baseScope = valueOrDefault(scopeOverride, this.scope);
|
||||
const baseScope = this.scope;
|
||||
const scope = baseScope ? baseScope + '.' + id : id;
|
||||
|
||||
if (!id) {
|
||||
throw new Error('class does not have id: ' + Object.getPrototypeOf(item));
|
||||
throw new Error('class does not have id: ' + item);
|
||||
}
|
||||
|
||||
if (id in items) {
|
||||
@@ -64,13 +62,14 @@ export default class TypedRegistry {
|
||||
unregister(item) {
|
||||
const items = this.items;
|
||||
const id = item.id;
|
||||
const scope = this.scope;
|
||||
|
||||
if (id in items) {
|
||||
delete items[id];
|
||||
}
|
||||
|
||||
if (id in defaults[this.scope]) {
|
||||
delete defaults[this.scope][id];
|
||||
if (scope && id in defaults[scope]) {
|
||||
delete defaults[scope][id];
|
||||
} else if (id in defaults) {
|
||||
delete defaults[id];
|
||||
}
|
||||
|
||||
175
test/specs/core.registry.tests.js
Normal file
175
test/specs/core.registry.tests.js
Normal file
@@ -0,0 +1,175 @@
|
||||
describe('Chart.registry', function() {
|
||||
it('should handle a classic controller extension', function() {
|
||||
function CustomController() {
|
||||
Chart.controllers.line.apply(this, arguments);
|
||||
}
|
||||
CustomController.prototype = Object.create(Chart.controllers.line.prototype);
|
||||
CustomController.prototype.constructor = CustomController;
|
||||
CustomController.id = 'myline';
|
||||
CustomController.defaults = Chart.defaults.line;
|
||||
|
||||
Chart.register(CustomController);
|
||||
|
||||
expect(Chart.registry.getController('myline')).toEqual(CustomController);
|
||||
expect(Chart.defaults.myline).toEqual(CustomController.defaults);
|
||||
|
||||
Chart.unregister(CustomController);
|
||||
});
|
||||
|
||||
it('should handle a classic scale extension', function() {
|
||||
function CustomScale() {
|
||||
Chart.Scale.apply(this, arguments);
|
||||
}
|
||||
CustomScale.prototype = Object.create(Chart.Scale.prototype);
|
||||
CustomScale.prototype.constructor = CustomScale;
|
||||
CustomScale.id = 'myScale';
|
||||
CustomScale.defaults = {
|
||||
foo: 'bar'
|
||||
};
|
||||
|
||||
Chart.register(CustomScale);
|
||||
|
||||
expect(Chart.registry.getScale('myScale')).toEqual(CustomScale);
|
||||
expect(Chart.defaults.scales.myScale).toEqual(CustomScale.defaults);
|
||||
|
||||
Chart.unregister(CustomScale);
|
||||
|
||||
expect(function() {
|
||||
Chart.registry.getScale('myScale');
|
||||
}).toThrow(new Error('"myScale" is not a registered scale.'));
|
||||
expect(Chart.defaults.scales.myScale).not.toBeDefined();
|
||||
});
|
||||
|
||||
it('should handle a classic element extension', function() {
|
||||
function CustomElement() {
|
||||
Chart.Element.apply(this, arguments);
|
||||
}
|
||||
CustomElement.prototype = Object.create(Chart.Element.prototype);
|
||||
CustomElement.prototype.constructor = CustomElement;
|
||||
CustomElement.id = 'myElement';
|
||||
CustomElement.defaults = {
|
||||
foo: 'baz'
|
||||
};
|
||||
|
||||
Chart.register(CustomElement);
|
||||
|
||||
expect(Chart.registry.getElement('myElement')).toEqual(CustomElement);
|
||||
expect(Chart.defaults.elements.myElement).toEqual(CustomElement.defaults);
|
||||
|
||||
Chart.unregister(CustomElement);
|
||||
|
||||
expect(function() {
|
||||
Chart.registry.getElement('myElement');
|
||||
}).toThrow(new Error('"myElement" is not a registered element.'));
|
||||
expect(Chart.defaults.elements.myElement).not.toBeDefined();
|
||||
});
|
||||
|
||||
it('should handle a classig plugin', function() {
|
||||
const CustomPlugin = {
|
||||
id: 'customPlugin',
|
||||
defaults: {
|
||||
custom: 'plugin'
|
||||
}
|
||||
};
|
||||
|
||||
Chart.register(CustomPlugin);
|
||||
|
||||
expect(Chart.registry.getPlugin('customPlugin')).toEqual(CustomPlugin);
|
||||
expect(Chart.defaults.plugins.customPlugin).toEqual(CustomPlugin.defaults);
|
||||
|
||||
Chart.unregister(CustomPlugin);
|
||||
|
||||
expect(function() {
|
||||
Chart.registry.getPlugin('customPlugin');
|
||||
}).toThrow(new Error('"customPlugin" is not a registered plugin.'));
|
||||
expect(Chart.defaults.plugins.customPlugin).not.toBeDefined();
|
||||
});
|
||||
|
||||
it('should handle an ES6 controller extension', function() {
|
||||
class CustomController extends Chart.DatasetController {}
|
||||
CustomController.id = 'custom';
|
||||
CustomController.defaults = {
|
||||
foo: 'bar'
|
||||
};
|
||||
Chart.register(CustomController);
|
||||
|
||||
expect(Chart.registry.getController('custom')).toEqual(CustomController);
|
||||
expect(Chart.defaults.custom).toEqual(CustomController.defaults);
|
||||
|
||||
Chart.unregister(CustomController);
|
||||
|
||||
expect(function() {
|
||||
Chart.registry.getController('custom');
|
||||
}).toThrow(new Error('"custom" is not a registered controller.'));
|
||||
expect(Chart.defaults.custom).not.toBeDefined();
|
||||
});
|
||||
|
||||
it('should handle an ES6 scale extension', function() {
|
||||
class CustomScale extends Chart.Scale {}
|
||||
CustomScale.id = 'es6Scale';
|
||||
CustomScale.defaults = {
|
||||
foo: 'bar'
|
||||
};
|
||||
Chart.register(CustomScale);
|
||||
|
||||
expect(Chart.registry.getScale('es6Scale')).toEqual(CustomScale);
|
||||
expect(Chart.defaults.scales.es6Scale).toEqual(CustomScale.defaults);
|
||||
|
||||
Chart.unregister(CustomScale);
|
||||
|
||||
expect(function() {
|
||||
Chart.registry.getScale('es6Scale');
|
||||
}).toThrow(new Error('"es6Scale" is not a registered scale.'));
|
||||
expect(Chart.defaults.custom).not.toBeDefined();
|
||||
});
|
||||
|
||||
it('should handle an ES6 element extension', function() {
|
||||
class CustomElement extends Chart.Element {}
|
||||
CustomElement.id = 'es6element';
|
||||
CustomElement.defaults = {
|
||||
foo: 'bar'
|
||||
};
|
||||
Chart.register(CustomElement);
|
||||
|
||||
expect(Chart.registry.getElement('es6element')).toEqual(CustomElement);
|
||||
expect(Chart.defaults.elements.es6element).toEqual(CustomElement.defaults);
|
||||
|
||||
Chart.unregister(CustomElement);
|
||||
|
||||
expect(function() {
|
||||
Chart.registry.getElement('es6element');
|
||||
}).toThrow(new Error('"es6element" is not a registered element.'));
|
||||
expect(Chart.defaults.elements.es6element).not.toBeDefined();
|
||||
});
|
||||
|
||||
it('should handle an ES6 plugin', function() {
|
||||
class CustomPlugin {}
|
||||
CustomPlugin.id = 'es6plugin';
|
||||
CustomPlugin.defaults = {
|
||||
foo: 'bar'
|
||||
};
|
||||
Chart.register(CustomPlugin);
|
||||
|
||||
expect(Chart.registry.getPlugin('es6plugin')).toEqual(CustomPlugin);
|
||||
expect(Chart.defaults.plugins.es6plugin).toEqual(CustomPlugin.defaults);
|
||||
|
||||
Chart.unregister(CustomPlugin);
|
||||
|
||||
expect(function() {
|
||||
Chart.registry.getPlugin('es6plugin');
|
||||
}).toThrow(new Error('"es6plugin" is not a registered plugin.'));
|
||||
expect(Chart.defaults.plugins.es6plugin).not.toBeDefined();
|
||||
});
|
||||
|
||||
it('should not accept an object without id', function() {
|
||||
expect(function() {
|
||||
Chart.register({foo: 'bar'});
|
||||
}).toThrow(new Error('class does not have id: bar'));
|
||||
|
||||
class FaultyPlugin {}
|
||||
|
||||
expect(function() {
|
||||
Chart.register(FaultyPlugin);
|
||||
}).toThrow(new Error('class does not have id: class FaultyPlugin {}'));
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user