mirror of
https://github.com/chartjs/Chart.js.git
synced 2025-12-08 20:36:08 +00:00
Implement per-dataset type (default and per-chart) options (#5999)
This commit is contained in:
parent
58e154c7da
commit
d6a5ea0d36
@ -31,3 +31,40 @@ var chartDifferentHoverMode = new Chart(ctx, {
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
## Dataset Configuration
|
||||
|
||||
Options may be configured directly on the dataset. The dataset options can be changed at 3 different levels and are evaluated with the following priority:
|
||||
|
||||
- per dataset: dataset.*
|
||||
- per chart: options.datasets[type].*
|
||||
- or globally: Chart.defaults.global.datasets[type].*
|
||||
|
||||
where type corresponds to the dataset type.
|
||||
|
||||
*Note:* dataset options take precedence over element options.
|
||||
|
||||
The following example would set the `showLine` option to 'false' for all line datasets except for those overridden by options passed to the dataset on creation.
|
||||
|
||||
```javascript
|
||||
// Do not show lines for all datasets by default
|
||||
Chart.defaults.global.datasets.line.showLine = false;
|
||||
|
||||
// This chart would show a line only for the third dataset
|
||||
var chart = new Chart(ctx, {
|
||||
type: 'line',
|
||||
data: {
|
||||
datasets: [{
|
||||
data: [0, 0],
|
||||
}, {
|
||||
data: [0, 1]
|
||||
}, {
|
||||
data: [1, 0],
|
||||
showLine: true // overrides the `line` dataset default
|
||||
}, {
|
||||
type: 'scatter', // 'line' dataset default does not affect this dataset since it's a 'scatter'
|
||||
data: [1, 1]
|
||||
}]
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
@ -382,6 +382,7 @@ module.exports = DatasetController.extend({
|
||||
var chart = me.chart;
|
||||
var datasets = chart.data.datasets;
|
||||
var dataset = datasets[me.index];
|
||||
var datasetOpts = me._config;
|
||||
var custom = rectangle.custom || {};
|
||||
var options = chart.options.elements.rectangle;
|
||||
var values = {};
|
||||
@ -406,7 +407,7 @@ module.exports = DatasetController.extend({
|
||||
key = keys[i];
|
||||
values[key] = resolve([
|
||||
custom[key],
|
||||
dataset[key],
|
||||
datasetOpts[key],
|
||||
options[key]
|
||||
], context, index);
|
||||
}
|
||||
|
||||
@ -127,6 +127,7 @@ module.exports = DatasetController.extend({
|
||||
var chart = me.chart;
|
||||
var datasets = chart.data.datasets;
|
||||
var dataset = datasets[me.index];
|
||||
var datasetOpts = me._config;
|
||||
var custom = point.custom || {};
|
||||
var options = chart.options.elements.point;
|
||||
var data = dataset.data[index];
|
||||
@ -158,7 +159,7 @@ module.exports = DatasetController.extend({
|
||||
key = keys[i];
|
||||
values[key] = resolve([
|
||||
custom[key],
|
||||
dataset[key],
|
||||
datasetOpts[key],
|
||||
options[key]
|
||||
], context, index);
|
||||
}
|
||||
|
||||
@ -315,7 +315,12 @@ module.exports = DatasetController.extend({
|
||||
|
||||
for (i = 0, ilen = arcs.length; i < ilen; ++i) {
|
||||
arc = arcs[i];
|
||||
options = controller ? controller._resolveElementOptions(arc, i) : arc._options;
|
||||
if (controller) {
|
||||
controller._configure();
|
||||
options = controller._resolveElementOptions(arc, i);
|
||||
} else {
|
||||
options = arc._options;
|
||||
}
|
||||
if (options.borderAlign !== 'inner') {
|
||||
borderWidth = options.borderWidth;
|
||||
hoverWidth = options.hoverBorderWidth;
|
||||
@ -353,6 +358,7 @@ module.exports = DatasetController.extend({
|
||||
var me = this;
|
||||
var chart = me.chart;
|
||||
var dataset = me.getDataset();
|
||||
var datasetOpts = me._config;
|
||||
var custom = arc.custom || {};
|
||||
var options = chart.options.elements.arc;
|
||||
var values = {};
|
||||
@ -380,7 +386,7 @@ module.exports = DatasetController.extend({
|
||||
key = keys[i];
|
||||
values[key] = resolve([
|
||||
custom[key],
|
||||
dataset[key],
|
||||
datasetOpts[key],
|
||||
options[key]
|
||||
], context, index);
|
||||
}
|
||||
|
||||
@ -29,10 +29,6 @@ defaults._set('line', {
|
||||
}
|
||||
});
|
||||
|
||||
function lineEnabled(dataset, options) {
|
||||
return valueOrDefault(dataset.showLine, options.showLines);
|
||||
}
|
||||
|
||||
module.exports = DatasetController.extend({
|
||||
|
||||
datasetElementType: elements.Line,
|
||||
@ -44,9 +40,10 @@ module.exports = DatasetController.extend({
|
||||
var meta = me.getMeta();
|
||||
var line = meta.dataset;
|
||||
var points = meta.data || [];
|
||||
var options = me.chart.options;
|
||||
var scale = me.getScaleForId(meta.yAxisID);
|
||||
var dataset = me.getDataset();
|
||||
var showLine = lineEnabled(dataset, me.chart.options);
|
||||
var showLine = me._showLine = valueOrDefault(me._config.showLine, options.showLines);
|
||||
var i, ilen;
|
||||
|
||||
// Update Line
|
||||
@ -132,6 +129,7 @@ module.exports = DatasetController.extend({
|
||||
var me = this;
|
||||
var chart = me.chart;
|
||||
var dataset = chart.data.datasets[me.index];
|
||||
var datasetOpts = me._config;
|
||||
var custom = element.custom || {};
|
||||
var options = chart.options.elements.point;
|
||||
var values = {};
|
||||
@ -164,8 +162,8 @@ module.exports = DatasetController.extend({
|
||||
key = keys[i];
|
||||
values[key] = resolve([
|
||||
custom[key],
|
||||
dataset[ELEMENT_OPTIONS[key]],
|
||||
dataset[key],
|
||||
datasetOpts[ELEMENT_OPTIONS[key]],
|
||||
datasetOpts[key],
|
||||
options[key]
|
||||
], context, index);
|
||||
}
|
||||
@ -181,6 +179,7 @@ module.exports = DatasetController.extend({
|
||||
var chart = me.chart;
|
||||
var datasetIndex = me.index;
|
||||
var dataset = chart.data.datasets[datasetIndex];
|
||||
var datasetOpts = me._config;
|
||||
var custom = element.custom || {};
|
||||
var options = chart.options;
|
||||
var elementOptions = options.elements.line;
|
||||
@ -210,7 +209,7 @@ module.exports = DatasetController.extend({
|
||||
key = keys[i];
|
||||
values[key] = resolve([
|
||||
custom[key],
|
||||
dataset[key],
|
||||
datasetOpts[key],
|
||||
elementOptions[key]
|
||||
], context);
|
||||
}
|
||||
@ -218,9 +217,9 @@ module.exports = DatasetController.extend({
|
||||
// The default behavior of lines is to break at null values, according
|
||||
// to https://github.com/chartjs/Chart.js/issues/2435#issuecomment-216718158
|
||||
// This option gives lines the ability to span gaps
|
||||
values.spanGaps = valueOrDefault(dataset.spanGaps, options.spanGaps);
|
||||
values.tension = valueOrDefault(dataset.lineTension, elementOptions.tension);
|
||||
values.steppedLine = resolve([custom.steppedLine, dataset.steppedLine, elementOptions.stepped]);
|
||||
values.spanGaps = valueOrDefault(datasetOpts.spanGaps, options.spanGaps);
|
||||
values.tension = valueOrDefault(datasetOpts.lineTension, elementOptions.tension);
|
||||
values.steppedLine = resolve([custom.steppedLine, datasetOpts.steppedLine, elementOptions.stepped]);
|
||||
|
||||
return values;
|
||||
},
|
||||
@ -319,11 +318,11 @@ module.exports = DatasetController.extend({
|
||||
var meta = me.getMeta();
|
||||
var points = meta.data || [];
|
||||
var area = chart.chartArea;
|
||||
var i = 0;
|
||||
var ilen = points.length;
|
||||
var halfBorderWidth;
|
||||
var i = 0;
|
||||
|
||||
if (lineEnabled(me.getDataset(), chart.options)) {
|
||||
if (me._showLine) {
|
||||
halfBorderWidth = (meta.dataset._model.borderWidth || 0) / 2;
|
||||
|
||||
helpers.canvas.clipArea(chart.ctx, {
|
||||
|
||||
@ -248,6 +248,7 @@ module.exports = DatasetController.extend({
|
||||
var me = this;
|
||||
var chart = me.chart;
|
||||
var dataset = me.getDataset();
|
||||
var datasetOpts = me._config;
|
||||
var custom = arc.custom || {};
|
||||
var options = chart.options.elements.arc;
|
||||
var values = {};
|
||||
@ -275,7 +276,7 @@ module.exports = DatasetController.extend({
|
||||
key = keys[i];
|
||||
values[key] = resolve([
|
||||
custom[key],
|
||||
dataset[key],
|
||||
datasetOpts[key],
|
||||
options[key]
|
||||
], context, index);
|
||||
}
|
||||
|
||||
@ -115,6 +115,7 @@ module.exports = DatasetController.extend({
|
||||
var me = this;
|
||||
var chart = me.chart;
|
||||
var dataset = chart.data.datasets[me.index];
|
||||
var datasetOpts = me._config;
|
||||
var custom = element.custom || {};
|
||||
var options = chart.options.elements.point;
|
||||
var values = {};
|
||||
@ -147,8 +148,8 @@ module.exports = DatasetController.extend({
|
||||
key = keys[i];
|
||||
values[key] = resolve([
|
||||
custom[key],
|
||||
dataset[ELEMENT_OPTIONS[key]],
|
||||
dataset[key],
|
||||
datasetOpts[ELEMENT_OPTIONS[key]],
|
||||
datasetOpts[key],
|
||||
options[key]
|
||||
], context, index);
|
||||
}
|
||||
@ -163,6 +164,7 @@ module.exports = DatasetController.extend({
|
||||
var me = this;
|
||||
var chart = me.chart;
|
||||
var dataset = chart.data.datasets[me.index];
|
||||
var datasetOpts = me._config;
|
||||
var custom = element.custom || {};
|
||||
var options = chart.options.elements.line;
|
||||
var values = {};
|
||||
@ -183,7 +185,7 @@ module.exports = DatasetController.extend({
|
||||
key = keys[i];
|
||||
values[key] = resolve([
|
||||
custom[key],
|
||||
dataset[key],
|
||||
datasetOpts[key],
|
||||
options[key]
|
||||
]);
|
||||
}
|
||||
|
||||
@ -21,8 +21,6 @@ defaults._set('scatter', {
|
||||
}]
|
||||
},
|
||||
|
||||
showLines: false,
|
||||
|
||||
tooltips: {
|
||||
callbacks: {
|
||||
title: function() {
|
||||
@ -35,5 +33,13 @@ defaults._set('scatter', {
|
||||
}
|
||||
});
|
||||
|
||||
defaults._set('global', {
|
||||
datasets: {
|
||||
scatter: {
|
||||
showLine: false
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Scatter charts use line controllers
|
||||
module.exports = LineController;
|
||||
|
||||
@ -567,7 +567,7 @@ helpers.extend(Chart.prototype, /** @lends Chart */ {
|
||||
return;
|
||||
}
|
||||
|
||||
meta.controller.update();
|
||||
meta.controller._update();
|
||||
|
||||
plugins.notify(me, 'afterDatasetUpdate', [args]);
|
||||
},
|
||||
|
||||
@ -100,6 +100,7 @@ helpers.extend(DatasetController.prototype, {
|
||||
me.index = datasetIndex;
|
||||
me.linkScales();
|
||||
me.addElements();
|
||||
me._type = me.getMeta().type;
|
||||
},
|
||||
|
||||
updateIndex: function(datasetIndex) {
|
||||
@ -160,7 +161,7 @@ helpers.extend(DatasetController.prototype, {
|
||||
},
|
||||
|
||||
reset: function() {
|
||||
this.update(true);
|
||||
this._update(true);
|
||||
},
|
||||
|
||||
/**
|
||||
@ -236,6 +237,30 @@ helpers.extend(DatasetController.prototype, {
|
||||
me.resyncElements();
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the merged user-supplied and default dataset-level options
|
||||
* @private
|
||||
*/
|
||||
_configure: function() {
|
||||
var me = this;
|
||||
me._config = helpers.merge({}, [
|
||||
me.chart.options.datasets[me._type],
|
||||
me.getDataset(),
|
||||
], {
|
||||
merger: function(key, target, source) {
|
||||
if (key !== '_meta' && key !== 'data') {
|
||||
helpers._merger(key, target, source);
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
_update: function(reset) {
|
||||
var me = this;
|
||||
me._configure();
|
||||
me.update(reset);
|
||||
},
|
||||
|
||||
update: helpers.noop,
|
||||
|
||||
transition: function(easingValue) {
|
||||
|
||||
@ -11,6 +11,8 @@ var defaults = {
|
||||
}
|
||||
};
|
||||
|
||||
// TODO(v3): remove 'global' from namespace. all default are global and
|
||||
// there's inconsistency around which options are under 'global'
|
||||
defaults._set('global', {
|
||||
defaultColor: 'rgba(0,0,0,0.1)',
|
||||
defaultFontColor: '#666',
|
||||
|
||||
@ -573,6 +573,181 @@ describe('Chart.controllers.line', function() {
|
||||
expect(meta.dataset._model.borderWidth).toBe(0.55);
|
||||
});
|
||||
|
||||
describe('dataset global defaults', function() {
|
||||
beforeEach(function() {
|
||||
this._defaults = Chart.helpers.clone(Chart.defaults.global.datasets.line);
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
Chart.defaults.global.datasets.line = this._defaults;
|
||||
delete this._defaults;
|
||||
});
|
||||
|
||||
it('should utilize the dataset global default options', function() {
|
||||
Chart.defaults.global.datasets.line = Chart.defaults.global.datasets.line || {};
|
||||
|
||||
Chart.helpers.merge(Chart.defaults.global.datasets.line, {
|
||||
spanGaps: true,
|
||||
lineTension: 0.231,
|
||||
backgroundColor: '#add',
|
||||
borderWidth: '#daa',
|
||||
borderColor: '#dad',
|
||||
borderCapStyle: 'round',
|
||||
borderDash: [0],
|
||||
borderDashOffset: 0.871,
|
||||
borderJoinStyle: 'miter',
|
||||
fill: 'start',
|
||||
cubicInterpolationMode: 'monotone'
|
||||
});
|
||||
|
||||
var chart = window.acquireChart({
|
||||
type: 'line',
|
||||
data: {
|
||||
datasets: [{
|
||||
data: [0, 0],
|
||||
label: 'dataset1'
|
||||
}],
|
||||
labels: ['label1', 'label2']
|
||||
}
|
||||
});
|
||||
|
||||
var model = chart.getDatasetMeta(0).dataset._model;
|
||||
|
||||
expect(model.spanGaps).toBe(true);
|
||||
expect(model.tension).toBe(0.231);
|
||||
expect(model.backgroundColor).toBe('#add');
|
||||
expect(model.borderWidth).toBe('#daa');
|
||||
expect(model.borderColor).toBe('#dad');
|
||||
expect(model.borderCapStyle).toBe('round');
|
||||
expect(model.borderDash).toEqual([0]);
|
||||
expect(model.borderDashOffset).toBe(0.871);
|
||||
expect(model.borderJoinStyle).toBe('miter');
|
||||
expect(model.fill).toBe('start');
|
||||
expect(model.cubicInterpolationMode).toBe('monotone');
|
||||
});
|
||||
|
||||
it('should be overriden by user-supplied values', function() {
|
||||
Chart.defaults.global.datasets.line = Chart.defaults.global.datasets.line || {};
|
||||
|
||||
Chart.helpers.merge(Chart.defaults.global.datasets.line, {
|
||||
spanGaps: true,
|
||||
lineTension: 0.231
|
||||
});
|
||||
|
||||
var chart = window.acquireChart({
|
||||
type: 'line',
|
||||
data: {
|
||||
datasets: [{
|
||||
data: [0, 0],
|
||||
label: 'dataset1',
|
||||
spanGaps: true,
|
||||
backgroundColor: '#dad'
|
||||
}],
|
||||
labels: ['label1', 'label2']
|
||||
},
|
||||
options: {
|
||||
datasets: {
|
||||
line: {
|
||||
lineTension: 0.345,
|
||||
backgroundColor: '#add'
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
var model = chart.getDatasetMeta(0).dataset._model;
|
||||
|
||||
// dataset-level option overrides global default
|
||||
expect(model.spanGaps).toBe(true);
|
||||
// chart-level default overrides global default
|
||||
expect(model.tension).toBe(0.345);
|
||||
// dataset-level option overrides chart-level default
|
||||
expect(model.backgroundColor).toBe('#dad');
|
||||
});
|
||||
});
|
||||
|
||||
it('should obey the chart-level dataset options', function() {
|
||||
var chart = window.acquireChart({
|
||||
type: 'line',
|
||||
data: {
|
||||
datasets: [{
|
||||
data: [0, 0],
|
||||
label: 'dataset1'
|
||||
}],
|
||||
labels: ['label1', 'label2']
|
||||
},
|
||||
options: {
|
||||
datasets: {
|
||||
line: {
|
||||
spanGaps: true,
|
||||
lineTension: 0.231,
|
||||
backgroundColor: '#add',
|
||||
borderWidth: '#daa',
|
||||
borderColor: '#dad',
|
||||
borderCapStyle: 'round',
|
||||
borderDash: [0],
|
||||
borderDashOffset: 0.871,
|
||||
borderJoinStyle: 'miter',
|
||||
fill: 'start',
|
||||
cubicInterpolationMode: 'monotone'
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
var model = chart.getDatasetMeta(0).dataset._model;
|
||||
|
||||
expect(model.spanGaps).toBe(true);
|
||||
expect(model.tension).toBe(0.231);
|
||||
expect(model.backgroundColor).toBe('#add');
|
||||
expect(model.borderWidth).toBe('#daa');
|
||||
expect(model.borderColor).toBe('#dad');
|
||||
expect(model.borderCapStyle).toBe('round');
|
||||
expect(model.borderDash).toEqual([0]);
|
||||
expect(model.borderDashOffset).toBe(0.871);
|
||||
expect(model.borderJoinStyle).toBe('miter');
|
||||
expect(model.fill).toBe('start');
|
||||
expect(model.cubicInterpolationMode).toBe('monotone');
|
||||
});
|
||||
|
||||
it('should obey the dataset options', function() {
|
||||
var chart = window.acquireChart({
|
||||
type: 'line',
|
||||
data: {
|
||||
datasets: [{
|
||||
data: [0, 0],
|
||||
label: 'dataset1',
|
||||
spanGaps: true,
|
||||
lineTension: 0.231,
|
||||
backgroundColor: '#add',
|
||||
borderWidth: '#daa',
|
||||
borderColor: '#dad',
|
||||
borderCapStyle: 'round',
|
||||
borderDash: [0],
|
||||
borderDashOffset: 0.871,
|
||||
borderJoinStyle: 'miter',
|
||||
fill: 'start',
|
||||
cubicInterpolationMode: 'monotone'
|
||||
}],
|
||||
labels: ['label1', 'label2']
|
||||
}
|
||||
});
|
||||
|
||||
var model = chart.getDatasetMeta(0).dataset._model;
|
||||
|
||||
expect(model.spanGaps).toBe(true);
|
||||
expect(model.tension).toBe(0.231);
|
||||
expect(model.backgroundColor).toBe('#add');
|
||||
expect(model.borderWidth).toBe('#daa');
|
||||
expect(model.borderColor).toBe('#dad');
|
||||
expect(model.borderCapStyle).toBe('round');
|
||||
expect(model.borderDash).toEqual([0]);
|
||||
expect(model.borderDashOffset).toBe(0.871);
|
||||
expect(model.borderJoinStyle).toBe('miter');
|
||||
expect(model.fill).toBe('start');
|
||||
expect(model.cubicInterpolationMode).toBe('monotone');
|
||||
});
|
||||
|
||||
it('should handle number of data point changes in update', function() {
|
||||
var chart = window.acquireChart({
|
||||
type: 'line',
|
||||
|
||||
@ -154,7 +154,7 @@ describe('Chart.controllers.radar', function() {
|
||||
});
|
||||
|
||||
// Now update controller and ensure proper updates
|
||||
meta.controller.update();
|
||||
meta.controller._update();
|
||||
|
||||
[
|
||||
{x: 256, y: 120, cppx: 246, cppy: 120, cpnx: 272, cpny: 120},
|
||||
@ -198,7 +198,7 @@ describe('Chart.controllers.radar', function() {
|
||||
chart.data.datasets[0].pointBorderColor = 'rgb(56, 57, 58)';
|
||||
chart.data.datasets[0].pointBorderWidth = 1.123;
|
||||
|
||||
meta.controller.update();
|
||||
meta.controller._update();
|
||||
|
||||
expect(meta.dataset._model).toEqual(jasmine.objectContaining({
|
||||
backgroundColor: 'rgb(98, 98, 98)',
|
||||
@ -256,7 +256,7 @@ describe('Chart.controllers.radar', function() {
|
||||
hitRadius: 5,
|
||||
};
|
||||
|
||||
meta.controller.update();
|
||||
meta.controller._update();
|
||||
|
||||
expect(meta.dataset._model).toEqual(jasmine.objectContaining({
|
||||
backgroundColor: 'rgb(55, 55, 54)',
|
||||
|
||||
@ -47,5 +47,28 @@ describe('Chart.controllers.scatter', function() {
|
||||
expect(meta.dataset.draw.calls.count()).toBe(0);
|
||||
expect(meta.data[0].draw.calls.count()).toBe(1);
|
||||
});
|
||||
|
||||
it('should draw a line if true', function() {
|
||||
var chart = window.acquireChart({
|
||||
type: 'scatter',
|
||||
data: {
|
||||
datasets: [{
|
||||
data: [{x: 10, y: 15}],
|
||||
showLine: true,
|
||||
label: 'dataset1'
|
||||
}],
|
||||
},
|
||||
options: {}
|
||||
});
|
||||
|
||||
var meta = chart.getDatasetMeta(0);
|
||||
spyOn(meta.dataset, 'draw');
|
||||
spyOn(meta.data[0], 'draw');
|
||||
|
||||
chart.update();
|
||||
|
||||
expect(meta.dataset.draw.calls.count()).toBe(1);
|
||||
expect(meta.data[0].draw.calls.count()).toBe(1);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -91,9 +91,11 @@ describe('Chart', function() {
|
||||
});
|
||||
|
||||
it('should override default options', function() {
|
||||
var callback = function() {};
|
||||
var defaults = Chart.defaults;
|
||||
|
||||
defaults.global.responsiveAnimationDuration = 42;
|
||||
defaults.global.hover.onHover = callback;
|
||||
defaults.line.hover.mode = 'x-axis';
|
||||
defaults.line.spanGaps = true;
|
||||
|
||||
@ -113,11 +115,13 @@ describe('Chart', function() {
|
||||
|
||||
var options = chart.options;
|
||||
expect(options.responsiveAnimationDuration).toBe(4242);
|
||||
expect(options.showLines).toBe(defaults.global.showLines);
|
||||
expect(options.spanGaps).toBe(false);
|
||||
expect(options.hover.mode).toBe('dataset');
|
||||
expect(options.title.position).toBe('bottom');
|
||||
|
||||
defaults.global.responsiveAnimationDuration = 0;
|
||||
defaults.global.hover.onHover = null;
|
||||
defaults.line.hover.mode = 'label';
|
||||
defaults.line.spanGaps = false;
|
||||
});
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user