mirror of
https://github.com/chartjs/Chart.js.git
synced 2025-12-08 20:36:08 +00:00
Relocate chart type and dataset type defaults (#8563)
* Relocate chart type and dataset type defaults * Update types * Separate overrides and descriptors * Update derived sample, use merge for inherit * Don't merge overrides * Review update
This commit is contained in:
parent
279b6ae1da
commit
8d6e87881a
@ -235,7 +235,7 @@ If true, the bars for a particular data point fall between the grid lines. The g
|
||||
|
||||
## Default Options
|
||||
|
||||
It is common to want to apply a configuration setting to all created bar charts. The global bar chart settings are stored in `Chart.defaults.controllers.bar`. Changing the global options only affects charts created after the change. Existing charts are not changed.
|
||||
It is common to want to apply a configuration setting to all created bar charts. The global bar chart settings are stored in `Chart.overrides.bar`. Changing the global options only affects charts created after the change. Existing charts are not changed.
|
||||
|
||||
## barPercentage vs categoryPercentage
|
||||
|
||||
|
||||
@ -106,7 +106,7 @@ All these values, if `undefined`, fallback to the associated [`elements.point.*`
|
||||
|
||||
## Default Options
|
||||
|
||||
We can also change the default values for the Bubble chart type. Doing so will give all bubble charts created after this point the new defaults. The default configuration for the bubble chart can be accessed at `Chart.defaults.controllers.bubble`.
|
||||
We can also change the default values for the Bubble chart type. Doing so will give all bubble charts created after this point the new defaults. The default configuration for the bubble chart can be accessed at `Chart.overrides.bubble`.
|
||||
|
||||
## Data Structure
|
||||
|
||||
|
||||
@ -172,7 +172,7 @@ These are the customisation options specific to Pie & Doughnut charts. These opt
|
||||
|
||||
## Default Options
|
||||
|
||||
We can also change these default values for each Doughnut type that is created, this object is available at `Chart.defaults.controllers.doughnut`. Pie charts also have a clone of these defaults available to change at `Chart.defaults.controllers.pie`, with the only difference being `cutout` being set to 0.
|
||||
We can also change these default values for each Doughnut type that is created, this object is available at `Chart.overrides.doughnut`. Pie charts also have a clone of these defaults available to change at `Chart.overrides.pie`, with the only difference being `cutout` being set to 0.
|
||||
|
||||
## Data Structure
|
||||
|
||||
|
||||
@ -188,12 +188,12 @@ The line chart defines the following configuration options. These options are lo
|
||||
|
||||
## Default Options
|
||||
|
||||
It is common to want to apply a configuration setting to all created line charts. The global line chart settings are stored in `Chart.defaults.controllers.line`. Changing the global options only affects charts created after the change. Existing charts are not changed.
|
||||
It is common to want to apply a configuration setting to all created line charts. The global line chart settings are stored in `Chart.overrides.line`. Changing the global options only affects charts created after the change. Existing charts are not changed.
|
||||
|
||||
For example, to configure all line charts with `spanGaps = true` you would do:
|
||||
|
||||
```javascript
|
||||
Chart.defaults.controllers.line.spanGaps = true;
|
||||
Chart.overrides.line.spanGaps = true;
|
||||
```
|
||||
|
||||
## Data Structure
|
||||
|
||||
@ -120,12 +120,12 @@ The polar area chart uses the [radialLinear](../axes/radial/linear.mdx) scale. A
|
||||
|
||||
## Default Options
|
||||
|
||||
We can also change these default values for each PolarArea type that is created, this object is available at `Chart.defaults.controllers.polarArea`. Changing the global options only affects charts created after the change. Existing charts are not changed.
|
||||
We can also change these default values for each PolarArea type that is created, this object is available at `Chart.overrides.polarArea`. Changing the global options only affects charts created after the change. Existing charts are not changed.
|
||||
|
||||
For example, to configure all new polar area charts with `animateScale = false` you would do:
|
||||
|
||||
```javascript
|
||||
Chart.defaults.controllers.polarArea.animation.animateScale = false;
|
||||
Chart.overrides.polarArea.animation.animateScale = false;
|
||||
```
|
||||
|
||||
## Data Structure
|
||||
|
||||
@ -193,7 +193,7 @@ options = {
|
||||
|
||||
## Default Options
|
||||
|
||||
It is common to want to apply a configuration setting to all created radar charts. The global radar chart settings are stored in `Chart.defaults.controllers.radar`. Changing the global options only affects charts created after the change. Existing charts are not changed.
|
||||
It is common to want to apply a configuration setting to all created radar charts. The global radar chart settings are stored in `Chart.overrides.radar`. Changing the global options only affects charts created after the change. Existing charts are not changed.
|
||||
|
||||
## Data Structure
|
||||
|
||||
|
||||
@ -86,7 +86,7 @@ function example() {
|
||||
y: {
|
||||
from: 0
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
hide: {
|
||||
animations: {
|
||||
@ -124,9 +124,8 @@ Animation configuration consists of 3 keys.
|
||||
These keys can be configured in following paths:
|
||||
|
||||
* `` - chart options
|
||||
* `controllers[type]` - controller type options
|
||||
* `controllers[type].datasets` - dataset type options
|
||||
* `datasets[type]` - dataset type options
|
||||
* `overrides[type]` - chart type options
|
||||
|
||||
These paths are valid under `defaults` for global confuguration and `options` for instance configuration.
|
||||
|
||||
|
||||
@ -42,7 +42,7 @@ The following example would set the `showLine` option to 'false' for all line da
|
||||
|
||||
```javascript
|
||||
// Do not show lines for all datasets by default
|
||||
Chart.defaults.controllers.line.showLine = false;
|
||||
Chart.defaults.datasets.line.showLine = false;
|
||||
|
||||
// This chart would show a line only for the third dataset
|
||||
var chart = new Chart(ctx, {
|
||||
|
||||
@ -9,7 +9,7 @@ Options are resolved from top to bottom, using a context dependent route.
|
||||
### Chart level options
|
||||
|
||||
* options
|
||||
* defaults.controllers[`config.type`]
|
||||
* overrides[`config.type`]
|
||||
* defaults
|
||||
|
||||
### Dataset level options
|
||||
@ -18,18 +18,18 @@ Options are resolved from top to bottom, using a context dependent route.
|
||||
|
||||
* dataset
|
||||
* options.datasets[`dataset.type`]
|
||||
* options.controllers[`dataset.type`].datasets
|
||||
* options
|
||||
* overrides[`config.type`].datasets[`dataset.type`]
|
||||
* defaults.datasets[`dataset.type`]
|
||||
* defaults.controllers[`dataset.type`].datasets
|
||||
* defaults
|
||||
|
||||
### Dataset animation options
|
||||
|
||||
* dataset.animation
|
||||
* options.controllers[`dataset.type`].datasets.animation
|
||||
* options.datasets[`dataset.type`].animation
|
||||
* options.animation
|
||||
* defaults.controllers[`dataset.type`].datasets.animation
|
||||
* overrides[`config.type`].datasets[`dataset.type`].animation
|
||||
* defaults.datasets[`dataset.type`].animation
|
||||
* defaults.animation
|
||||
|
||||
### Dataset element level options
|
||||
@ -38,31 +38,30 @@ Each scope is looked up with `elementType` prefix in the option name first, then
|
||||
|
||||
* dataset
|
||||
* options.datasets[`dataset.type`]
|
||||
* options.controllers[`dataset.type`].datasets
|
||||
* options.controllers[`dataset.type`].elements[`elementType`]
|
||||
* options.datasets[`dataset.type`].elements[`elementType`]
|
||||
* options.elements[`elementType`]
|
||||
* options
|
||||
* overrides[`config.type`].datasets[`dataset.type`]
|
||||
* overrides[`config.type`].datasets[`dataset.type`].elements[`elementType`]
|
||||
* defaults.datasets[`dataset.type`]
|
||||
* defaults.controllers[`dataset.type`].datasets
|
||||
* defaults.controllers[`dataset.type`].elements[`elementType`]
|
||||
* defaults.datasets[`dataset.type`].elements[`elementType`]
|
||||
* defaults.elements[`elementType`]
|
||||
* defaults
|
||||
|
||||
### Scale options
|
||||
|
||||
* options.scales
|
||||
* defaults.controllers[`config.type`].scales
|
||||
* defaults.controllers[`dataset.type`].scales
|
||||
* overrides[`config.type`].scales
|
||||
* defaults.scales
|
||||
* defaults.scale
|
||||
|
||||
### Plugin options
|
||||
|
||||
A plugin can provide `additionalOptionScopes` array of paths to additionally look for its options in. For root scope, use empty string: `''`. Most core plugins also take options from root scope.
|
||||
|
||||
* options.plugins[`plugin.id`]
|
||||
* options.controllers[`config.type`].plugins[`plugin.id`]
|
||||
* (options.[`...plugin.additionalOptionScopes`])
|
||||
* defaults.controllers[`config.type`].plugins[`plugin.id`]
|
||||
* overrides[`config.type`].plugins[`plugin.id`]
|
||||
* defaults.plugins[`plugin.id`]
|
||||
* (defaults.[`...plugin.additionalOptionScopes`])
|
||||
|
||||
|
||||
@ -111,7 +111,7 @@ A number of changes were made to the configuration options passed to the `Chart`
|
||||
#### Defaults
|
||||
|
||||
* `global` namespace was removed from `defaults`. So `Chart.defaults.global` is now `Chart.defaults`
|
||||
* Dataset controller defaults were relocate to `controllers`. For example `Chart.defaults.line` is now `Chart.defaults.controllers.line`
|
||||
* Dataset controller defaults were relocate to `overrides`. For example `Chart.defaults.line` is now `Chart.overrides.line`
|
||||
* `default` prefix was removed from defaults. For example `Chart.defaults.global.defaultColor` is now `Chart.defaults.color`
|
||||
* `defaultColor` was split to `color`, `borderColor` and `backgroundColor`
|
||||
* `defaultFontColor` was renamed to `color`
|
||||
|
||||
@ -24,7 +24,7 @@
|
||||
// Call bubble controller method to draw all the points
|
||||
super.draw(arguments);
|
||||
|
||||
// Now we can do some custom drawing for this dataset. Here we'll draw a red box around the first point in each dataset
|
||||
// Now we can do some custom drawing for this dataset. Here we'll draw a box around the first point in each dataset, using `boxStrokeStyle` dataset option for color
|
||||
var meta = this.getMeta();
|
||||
var pt0 = meta.data[0];
|
||||
|
||||
@ -33,14 +33,19 @@
|
||||
|
||||
var ctx = this.chart.ctx;
|
||||
ctx.save();
|
||||
ctx.strokeStyle = 'red';
|
||||
ctx.strokeStyle = this.options.boxStrokeStyle;
|
||||
ctx.lineWidth = 1;
|
||||
ctx.strokeRect(x - radius, y - radius, 2 * radius, 2 * radius);
|
||||
ctx.restore();
|
||||
}
|
||||
}
|
||||
Custom.id = 'derivedBubble';
|
||||
Custom.defaults = Chart.controllers.bubble.defaults;
|
||||
Custom.defaults = {
|
||||
// Custom defaults. Bubble defaults are inherited.
|
||||
boxStrokeStyle: 'red'
|
||||
};
|
||||
// Overrides are only inherited, but not merged if defined
|
||||
// Custom.overrides = Chart.overrides.bubble;
|
||||
|
||||
// Stores the controller so that the chart initialization routine can look it up
|
||||
Chart.register(Custom);
|
||||
|
||||
@ -48,7 +48,7 @@
|
||||
labels: {
|
||||
generateLabels: function(chart) {
|
||||
// Get the default label list
|
||||
var original = Chart.defaults.controllers.pie.plugins.legend.labels.generateLabels;
|
||||
var original = Chart.overrides.pie.plugins.legend.labels.generateLabels;
|
||||
var labels = original.call(this, chart);
|
||||
|
||||
// Build an array of colors used in the datasets of the chart
|
||||
|
||||
@ -511,23 +511,27 @@ BarController.defaults = {
|
||||
datasetElementType: false,
|
||||
dataElementType: 'bar',
|
||||
|
||||
categoryPercentage: 0.8,
|
||||
barPercentage: 0.9,
|
||||
|
||||
animations: {
|
||||
numbers: {
|
||||
type: 'number',
|
||||
properties: ['x', 'y', 'base', 'width', 'height']
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @type {any}
|
||||
*/
|
||||
BarController.overrides = {
|
||||
interaction: {
|
||||
mode: 'index'
|
||||
},
|
||||
|
||||
hover: {},
|
||||
|
||||
datasets: {
|
||||
categoryPercentage: 0.8,
|
||||
barPercentage: 0.9,
|
||||
animations: {
|
||||
numbers: {
|
||||
type: 'number',
|
||||
properties: ['x', 'y', 'base', 'width', 'height']
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
scales: {
|
||||
_index_: {
|
||||
type: 'category',
|
||||
|
||||
@ -133,12 +133,19 @@ BubbleController.id = 'bubble';
|
||||
BubbleController.defaults = {
|
||||
datasetElementType: false,
|
||||
dataElementType: 'point',
|
||||
|
||||
animations: {
|
||||
numbers: {
|
||||
type: 'number',
|
||||
properties: ['x', 'y', 'borderWidth', 'radius']
|
||||
}
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @type {any}
|
||||
*/
|
||||
BubbleController.overrides = {
|
||||
scales: {
|
||||
x: {
|
||||
type: 'linear'
|
||||
|
||||
@ -328,23 +328,26 @@ DoughnutController.defaults = {
|
||||
properties: ['circumference', 'endAngle', 'innerRadius', 'outerRadius', 'startAngle', 'x', 'y', 'offset', 'borderWidth']
|
||||
},
|
||||
},
|
||||
aspectRatio: 1,
|
||||
// The percentage of the chart that we cut out of the middle.
|
||||
cutout: '50%',
|
||||
|
||||
datasets: {
|
||||
// The percentage of the chart that we cut out of the middle.
|
||||
cutout: '50%',
|
||||
// The rotation of the chart, where the first data arc begins.
|
||||
rotation: 0,
|
||||
|
||||
// The rotation of the chart, where the first data arc begins.
|
||||
rotation: 0,
|
||||
// The total circumference of the chart.
|
||||
circumference: 360,
|
||||
|
||||
// The total circumference of the chart.
|
||||
circumference: 360,
|
||||
|
||||
// The outr radius of the chart
|
||||
radius: '100%'
|
||||
},
|
||||
// The outr radius of the chart
|
||||
radius: '100%',
|
||||
|
||||
indexAxis: 'r',
|
||||
};
|
||||
|
||||
/**
|
||||
* @type {any}
|
||||
*/
|
||||
DoughnutController.overrides = {
|
||||
aspectRatio: 1,
|
||||
|
||||
// Need to override these to give a nice default
|
||||
plugins: {
|
||||
|
||||
@ -111,11 +111,14 @@ LineController.defaults = {
|
||||
datasetElementType: 'line',
|
||||
dataElementType: 'point',
|
||||
|
||||
datasets: {
|
||||
showLine: true,
|
||||
spanGaps: false,
|
||||
},
|
||||
showLine: true,
|
||||
spanGaps: false,
|
||||
};
|
||||
|
||||
/**
|
||||
* @type {any}
|
||||
*/
|
||||
LineController.overrides = {
|
||||
interaction: {
|
||||
mode: 'index'
|
||||
},
|
||||
|
||||
@ -11,17 +11,15 @@ PieController.id = 'pie';
|
||||
* @type {any}
|
||||
*/
|
||||
PieController.defaults = {
|
||||
datasets: {
|
||||
// The percentage of the chart that we cut out of the middle.
|
||||
cutout: 0,
|
||||
// The percentage of the chart that we cut out of the middle.
|
||||
cutout: 0,
|
||||
|
||||
// The rotation of the chart, where the first data arc begins.
|
||||
rotation: 0,
|
||||
// The rotation of the chart, where the first data arc begins.
|
||||
rotation: 0,
|
||||
|
||||
// The total circumference of the chart.
|
||||
circumference: 360,
|
||||
// The total circumference of the chart.
|
||||
circumference: 360,
|
||||
|
||||
// The outr radius of the chart
|
||||
radius: '100%'
|
||||
}
|
||||
// The outr radius of the chart
|
||||
radius: '100%'
|
||||
};
|
||||
|
||||
@ -131,25 +131,16 @@ PolarAreaController.defaults = {
|
||||
properties: ['x', 'y', 'startAngle', 'endAngle', 'innerRadius', 'outerRadius']
|
||||
},
|
||||
},
|
||||
aspectRatio: 1,
|
||||
indexAxis: 'r',
|
||||
scales: {
|
||||
r: {
|
||||
type: 'radialLinear',
|
||||
angleLines: {
|
||||
display: false
|
||||
},
|
||||
beginAtZero: true,
|
||||
gridLines: {
|
||||
circular: true
|
||||
},
|
||||
pointLabels: {
|
||||
display: false
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
startAngle: 0,
|
||||
};
|
||||
|
||||
/**
|
||||
* @type {any}
|
||||
*/
|
||||
PolarAreaController.overrides = {
|
||||
aspectRatio: 1,
|
||||
|
||||
plugins: {
|
||||
legend: {
|
||||
labels: {
|
||||
@ -193,6 +184,21 @@ PolarAreaController.defaults = {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
scales: {
|
||||
r: {
|
||||
type: 'radialLinear',
|
||||
angleLines: {
|
||||
display: false
|
||||
},
|
||||
beginAtZero: true,
|
||||
gridLines: {
|
||||
circular: true
|
||||
},
|
||||
pointLabels: {
|
||||
display: false
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@ -80,16 +80,21 @@ RadarController.id = 'radar';
|
||||
RadarController.defaults = {
|
||||
datasetElementType: 'line',
|
||||
dataElementType: 'point',
|
||||
aspectRatio: 1,
|
||||
datasets: {
|
||||
showLine: true,
|
||||
},
|
||||
indexAxis: 'r',
|
||||
showLine: true,
|
||||
elements: {
|
||||
line: {
|
||||
fill: 'start'
|
||||
}
|
||||
},
|
||||
indexAxis: 'r',
|
||||
};
|
||||
|
||||
/**
|
||||
* @type {any}
|
||||
*/
|
||||
RadarController.overrides = {
|
||||
aspectRatio: 1,
|
||||
|
||||
scales: {
|
||||
r: {
|
||||
type: 'radialLinear',
|
||||
|
||||
@ -10,19 +10,14 @@ ScatterController.id = 'scatter';
|
||||
* @type {any}
|
||||
*/
|
||||
ScatterController.defaults = {
|
||||
scales: {
|
||||
x: {
|
||||
type: 'linear'
|
||||
},
|
||||
y: {
|
||||
type: 'linear'
|
||||
}
|
||||
},
|
||||
showLine: false,
|
||||
fill: false
|
||||
};
|
||||
|
||||
datasets: {
|
||||
showLine: false,
|
||||
fill: false
|
||||
},
|
||||
/**
|
||||
* @type {any}
|
||||
*/
|
||||
ScatterController.overrides = {
|
||||
|
||||
interaction: {
|
||||
mode: 'point'
|
||||
@ -39,5 +34,14 @@ ScatterController.defaults = {
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
scales: {
|
||||
x: {
|
||||
type: 'linear'
|
||||
},
|
||||
y: {
|
||||
type: 'linear'
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@ -1,13 +1,11 @@
|
||||
import defaults from './core.defaults';
|
||||
import defaults, {overrides, descriptors} from './core.defaults';
|
||||
import {mergeIf, resolveObjectKey, isArray, isFunction, valueOrDefault, isObject} from '../helpers/helpers.core';
|
||||
import {_attachContext, _createResolver, _descriptors} from '../helpers/helpers.config';
|
||||
|
||||
export function getIndexAxis(type, options) {
|
||||
const typeDefaults = defaults.controllers[type] || {};
|
||||
const datasetDefaults = typeDefaults.datasets || {};
|
||||
const datasetOptions = options.datasets || {};
|
||||
const typeOptions = datasetOptions[type] || {};
|
||||
return typeOptions.indexAxis || options.indexAxis || datasetDefaults.indexAxis || 'x';
|
||||
const datasetDefaults = defaults.datasets[type] || {};
|
||||
const datasetOptions = (options.datasets || {})[type] || {};
|
||||
return datasetOptions.indexAxis || options.indexAxis || datasetDefaults.indexAxis || 'x';
|
||||
}
|
||||
|
||||
function getAxisFromDefaultScaleID(id, indexAxis) {
|
||||
@ -41,7 +39,7 @@ export function determineAxis(id, scaleOptions) {
|
||||
}
|
||||
|
||||
function mergeScaleConfig(config, options) {
|
||||
const chartDefaults = defaults.controllers[config.type] || {scales: {}};
|
||||
const chartDefaults = overrides[config.type] || {scales: {}};
|
||||
const configScales = options.scales || {};
|
||||
const chartIndexAxis = getIndexAxis(config.type, options);
|
||||
const firstIDs = Object.create(null);
|
||||
@ -61,7 +59,7 @@ function mergeScaleConfig(config, options) {
|
||||
config.data.datasets.forEach(dataset => {
|
||||
const type = dataset.type || config.type;
|
||||
const indexAxis = dataset.indexAxis || getIndexAxis(type, options);
|
||||
const datasetDefaults = defaults.controllers[type] || {};
|
||||
const datasetDefaults = overrides[type] || {};
|
||||
const defaultScaleOptions = datasetDefaults.scales || {};
|
||||
Object.keys(defaultScaleOptions).forEach(defaultID => {
|
||||
const axis = getAxisFromDefaultScaleID(defaultID, indexAxis);
|
||||
@ -175,8 +173,6 @@ export default class Config {
|
||||
return cachedKeys(datasetType,
|
||||
() => [
|
||||
`datasets.${datasetType}`,
|
||||
`controllers.${datasetType}`,
|
||||
`controllers.${datasetType}.datasets`,
|
||||
''
|
||||
]);
|
||||
}
|
||||
@ -192,12 +188,9 @@ export default class Config {
|
||||
return cachedKeys(`${datasetType}.transition.${transition}`,
|
||||
() => [
|
||||
`datasets.${datasetType}.transitions.${transition}`,
|
||||
`controllers.${datasetType}.transitions.${transition}`,
|
||||
`controllers.${datasetType}.datasets.transitions.${transition}`,
|
||||
`transitions.${transition}`,
|
||||
// The following are used for looking up the `animations` and `animation` keys
|
||||
`datasets.${datasetType}`,
|
||||
`controllers.${datasetType}`,
|
||||
`controllers.${datasetType}.datasets`,
|
||||
''
|
||||
]);
|
||||
}
|
||||
@ -213,9 +206,8 @@ export default class Config {
|
||||
datasetElementScopeKeys(datasetType, elementType) {
|
||||
return cachedKeys(`${datasetType}-${elementType}`,
|
||||
() => [
|
||||
`datasets.${datasetType}.elements.${elementType}`,
|
||||
`datasets.${datasetType}`,
|
||||
`controllers.${datasetType}.datasets`,
|
||||
`controllers.${datasetType}.elements.${elementType}`,
|
||||
`elements.${elementType}`,
|
||||
''
|
||||
]);
|
||||
@ -231,7 +223,6 @@ export default class Config {
|
||||
const type = this.type;
|
||||
return cachedKeys(`${type}-plugin-${id}`,
|
||||
() => [
|
||||
`controllers.${type}.plugins.${id}`,
|
||||
`plugins.${id}`,
|
||||
...plugin.additionalOptionScopes || [],
|
||||
]);
|
||||
@ -244,10 +235,11 @@ export default class Config {
|
||||
* @param {boolean} [resetCache] - reset the cache for this mainScope
|
||||
*/
|
||||
getOptionScopes(mainScope, scopeKeys, resetCache) {
|
||||
let cache = this._scopeCache.get(mainScope);
|
||||
const {_scopeCache, options, type} = this;
|
||||
let cache = _scopeCache.get(mainScope);
|
||||
if (!cache || resetCache) {
|
||||
cache = new Map();
|
||||
this._scopeCache.set(mainScope, cache);
|
||||
_scopeCache.set(mainScope, cache);
|
||||
}
|
||||
const cached = cache.get(scopeKeys);
|
||||
if (cached) {
|
||||
@ -260,9 +252,10 @@ export default class Config {
|
||||
scopes.add(mainScope);
|
||||
scopeKeys.forEach(key => addIfFound(scopes, mainScope, key));
|
||||
}
|
||||
scopeKeys.forEach(key => addIfFound(scopes, this.options, key));
|
||||
scopeKeys.forEach(key => addIfFound(scopes, options, key));
|
||||
scopeKeys.forEach(key => addIfFound(scopes, overrides[type] || {}, key));
|
||||
scopeKeys.forEach(key => addIfFound(scopes, defaults, key));
|
||||
scopeKeys.forEach(key => addIfFound(scopes, defaults.descriptors, key));
|
||||
scopeKeys.forEach(key => addIfFound(scopes, descriptors, key));
|
||||
|
||||
const array = [...scopes];
|
||||
if (keysCached.has(scopeKeys)) {
|
||||
@ -276,14 +269,15 @@ export default class Config {
|
||||
* @return {object[]}
|
||||
*/
|
||||
chartOptionScopes() {
|
||||
const controllerDefaults = defaults.controllers[this.type] || {};
|
||||
const {options, type} = this;
|
||||
|
||||
return [
|
||||
this.options,
|
||||
controllerDefaults,
|
||||
controllerDefaults.datasets || {},
|
||||
{type: this.type},
|
||||
options,
|
||||
overrides[type] || {},
|
||||
defaults.datasets[type] || {}, // https://github.com/chartjs/Chart.js/issues/8531
|
||||
{type},
|
||||
defaults,
|
||||
defaults.descriptors
|
||||
descriptors
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import animator from './core.animator';
|
||||
import defaults from './core.defaults';
|
||||
import defaults, {overrides} from './core.defaults';
|
||||
import Interaction from './core.interaction';
|
||||
import layouts from './core.layouts';
|
||||
import {BasicPlatform, DomPlatform} from '../platform';
|
||||
@ -410,11 +410,11 @@ class Chart {
|
||||
meta.controller.updateIndex(i);
|
||||
meta.controller.linkScales();
|
||||
} else {
|
||||
const controllerDefaults = defaults.controllers[type];
|
||||
const ControllerClass = registry.getController(type);
|
||||
const {datasetElementType, dataElementType} = defaults.datasets[type];
|
||||
Object.assign(ControllerClass.prototype, {
|
||||
dataElementType: registry.getElement(controllerDefaults.dataElementType),
|
||||
datasetElementType: controllerDefaults.datasetElementType && registry.getElement(controllerDefaults.datasetElementType)
|
||||
dataElementType: registry.getElement(dataElementType),
|
||||
datasetElementType: datasetElementType && registry.getElement(datasetElementType)
|
||||
});
|
||||
meta.controller = new ControllerClass(me, i);
|
||||
newControllers.push(meta.controller);
|
||||
@ -1117,6 +1117,10 @@ Object.defineProperties(Chart, {
|
||||
enumerable,
|
||||
value: instances
|
||||
},
|
||||
overrides: {
|
||||
enumerable,
|
||||
value: overrides
|
||||
},
|
||||
registry: {
|
||||
enumerable,
|
||||
value: registry
|
||||
|
||||
@ -1,7 +1,8 @@
|
||||
import {getHoverColor} from '../helpers/helpers.color';
|
||||
import {isObject, merge, valueOrDefault} from '../helpers/helpers.core';
|
||||
|
||||
const privateSymbol = Symbol('private');
|
||||
export const overrides = Object.create(null);
|
||||
export const descriptors = Object.create(null);
|
||||
|
||||
/**
|
||||
* @param {object} node
|
||||
@ -20,17 +21,24 @@ function getScope(node, key) {
|
||||
return node;
|
||||
}
|
||||
|
||||
function set(root, scope, values) {
|
||||
if (typeof scope === 'string') {
|
||||
return merge(getScope(root, scope), values);
|
||||
}
|
||||
return merge(getScope(root, ''), scope);
|
||||
}
|
||||
|
||||
/**
|
||||
* Please use the module's default export which provides a singleton instance
|
||||
* Note: class is exported for typedoc
|
||||
*/
|
||||
export class Defaults {
|
||||
constructor(descriptors) {
|
||||
constructor(_descriptors) {
|
||||
this.animation = undefined;
|
||||
this.backgroundColor = 'rgba(0,0,0,0.1)';
|
||||
this.borderColor = 'rgba(0,0,0,0.1)';
|
||||
this.color = '#666';
|
||||
this.controllers = {};
|
||||
this.datasets = {};
|
||||
this.devicePixelRatio = (context) => context.chart.platform.getDevicePixelRatio();
|
||||
this.elements = {};
|
||||
this.events = [
|
||||
@ -68,12 +76,7 @@ export class Defaults {
|
||||
this.scales = {};
|
||||
this.showLine = true;
|
||||
|
||||
Object.defineProperty(this, privateSymbol, {
|
||||
value: Object.create(null),
|
||||
writable: false
|
||||
});
|
||||
|
||||
this.describe(descriptors);
|
||||
this.describe(_descriptors);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -81,10 +84,7 @@ export class Defaults {
|
||||
* @param {object} [values]
|
||||
*/
|
||||
set(scope, values) {
|
||||
if (typeof scope === 'string') {
|
||||
return merge(getScope(this, scope), values);
|
||||
}
|
||||
return merge(getScope(this, ''), scope);
|
||||
return set(this, scope, values);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -99,15 +99,11 @@ export class Defaults {
|
||||
* @param {object} [values]
|
||||
*/
|
||||
describe(scope, values) {
|
||||
const root = this[privateSymbol];
|
||||
if (typeof scope === 'string') {
|
||||
return merge(getScope(root, scope), values);
|
||||
}
|
||||
return merge(getScope(root, ''), scope);
|
||||
return set(descriptors, scope, values);
|
||||
}
|
||||
|
||||
get descriptors() {
|
||||
return this[privateSymbol];
|
||||
override(scope, values) {
|
||||
return set(overrides, scope, values);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -10,7 +10,7 @@ import {each, callback as call, _capitalize} from '../helpers/helpers.core';
|
||||
*/
|
||||
export class Registry {
|
||||
constructor() {
|
||||
this.controllers = new TypedRegistry(DatasetController, 'controllers');
|
||||
this.controllers = new TypedRegistry(DatasetController, 'datasets', true);
|
||||
this.elements = new TypedRegistry(Element, 'elements');
|
||||
this.plugins = new TypedRegistry(Object, 'plugins');
|
||||
this.scales = new TypedRegistry(Scale, 'scales');
|
||||
|
||||
@ -1,13 +1,15 @@
|
||||
import defaults from './core.defaults';
|
||||
import {merge} from '../helpers';
|
||||
import defaults, {overrides} from './core.defaults';
|
||||
|
||||
/**
|
||||
* @typedef {{id: string, defaults: any, defaultRoutes: any}} IChartComponent
|
||||
* @typedef {{id: string, defaults: any, overrides?: any, defaultRoutes: any}} IChartComponent
|
||||
*/
|
||||
|
||||
export default class TypedRegistry {
|
||||
constructor(type, scope) {
|
||||
constructor(type, scope, override) {
|
||||
this.type = type;
|
||||
this.scope = scope;
|
||||
this.override = override;
|
||||
this.items = Object.create(null);
|
||||
}
|
||||
|
||||
@ -20,18 +22,18 @@ export default class TypedRegistry {
|
||||
* @returns {string} The scope where items defaults were registered to.
|
||||
*/
|
||||
register(item) {
|
||||
const me = this;
|
||||
const proto = Object.getPrototypeOf(item);
|
||||
let parentScope;
|
||||
|
||||
if (isIChartComponent(proto)) {
|
||||
// Make sure the parent is registered and note the scope where its defaults are.
|
||||
parentScope = this.register(proto);
|
||||
parentScope = me.register(proto);
|
||||
}
|
||||
|
||||
const items = this.items;
|
||||
const items = me.items;
|
||||
const id = item.id;
|
||||
const baseScope = this.scope;
|
||||
const scope = baseScope ? baseScope + '.' + id : id;
|
||||
const scope = me.scope + '.' + id;
|
||||
|
||||
if (!id) {
|
||||
throw new Error('class does not have id: ' + item);
|
||||
@ -44,6 +46,9 @@ export default class TypedRegistry {
|
||||
|
||||
items[id] = item;
|
||||
registerDefaults(item, scope, parentScope);
|
||||
if (me.override) {
|
||||
defaults.override(item.id, item.overrides);
|
||||
}
|
||||
|
||||
return scope;
|
||||
}
|
||||
@ -70,18 +75,20 @@ export default class TypedRegistry {
|
||||
|
||||
if (scope && id in defaults[scope]) {
|
||||
delete defaults[scope][id];
|
||||
if (this.override) {
|
||||
delete overrides[id];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function registerDefaults(item, scope, parentScope) {
|
||||
// Inherit the parent's defaults and keep existing defaults
|
||||
const itemDefaults = Object.assign(
|
||||
Object.create(null),
|
||||
parentScope && defaults.get(parentScope),
|
||||
item.defaults,
|
||||
defaults.get(scope)
|
||||
);
|
||||
const itemDefaults = merge(Object.create(null), [
|
||||
parentScope ? defaults.get(parentScope) : {},
|
||||
defaults.get(scope),
|
||||
item.defaults
|
||||
]);
|
||||
|
||||
defaults.set(scope, itemDefaults);
|
||||
|
||||
|
||||
@ -1306,7 +1306,7 @@ describe('Chart.controllers.bar', function() {
|
||||
var chart = window.acquireChart(this.config);
|
||||
var meta = chart.getDatasetMeta(0);
|
||||
var xScale = chart.scales[meta.xAxisID];
|
||||
var options = Chart.defaults.controllers.bar.datasets;
|
||||
var options = Chart.defaults.datasets.bar;
|
||||
|
||||
var categoryPercentage = options.categoryPercentage;
|
||||
var barPercentage = options.barPercentage;
|
||||
@ -1482,7 +1482,7 @@ describe('Chart.controllers.bar', function() {
|
||||
expected = barThickness;
|
||||
} else {
|
||||
var scale = chart.scales.x;
|
||||
var options = Chart.defaults.controllers.bar.datasets;
|
||||
var options = Chart.defaults.datasets.bar;
|
||||
var categoryPercentage = options.categoryPercentage;
|
||||
var barPercentage = options.barPercentage;
|
||||
var tickInterval = scale.getPixelForTick(1) - scale.getPixelForTick(0);
|
||||
|
||||
@ -511,18 +511,16 @@ describe('Chart.controllers.line', function() {
|
||||
|
||||
describe('dataset global defaults', function() {
|
||||
beforeEach(function() {
|
||||
this._defaults = Chart.helpers.clone(Chart.defaults.controllers.line.datasets);
|
||||
this._defaults = Chart.helpers.clone(Chart.defaults.datasets.line);
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
Chart.defaults.controllers.line.datasets = this._defaults;
|
||||
Chart.defaults.datasets.line = this._defaults;
|
||||
delete this._defaults;
|
||||
});
|
||||
|
||||
it('should utilize the dataset global default options', function() {
|
||||
Chart.defaults.controllers.line.datasets = Chart.defaults.controllers.line.datasets || {};
|
||||
|
||||
Chart.helpers.merge(Chart.defaults.controllers.line.datasets, {
|
||||
Chart.helpers.merge(Chart.defaults.datasets.line, {
|
||||
spanGaps: true,
|
||||
tension: 0.231,
|
||||
backgroundColor: '#add',
|
||||
@ -563,9 +561,7 @@ describe('Chart.controllers.line', function() {
|
||||
});
|
||||
|
||||
it('should be overriden by user-supplied values', function() {
|
||||
Chart.defaults.controllers.line.datasets = Chart.defaults.controllers.line.datasets || {};
|
||||
|
||||
Chart.helpers.merge(Chart.defaults.controllers.line.datasets, {
|
||||
Chart.helpers.merge(Chart.defaults.datasets.line, {
|
||||
spanGaps: true,
|
||||
tension: 0.231
|
||||
});
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
describe('Chart', function() {
|
||||
|
||||
const overrides = Chart.overrides;
|
||||
|
||||
// https://github.com/chartjs/Chart.js/issues/2481
|
||||
// See global.deprecations.tests.js for backward compatibility
|
||||
it('should be defined and prototype of chart instances', function() {
|
||||
@ -92,11 +94,10 @@ describe('Chart', function() {
|
||||
it('should initialize config with default interaction options', function() {
|
||||
var callback = function() {};
|
||||
var defaults = Chart.defaults;
|
||||
var defaultMode = defaults.controllers.line.interaction.mode;
|
||||
var defaultMode = overrides.line.interaction.mode;
|
||||
|
||||
defaults.hover.onHover = callback;
|
||||
defaults.controllers.line.spanGaps = true;
|
||||
defaults.controllers.line.interaction.mode = 'test';
|
||||
overrides.line.interaction.mode = 'test';
|
||||
|
||||
var chart = acquireChart({
|
||||
type: 'line'
|
||||
@ -104,14 +105,11 @@ describe('Chart', function() {
|
||||
|
||||
var options = chart.options;
|
||||
expect(options.font.size).toBe(defaults.font.size);
|
||||
expect(options.showLine).toBe(defaults.controllers.line.datasets.showLine);
|
||||
expect(options.spanGaps).toBe(true);
|
||||
expect(options.hover.onHover).toBe(callback);
|
||||
expect(options.hover.mode).toBe('test');
|
||||
|
||||
defaults.hover.onHover = null;
|
||||
defaults.controllers.line.spanGaps = false;
|
||||
defaults.controllers.line.interaction.mode = defaultMode;
|
||||
overrides.line.interaction.mode = defaultMode;
|
||||
});
|
||||
|
||||
it('should initialize config with default hover options', function() {
|
||||
@ -119,8 +117,7 @@ describe('Chart', function() {
|
||||
var defaults = Chart.defaults;
|
||||
|
||||
defaults.hover.onHover = callback;
|
||||
defaults.controllers.line.spanGaps = true;
|
||||
defaults.controllers.line.hover.mode = 'test';
|
||||
overrides.line.hover.mode = 'test';
|
||||
|
||||
var chart = acquireChart({
|
||||
type: 'line'
|
||||
@ -128,23 +125,21 @@ describe('Chart', function() {
|
||||
|
||||
var options = chart.options;
|
||||
expect(options.font.size).toBe(defaults.font.size);
|
||||
expect(options.showLine).toBe(defaults.controllers.line.datasets.showLine);
|
||||
expect(options.spanGaps).toBe(true);
|
||||
expect(options.hover.onHover).toBe(callback);
|
||||
expect(options.hover.mode).toBe('test');
|
||||
|
||||
defaults.hover.onHover = null;
|
||||
defaults.controllers.line.spanGaps = false;
|
||||
delete defaults.controllers.line.hover.mode;
|
||||
delete overrides.line.hover.mode;
|
||||
});
|
||||
|
||||
it('should override default options', function() {
|
||||
var callback = function() {};
|
||||
var defaults = Chart.defaults;
|
||||
var defaultSpanGaps = defaults.datasets.line.spanGaps;
|
||||
|
||||
defaults.hover.onHover = callback;
|
||||
defaults.controllers.line.hover.mode = 'x-axis';
|
||||
defaults.controllers.line.spanGaps = true;
|
||||
overrides.line.hover.mode = 'x-axis';
|
||||
defaults.datasets.line.spanGaps = true;
|
||||
|
||||
var chart = acquireChart({
|
||||
type: 'line',
|
||||
@ -167,12 +162,12 @@ describe('Chart', function() {
|
||||
expect(options.plugins.title.position).toBe('bottom');
|
||||
|
||||
defaults.hover.onHover = null;
|
||||
delete defaults.controllers.line.hover.mode;
|
||||
defaults.controllers.line.spanGaps = false;
|
||||
delete overrides.line.hover.mode;
|
||||
defaults.datasets.line.spanGaps = defaultSpanGaps;
|
||||
});
|
||||
|
||||
it('should initialize config with default dataset options', function() {
|
||||
var defaults = Chart.defaults.controllers.pie.datasets;
|
||||
var defaults = Chart.defaults.datasets.pie;
|
||||
|
||||
var chart = acquireChart({
|
||||
type: 'pie'
|
||||
@ -431,7 +426,7 @@ describe('Chart', function() {
|
||||
expect(chart.scales.x.options._jasmineCheck).toBeDefined();
|
||||
expect(chart.scales.y.options._jasmineCheck).toBeDefined();
|
||||
|
||||
expect(Chart.defaults.controllers.line._jasmineCheck).not.toBeDefined();
|
||||
expect(Chart.overrides.line._jasmineCheck).not.toBeDefined();
|
||||
expect(Chart.defaults._jasmineCheck).not.toBeDefined();
|
||||
expect(Chart.defaults.scales.linear._jasmineCheck).not.toBeDefined();
|
||||
expect(Chart.defaults.scales.category._jasmineCheck).not.toBeDefined();
|
||||
|
||||
@ -5,17 +5,22 @@ describe('Chart.registry', function() {
|
||||
CustomController.defaults = {
|
||||
foo: 'bar'
|
||||
};
|
||||
CustomController.overrides = {
|
||||
bar: 'foo'
|
||||
};
|
||||
Chart.register(CustomController);
|
||||
|
||||
expect(Chart.registry.getController('custom')).toEqual(CustomController);
|
||||
expect(Chart.defaults.controllers.custom).toEqual(CustomController.defaults);
|
||||
expect(Chart.defaults.datasets.custom).toEqual(CustomController.defaults);
|
||||
expect(Chart.overrides.custom).toEqual(CustomController.overrides);
|
||||
|
||||
Chart.unregister(CustomController);
|
||||
|
||||
expect(function() {
|
||||
Chart.registry.getController('custom');
|
||||
}).toThrow(new Error('"custom" is not a registered controller.'));
|
||||
expect(Chart.defaults.controllers.custom).not.toBeDefined();
|
||||
expect(Chart.overrides.custom).not.toBeDefined();
|
||||
expect(Chart.defaults.datasets.custom).not.toBeDefined();
|
||||
});
|
||||
|
||||
it('should handle an ES6 scale extension', function() {
|
||||
@ -34,7 +39,7 @@ describe('Chart.registry', function() {
|
||||
expect(function() {
|
||||
Chart.registry.getScale('es6Scale');
|
||||
}).toThrow(new Error('"es6Scale" is not a registered scale.'));
|
||||
expect(Chart.defaults.controllers.custom).not.toBeDefined();
|
||||
expect(Chart.defaults.scales.es6Scale).not.toBeDefined();
|
||||
});
|
||||
|
||||
it('should handle an ES6 element extension', function() {
|
||||
@ -104,14 +109,14 @@ describe('Chart.registry', function() {
|
||||
Chart.registry.addControllers(customExtension);
|
||||
|
||||
expect(Chart.registry.getController('custom')).toEqual(customExtension);
|
||||
expect(Chart.defaults.controllers.custom).toEqual(customExtension.defaults);
|
||||
expect(Chart.defaults.datasets.custom).toEqual(customExtension.defaults);
|
||||
|
||||
Chart.registry.removeControllers(customExtension);
|
||||
|
||||
expect(function() {
|
||||
Chart.registry.getController('custom');
|
||||
}).toThrow(new Error('"custom" is not a registered controller.'));
|
||||
expect(Chart.defaults.controllers.custom).not.toBeDefined();
|
||||
expect(Chart.defaults.datasets.custom).not.toBeDefined();
|
||||
});
|
||||
|
||||
it('as scale', function() {
|
||||
@ -199,17 +204,21 @@ describe('Chart.registry', function() {
|
||||
});
|
||||
|
||||
it('should preserve existing defaults', function() {
|
||||
Chart.defaults.controllers.test = {test1: true};
|
||||
Chart.defaults.datasets.test = {test1: true, test3: false};
|
||||
Chart.overrides.test = {testA: true, testC: false};
|
||||
|
||||
class testController extends Chart.DatasetController {}
|
||||
testController.id = 'test';
|
||||
testController.defaults = {test1: false, test2: true};
|
||||
testController.overrides = {testA: false, testB: true};
|
||||
|
||||
Chart.register(testController);
|
||||
expect(Chart.defaults.controllers.test).toEqual({test1: true, test2: true});
|
||||
expect(Chart.defaults.datasets.test).toEqual({test1: false, test2: true, test3: false});
|
||||
expect(Chart.overrides.test).toEqual({testA: false, testB: true, testC: false});
|
||||
|
||||
Chart.unregister(testController);
|
||||
expect(Chart.defaults.controllers.test).not.toBeDefined();
|
||||
expect(Chart.defaults.datasets.test).not.toBeDefined();
|
||||
expect(Chart.overrides.test).not.toBeDefined();
|
||||
});
|
||||
|
||||
describe('should handle multiple items', function() {
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
describe('Default Configs', function() {
|
||||
describe('Bubble Chart', function() {
|
||||
it('should return correct tooltip strings', function() {
|
||||
var config = Chart.defaults.controllers.bubble;
|
||||
var chart = window.acquireChart({
|
||||
type: 'bubble',
|
||||
data: {
|
||||
@ -14,7 +13,6 @@ describe('Default Configs', function() {
|
||||
}]
|
||||
}]
|
||||
},
|
||||
options: config
|
||||
});
|
||||
|
||||
// fake out the tooltip hover and force the tooltip to update
|
||||
@ -33,7 +31,6 @@ describe('Default Configs', function() {
|
||||
|
||||
describe('Doughnut Chart', function() {
|
||||
it('should return correct tooltip strings', function() {
|
||||
var config = Chart.defaults.controllers.doughnut;
|
||||
var chart = window.acquireChart({
|
||||
type: 'doughnut',
|
||||
data: {
|
||||
@ -42,7 +39,6 @@ describe('Default Configs', function() {
|
||||
data: [10, 20, 30],
|
||||
}]
|
||||
},
|
||||
options: config
|
||||
});
|
||||
|
||||
// fake out the tooltip hover and force the tooltip to update
|
||||
@ -59,7 +55,6 @@ describe('Default Configs', function() {
|
||||
});
|
||||
|
||||
it('should return correct tooltip string for a multiline label', function() {
|
||||
var config = Chart.defaults.controllers.doughnut;
|
||||
var chart = window.acquireChart({
|
||||
type: 'doughnut',
|
||||
data: {
|
||||
@ -68,7 +63,6 @@ describe('Default Configs', function() {
|
||||
data: [10, 20, 30],
|
||||
}]
|
||||
},
|
||||
options: config
|
||||
});
|
||||
|
||||
// fake out the tooltip hover and force the tooltip to update
|
||||
@ -89,7 +83,6 @@ describe('Default Configs', function() {
|
||||
});
|
||||
|
||||
it('should return correct legend label objects', function() {
|
||||
var config = Chart.defaults.controllers.doughnut;
|
||||
var chart = window.acquireChart({
|
||||
type: 'doughnut',
|
||||
data: {
|
||||
@ -101,7 +94,6 @@ describe('Default Configs', function() {
|
||||
borderColor: '#000'
|
||||
}]
|
||||
},
|
||||
options: config
|
||||
});
|
||||
|
||||
var expected = [{
|
||||
@ -130,7 +122,7 @@ describe('Default Configs', function() {
|
||||
});
|
||||
|
||||
it('should hide the correct arc when a legend item is clicked', function() {
|
||||
var config = Chart.defaults.controllers.doughnut;
|
||||
var config = Chart.overrides.doughnut;
|
||||
var chart = window.acquireChart({
|
||||
type: 'doughnut',
|
||||
data: {
|
||||
@ -142,7 +134,6 @@ describe('Default Configs', function() {
|
||||
borderColor: '#000'
|
||||
}]
|
||||
},
|
||||
options: config
|
||||
});
|
||||
spyOn(chart, 'update').and.callThrough();
|
||||
|
||||
@ -159,7 +150,6 @@ describe('Default Configs', function() {
|
||||
|
||||
describe('Polar Area Chart', function() {
|
||||
it('should return correct tooltip strings', function() {
|
||||
var config = Chart.defaults.controllers.polarArea;
|
||||
var chart = window.acquireChart({
|
||||
type: 'polarArea',
|
||||
data: {
|
||||
@ -168,7 +158,6 @@ describe('Default Configs', function() {
|
||||
data: [10, 20, 30],
|
||||
}]
|
||||
},
|
||||
options: config
|
||||
});
|
||||
|
||||
// fake out the tooltip hover and force the tooltip to update
|
||||
@ -185,7 +174,6 @@ describe('Default Configs', function() {
|
||||
});
|
||||
|
||||
it('should return correct legend label objects', function() {
|
||||
var config = Chart.defaults.controllers.polarArea;
|
||||
var chart = window.acquireChart({
|
||||
type: 'polarArea',
|
||||
data: {
|
||||
@ -197,7 +185,6 @@ describe('Default Configs', function() {
|
||||
borderColor: '#000'
|
||||
}]
|
||||
},
|
||||
options: config
|
||||
});
|
||||
|
||||
var expected = [{
|
||||
@ -226,7 +213,7 @@ describe('Default Configs', function() {
|
||||
});
|
||||
|
||||
it('should hide the correct arc when a legend item is clicked', function() {
|
||||
var config = Chart.defaults.controllers.polarArea;
|
||||
var config = Chart.overrides.polarArea;
|
||||
var chart = window.acquireChart({
|
||||
type: 'polarArea',
|
||||
data: {
|
||||
@ -238,7 +225,6 @@ describe('Default Configs', function() {
|
||||
borderColor: '#000'
|
||||
}]
|
||||
},
|
||||
options: config
|
||||
});
|
||||
spyOn(chart, 'update').and.callThrough();
|
||||
|
||||
|
||||
@ -119,8 +119,8 @@ describe('Platform.dom', function() {
|
||||
});
|
||||
|
||||
it('should use default "chart" aspect ratio for render and display sizes', function() {
|
||||
var ratio = Chart.defaults.controllers.doughnut.aspectRatio;
|
||||
Chart.defaults.controllers.doughnut.aspectRatio = 1;
|
||||
var ratio = Chart.overrides.doughnut.aspectRatio;
|
||||
Chart.overrides.doughnut.aspectRatio = 1;
|
||||
|
||||
var chart = acquireChart({
|
||||
type: 'doughnut',
|
||||
@ -133,7 +133,7 @@ describe('Platform.dom', function() {
|
||||
}
|
||||
});
|
||||
|
||||
Chart.defaults.controllers.doughnut.aspectRatio = ratio;
|
||||
Chart.overrides.doughnut.aspectRatio = ratio;
|
||||
|
||||
expect(chart).toBeChartOfSize({
|
||||
dw: 425, dh: 425,
|
||||
|
||||
58
types/index.esm.d.ts
vendored
58
types/index.esm.d.ts
vendored
@ -93,7 +93,8 @@ export interface ControllerDatasetOptions extends ParsingOptions {
|
||||
export interface BarControllerDatasetOptions
|
||||
extends ControllerDatasetOptions,
|
||||
ScriptableAndArrayOptions<BarOptions, ScriptableContext<'bar'>>,
|
||||
ScriptableAndArrayOptions<CommonHoverOptions, ScriptableContext<'bar'>> {
|
||||
ScriptableAndArrayOptions<CommonHoverOptions, ScriptableContext<'bar'>>,
|
||||
AnimationOptions<'bar'> {
|
||||
/**
|
||||
* The ID of the x axis to plot this dataset on.
|
||||
*/
|
||||
@ -182,7 +183,8 @@ export interface LineControllerDatasetOptions
|
||||
ScriptableAndArrayOptions<PointPrefixedOptions, ScriptableContext<'line'>>,
|
||||
ScriptableAndArrayOptions<PointPrefixedHoverOptions, ScriptableContext<'line'>>,
|
||||
ScriptableOptions<LineOptions, ScriptableContext<'line'>>,
|
||||
ScriptableOptions<LineHoverOptions, ScriptableContext<'line'>> {
|
||||
ScriptableOptions<LineHoverOptions, ScriptableContext<'line'>>,
|
||||
AnimationOptions<'line'> {
|
||||
/**
|
||||
* The ID of the x axis to plot this dataset on.
|
||||
*/
|
||||
@ -238,7 +240,8 @@ export const ScatterController: ChartComponent & {
|
||||
export interface DoughnutControllerDatasetOptions
|
||||
extends ControllerDatasetOptions,
|
||||
ScriptableAndArrayOptions<ArcOptions, ScriptableContext<'doughnut'>>,
|
||||
ScriptableAndArrayOptions<ArcHoverOptions, ScriptableContext<'doughnut'>> {
|
||||
ScriptableAndArrayOptions<ArcHoverOptions, ScriptableContext<'doughnut'>>,
|
||||
AnimationOptions<'doughnut'> {
|
||||
|
||||
/**
|
||||
* Sweep to allow arcs to cover.
|
||||
@ -364,8 +367,9 @@ export interface RadarControllerDatasetOptions
|
||||
ScriptableOptions<PointPrefixedOptions, ScriptableContext<'radar'>>,
|
||||
ScriptableOptions<PointPrefixedHoverOptions, ScriptableContext<'radar'>>,
|
||||
ScriptableOptions<LineOptions, ScriptableContext<'radar'>>,
|
||||
ScriptableOptions<LineHoverOptions, ScriptableContext<'radar'>> {
|
||||
/**
|
||||
ScriptableOptions<LineHoverOptions, ScriptableContext<'radar'>>,
|
||||
AnimationOptions<'radar'> {
|
||||
/**
|
||||
* The ID of the x axis to plot this dataset on.
|
||||
*/
|
||||
xAxisID: string;
|
||||
@ -496,6 +500,7 @@ export declare class Chart<
|
||||
notifyPlugins(hook: string, args?: AnyObject): boolean | void;
|
||||
|
||||
static readonly defaults: Defaults;
|
||||
static readonly overrides: Overrides;
|
||||
static readonly version: string;
|
||||
static readonly instances: { [key: string]: Chart };
|
||||
static readonly registry: Registry;
|
||||
@ -608,16 +613,6 @@ export interface DatasetControllerChartComponent extends ChartComponent {
|
||||
}
|
||||
|
||||
export interface Defaults extends CoreChartOptions<ChartType>, ElementChartOptions, PluginChartOptions<ChartType> {
|
||||
controllers: {
|
||||
[key in ChartType]: DeepPartial<
|
||||
CoreChartOptions<key> &
|
||||
ElementChartOptions &
|
||||
PluginChartOptions<key> &
|
||||
DatasetChartOptions<key>[key] &
|
||||
ScaleChartOptions<key> &
|
||||
ChartTypeRegistry[key]['chartOptions']
|
||||
>;
|
||||
};
|
||||
|
||||
scale: ScaleOptionsByType;
|
||||
scales: {
|
||||
@ -648,6 +643,17 @@ export interface Defaults extends CoreChartOptions<ChartType>, ElementChartOptio
|
||||
route(scope: string, name: string, targetScope: string, targetName: string): void;
|
||||
}
|
||||
|
||||
export type Overrides = {
|
||||
[key in ChartType]: DeepPartial<
|
||||
CoreChartOptions<key> &
|
||||
ElementChartOptions &
|
||||
PluginChartOptions<key> &
|
||||
DatasetChartOptions<ChartType> &
|
||||
ScaleChartOptions<key> &
|
||||
ChartTypeRegistry[key]['chartOptions']
|
||||
>;
|
||||
}
|
||||
|
||||
export const defaults: Defaults;
|
||||
export interface InteractionOptions {
|
||||
axis?: string;
|
||||
@ -1349,7 +1355,9 @@ export interface HoverInteractionOptions extends CoreInteractionOptions {
|
||||
|
||||
export interface CoreChartOptions<TType extends ChartType> extends ParsingOptions, AnimationOptions<TType> {
|
||||
|
||||
datasets: AnimationOptions<TType>;
|
||||
datasets: {
|
||||
[key in ChartType]: ChartTypeRegistry[key]['datasetOptions']
|
||||
}
|
||||
|
||||
/**
|
||||
* The base axis of the chart. 'x' for vertical charts and 'y' for horizontal charts.
|
||||
@ -1474,30 +1482,24 @@ export type AnimationSpec<TType extends ChartType> = {
|
||||
* The number of milliseconds an animation takes.
|
||||
* @default 1000
|
||||
*/
|
||||
duration: Scriptable<number, ScriptableContext<TType>>;
|
||||
duration?: Scriptable<number, ScriptableContext<TType>>;
|
||||
/**
|
||||
* Easing function to use
|
||||
* @default 'easeOutQuart'
|
||||
*/
|
||||
easing: Scriptable<EasingFunction, ScriptableContext<TType>>;
|
||||
|
||||
/**
|
||||
* Running animation count + FPS display in upper left corner of the chart.
|
||||
* @default false
|
||||
*/
|
||||
debug: Scriptable<boolean, ScriptableContext<TType>>;
|
||||
easing?: Scriptable<EasingFunction, ScriptableContext<TType>>;
|
||||
|
||||
/**
|
||||
* Delay before starting the animations.
|
||||
* @default 0
|
||||
*/
|
||||
delay: Scriptable<number, ScriptableContext<TType>>;
|
||||
delay?: Scriptable<number, ScriptableContext<TType>>;
|
||||
|
||||
/**
|
||||
* If set to true, the animations loop endlessly.
|
||||
* @default false
|
||||
*/
|
||||
loop: Scriptable<boolean, ScriptableContext<TType>>;
|
||||
loop?: Scriptable<boolean, ScriptableContext<TType>>;
|
||||
}
|
||||
|
||||
export type AnimationsSpec<TType extends ChartType> = {
|
||||
@ -1536,11 +1538,11 @@ export type AnimationOptions<TType extends ChartType> = {
|
||||
/**
|
||||
* Callback called on each step of an animation.
|
||||
*/
|
||||
onProgress: (this: Chart, event: AnimationEvent) => void;
|
||||
onProgress?: (this: Chart, event: AnimationEvent) => void;
|
||||
/**
|
||||
* Callback called when all animations are completed.
|
||||
*/
|
||||
onComplete: (this: Chart, event: AnimationEvent) => void;
|
||||
onComplete?: (this: Chart, event: AnimationEvent) => void;
|
||||
};
|
||||
animations: AnimationsSpec<TType>;
|
||||
transitions: TransitionsSpec<TType>;
|
||||
|
||||
9
types/tests/defaults.ts
Normal file
9
types/tests/defaults.ts
Normal file
@ -0,0 +1,9 @@
|
||||
import { Chart } from '../index.esm';
|
||||
|
||||
Chart.defaults.scales.time.time.minUnit = 'day';
|
||||
|
||||
Chart.defaults.plugins.title.display = false;
|
||||
|
||||
Chart.defaults.datasets.bar.backgroundColor = 'red';
|
||||
|
||||
Chart.defaults.animation = { duration: 500 };
|
||||
33
types/tests/options.ts
Normal file
33
types/tests/options.ts
Normal file
@ -0,0 +1,33 @@
|
||||
import { Chart } from '../index.esm';
|
||||
|
||||
export const chart = new Chart('test', {
|
||||
type: 'bar',
|
||||
data: {
|
||||
labels: ['a'],
|
||||
datasets: [{
|
||||
data: [1],
|
||||
}, {
|
||||
type: 'line',
|
||||
data: [{ x: 1, y: 1 }]
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
animation: {
|
||||
duration: 500
|
||||
},
|
||||
backgroundColor: 'red',
|
||||
datasets: {
|
||||
line: {
|
||||
animation: {
|
||||
duration: 600
|
||||
},
|
||||
backgroundColor: 'blue',
|
||||
}
|
||||
},
|
||||
elements: {
|
||||
point: {
|
||||
backgroundColor: 'red'
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
10
types/tests/overrides.ts
Normal file
10
types/tests/overrides.ts
Normal file
@ -0,0 +1,10 @@
|
||||
import { Chart } from '../index.esm';
|
||||
|
||||
Chart.overrides.bar.scales.x.type = 'time';
|
||||
|
||||
Chart.overrides.bar.plugins.title.display = false;
|
||||
|
||||
Chart.overrides.line.datasets.bar.backgroundColor = 'red';
|
||||
|
||||
Chart.overrides.line.animation = false;
|
||||
Chart.overrides.line.datasets.bar.animation = { duration: 100 };
|
||||
@ -1,6 +1,6 @@
|
||||
import { Chart } from '../../../index.esm';
|
||||
|
||||
Chart.defaults.controllers.bubble.plugins.tooltip.callbacks.label = (item) => {
|
||||
Chart.overrides.bubble.plugins.tooltip.callbacks.label = (item) => {
|
||||
const { x, y, _custom: r } = item.parsed;
|
||||
return `${item.label}: (${x}, ${y}, ${r})`;
|
||||
};
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user