Skip to content

Commit 7dc38a4

Browse files
committed
Bar options should not be defined on scale
1 parent d6a5ea0 commit 7dc38a4

File tree

4 files changed

+195
-71
lines changed

4 files changed

+195
-71
lines changed

docs/charts/bar.md

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -132,8 +132,8 @@ The interaction with each bar can be controlled with the following properties:
132132

133133
All these values, if `undefined`, fallback to the associated [`elements.rectangle.*`](../configuration/elements.md#rectangle-configuration) options.
134134

135-
## Scale Configuration
136-
The bar chart accepts the following configuration from the associated `scale` options:
135+
## Dataset Configuration
136+
The bar chart accepts the following configuration from the associated dataset options:
137137

138138
| Name | Type | Default | Description
139139
| ---- | ---- | ------- | -----------
@@ -142,6 +142,32 @@ The bar chart accepts the following configuration from the associated `scale` op
142142
| `barThickness` | <code>number&#124;string</code> | | Manually set width of each bar in pixels. If set to `'flex'`, it computes "optimal" sample widths that globally arrange bars side by side. If not set (default), bars are equally sized based on the smallest interval. [more...](#barthickness)
143143
| `maxBarThickness` | `number` | | Set this to ensure that bars are not sized thicker than this.
144144
| `minBarLength` | `number` | | Set this to ensure that bars have a minimum length in pixels.
145+
146+
### Example Usage
147+
148+
```javascript
149+
data: {
150+
datasets: [{
151+
barPercentage: 0.5,
152+
barThickness: 6,
153+
maxBarThickness: 8,
154+
minBarLength: 2,
155+
data: [10, 20, 30, 40, 50, 60, 70]
156+
}]
157+
};
158+
```
159+
### barThickness
160+
If this value is a number, it is applied to the width of each bar, in pixels. When this is enforced, `barPercentage` and `categoryPercentage` are ignored.
161+
162+
If set to `'flex'`, the base sample widths are calculated automatically based on the previous and following samples so that they take the full available widths without overlap. Then, bars are sized using `barPercentage` and `categoryPercentage`. There is no gap when the percentage options are 1. This mode generates bars with different widths when data are not evenly spaced.
163+
164+
If not set (default), the base sample widths are calculated using the smallest interval that prevents bar overlapping, and bars are sized using `barPercentage` and `categoryPercentage`. This mode always generates bars equally sized.
165+
166+
## Scale Configuration
167+
The bar chart accepts the following configuration from the associated `scale` options:
168+
169+
| Name | Type | Default | Description
170+
| ---- | ---- | ------- | -----------
145171
| `gridLines.offsetGridLines` | `boolean` | `true` | If true, the bars for a particular data point fall between the grid lines. The grid line will move to the left by one half of the tick interval. If false, the grid line will go right down the middle of the bars. [more...](#offsetgridlines)
146172

147173
### Example Usage
@@ -150,23 +176,13 @@ The bar chart accepts the following configuration from the associated `scale` op
150176
options = {
151177
scales: {
152178
xAxes: [{
153-
barPercentage: 0.5,
154-
barThickness: 6,
155-
maxBarThickness: 8,
156-
minBarLength: 2,
157179
gridLines: {
158180
offsetGridLines: true
159181
}
160182
}]
161183
}
162184
};
163185
```
164-
### barThickness
165-
If this value is a number, it is applied to the width of each bar, in pixels. When this is enforced, `barPercentage` and `categoryPercentage` are ignored.
166-
167-
If set to `'flex'`, the base sample widths are calculated automatically based on the previous and following samples so that they take the full available widths without overlap. Then, bars are sized using `barPercentage` and `categoryPercentage`. There is no gap when the percentage options are 1. This mode generates bars with different widths when data are not evenly spaced.
168-
169-
If not set (default), the base sample widths are calculated using the smallest interval that prevents bar overlapping, and bars are sized using `barPercentage` and `categoryPercentage`. This mode always generates bars equally sized.
170186

171187
### offsetGridLines
172188
If true, the bars for a particular data point fall between the grid lines. The grid line will move to the left by one half of the tick interval, which is the space between the grid lines. If false, the grid line will go right down the middle of the bars. This is set to true for a category scale in a bar chart while false for other scales or chart types by default.

src/controllers/controller.bar.js

Lines changed: 63 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ var elements = require('../elements/index');
66
var helpers = require('../helpers/index');
77

88
var resolve = helpers.options.resolve;
9+
var valueOrDefault = helpers.valueOrDefault;
910

1011
defaults._set('bar', {
1112
hover: {
@@ -15,8 +16,6 @@ defaults._set('bar', {
1516
scales: {
1617
xAxes: [{
1718
type: 'category',
18-
categoryPercentage: 0.8,
19-
barPercentage: 0.9,
2019
offset: true,
2120
gridLines: {
2221
offsetGridLines: true
@@ -29,6 +28,15 @@ defaults._set('bar', {
2928
}
3029
});
3130

31+
defaults._set('global', {
32+
datasets: {
33+
bar: {
34+
categoryPercentage: 0.8,
35+
barPercentage: 0.9
36+
}
37+
}
38+
});
39+
3240
/**
3341
* Computes the "optimal" sample size to maintain bars equally sized while preventing overlap.
3442
* @private
@@ -116,26 +124,42 @@ function computeFlexCategoryTraits(index, ruler, options) {
116124
};
117125
}
118126

127+
function deprecated(value, previous, current) {
128+
if (value !== undefined) {
129+
console.warn(
130+
'bar chart: "' + previous + '" is deprecated. ' +
131+
'Please use "' + current + '" instead');
132+
}
133+
}
134+
119135
module.exports = DatasetController.extend({
120136

121137
dataElementType: elements.Rectangle,
122138

123139
initialize: function() {
124140
var me = this;
125-
var meta;
141+
var meta, scaleOpts;
126142

127143
DatasetController.prototype.initialize.apply(me, arguments);
128144

129145
meta = me.getMeta();
130146
meta.stack = me.getDataset().stack;
131147
meta.bar = true;
148+
149+
scaleOpts = me._getIndexScale().options;
150+
deprecated(scaleOpts.barPercentage, 'scales.[x/y]Axes.barPercentage', 'dataset.barPercentage');
151+
deprecated(scaleOpts.barThickness, 'scales.[x/y]Axes.barThickness', 'dataset.barThickness');
152+
deprecated(scaleOpts.categoryPercentage, 'scales.[x/y]Axes.categoryPercentage', 'dataset.categoryPercentage');
153+
deprecated(me._getValueScale().options.minBarLength, 'scales.[x/y]Axes.minBarLength', 'dataset.minBarLength');
154+
deprecated(scaleOpts.maxBarThickness, 'scales.[x/y]Axes.maxBarThickness', 'dataset.maxBarThickness');
132155
},
133156

134157
update: function(reset) {
135158
var me = this;
136159
var rects = me.getMeta().data;
137160
var i, ilen;
138161

162+
me._options = me._resolveControllerOptions(me.index);
139163
me._ruler = me.getRuler();
140164

141165
for (i = 0, ilen = rects.length; i < ilen; ++i) {
@@ -260,7 +284,7 @@ module.exports = DatasetController.extend({
260284
pixels.push(scale.getPixelForValue(null, i, datasetIndex));
261285
}
262286

263-
min = helpers.isNullOrUndef(scale.options.barThickness)
287+
min = helpers.isNullOrUndef(me._options.barThickness)
264288
? computeMinSampleSize(scale, pixels)
265289
: -1;
266290

@@ -286,7 +310,7 @@ module.exports = DatasetController.extend({
286310
var isHorizontal = scale.isHorizontal();
287311
var datasets = chart.data.datasets;
288312
var value = +scale.getRightValue(datasets[datasetIndex].data[index]);
289-
var minBarLength = scale.options.minBarLength;
313+
var minBarLength = me._options.minBarLength;
290314
var stacked = scale.options.stacked;
291315
var stack = meta.stack;
292316
var start = 0;
@@ -335,15 +359,15 @@ module.exports = DatasetController.extend({
335359
*/
336360
calculateBarIndexPixels: function(datasetIndex, index, ruler) {
337361
var me = this;
338-
var options = ruler.scale.options;
362+
var options = me._options;
339363
var range = options.barThickness === 'flex'
340364
? computeFlexCategoryTraits(index, ruler, options)
341365
: computeFitCategoryTraits(index, ruler, options);
342366

343367
var stackIndex = me.getStackIndex(datasetIndex, me.getMeta().stack);
344368
var center = range.start + (range.chunk * stackIndex) + (range.chunk / 2);
345369
var size = Math.min(
346-
helpers.valueOrDefault(options.maxBarThickness, Infinity),
370+
valueOrDefault(options.maxBarThickness, Infinity),
347371
range.chunk * range.ratio);
348372

349373
return {
@@ -386,7 +410,6 @@ module.exports = DatasetController.extend({
386410
var custom = rectangle.custom || {};
387411
var options = chart.options.elements.rectangle;
388412
var values = {};
389-
var i, ilen, key;
390413

391414
// Scriptable options
392415
var context = {
@@ -403,6 +426,7 @@ module.exports = DatasetController.extend({
403426
'borderWidth'
404427
];
405428

429+
var i, ilen, key;
406430
for (i = 0, ilen = keys.length; i < ilen; ++i) {
407431
key = keys[i];
408432
values[key] = resolve([
@@ -412,6 +436,37 @@ module.exports = DatasetController.extend({
412436
], context, index);
413437
}
414438

439+
return values;
440+
},
441+
442+
/**
443+
* @private
444+
*/
445+
_resolveControllerOptions: function() {
446+
var me = this;
447+
var datasetOpts = me._config;
448+
var indexOpts = me._getIndexScale().options;
449+
var valueOpts = me._getValueScale().options;
450+
var values = {};
451+
var keys = [
452+
'barPercentage',
453+
'barThickness',
454+
'categoryPercentage',
455+
'maxBarThickness'
456+
];
457+
var i, ilen, key;
458+
459+
for (i = 0, ilen = keys.length; i < ilen; ++i) {
460+
key = keys[i];
461+
values[key] = valueOrDefault(
462+
indexOpts[key],
463+
datasetOpts[key]
464+
);
465+
}
466+
467+
values.minBarLength = valueOrDefault(valueOpts.minBarLength, datasetOpts.minBarLength);
468+
415469
return values;
416470
}
471+
417472
});

test/specs/controller.bar.tests.js

Lines changed: 104 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1514,9 +1514,10 @@ describe('Chart.controllers.bar', function() {
15141514
var chart = window.acquireChart(this.config);
15151515
var meta = chart.getDatasetMeta(0);
15161516
var xScale = chart.scales[meta.xAxisID];
1517+
var options = Chart.defaults.global.datasets.bar;
15171518

1518-
var categoryPercentage = xScale.options.categoryPercentage;
1519-
var barPercentage = xScale.options.barPercentage;
1519+
var categoryPercentage = options.categoryPercentage;
1520+
var barPercentage = options.barPercentage;
15201521
var stacked = xScale.options.stacked;
15211522

15221523
var totalBarWidth = 0;
@@ -1690,7 +1691,7 @@ describe('Chart.controllers.bar', function() {
16901691
expected = barThickness;
16911692
} else {
16921693
var scale = chart.scales.x;
1693-
var options = chart.options.scales.xAxes[0];
1694+
var options = Chart.defaults.global.datasets.bar;
16941695
var categoryPercentage = options.categoryPercentage;
16951696
var barPercentage = options.barPercentage;
16961697
var tickInterval = scale.getPixelForTick(1) - scale.getPixelForTick(0);
@@ -1706,6 +1707,21 @@ describe('Chart.controllers.bar', function() {
17061707
});
17071708

17081709
it('should correctly set bar width if maxBarThickness is specified', function() {
1710+
var chart = this.chart;
1711+
var i, ilen, meta;
1712+
1713+
chart.data.datasets[0].maxBarThickness = 10;
1714+
chart.data.datasets[1].maxBarThickness = 10;
1715+
chart.update();
1716+
1717+
for (i = 0, ilen = chart.data.datasets.length; i < ilen; ++i) {
1718+
meta = chart.getDatasetMeta(i);
1719+
expect(meta.data[0]._model.width).toBeCloseToPixel(10);
1720+
expect(meta.data[1]._model.width).toBeCloseToPixel(10);
1721+
}
1722+
});
1723+
1724+
it('should correctly set bar width if maxBarThickness is specified via deprecated option', function() {
17091725
var chart = this.chart;
17101726
var options = chart.options.scales.xAxes[0];
17111727
var i, ilen, meta;
@@ -1722,4 +1738,89 @@ describe('Chart.controllers.bar', function() {
17221738
});
17231739
});
17241740
});
1741+
1742+
it('minBarLength settings should be used on Y axis on bar chart', function() {
1743+
var minBarLength = 4;
1744+
var chart = window.acquireChart({
1745+
type: 'bar',
1746+
data: {
1747+
datasets: [{
1748+
minBarLength: minBarLength,
1749+
data: [0.05, -0.05, 10, 15, 20, 25, 30, 35]
1750+
}]
1751+
}
1752+
});
1753+
1754+
var data = chart.getDatasetMeta(0).data;
1755+
1756+
expect(data[0]._model.base - minBarLength).toEqual(data[0]._model.y);
1757+
expect(data[1]._model.base + minBarLength).toEqual(data[1]._model.y);
1758+
});
1759+
1760+
it('minBarLength settings should be used on X axis on horizontalBar chart', function() {
1761+
var minBarLength = 4;
1762+
var chart = window.acquireChart({
1763+
type: 'horizontalBar',
1764+
data: {
1765+
datasets: [{
1766+
minBarLength: minBarLength,
1767+
data: [0.05, -0.05, 10, 15, 20, 25, 30, 35]
1768+
}]
1769+
}
1770+
});
1771+
1772+
var data = chart.getDatasetMeta(0).data;
1773+
1774+
expect(data[0]._model.base + minBarLength).toEqual(data[0]._model.x);
1775+
expect(data[1]._model.base - minBarLength).toEqual(data[1]._model.x);
1776+
});
1777+
1778+
it('deprecated minBarLength settings should be used on Y axis on bar chart', function() {
1779+
var minBarLength = 4;
1780+
var chart = window.acquireChart({
1781+
type: 'bar',
1782+
data: {
1783+
datasets: [{
1784+
data: [0.05, -0.05, 10, 15, 20, 25, 30, 35]
1785+
}]
1786+
},
1787+
options: {
1788+
scales: {
1789+
yAxes: [{
1790+
minBarLength: minBarLength
1791+
}]
1792+
}
1793+
}
1794+
});
1795+
1796+
var data = chart.getDatasetMeta(0).data;
1797+
1798+
expect(data[0]._model.base - minBarLength).toEqual(data[0]._model.y);
1799+
expect(data[1]._model.base + minBarLength).toEqual(data[1]._model.y);
1800+
});
1801+
1802+
it('deprecated minBarLength settings should be used on X axis on horizontalBar chart', function() {
1803+
var minBarLength = 4;
1804+
var chart = window.acquireChart({
1805+
type: 'horizontalBar',
1806+
data: {
1807+
datasets: [{
1808+
data: [0.05, -0.05, 10, 15, 20, 25, 30, 35]
1809+
}]
1810+
},
1811+
options: {
1812+
scales: {
1813+
xAxes: [{
1814+
minBarLength: minBarLength
1815+
}]
1816+
}
1817+
}
1818+
});
1819+
1820+
var data = chart.getDatasetMeta(0).data;
1821+
1822+
expect(data[0]._model.base + minBarLength).toEqual(data[0]._model.x);
1823+
expect(data[1]._model.base - minBarLength).toEqual(data[1]._model.x);
1824+
});
1825+
17251826
});

0 commit comments

Comments
 (0)