Skip to content

Commit 0697d0d

Browse files
authored
Deprecate configMerge and scaleMerge helpers (#6022)
These methods shouldn't have been public since they are specific to the chart controller internal logic. Note that this scale custom merging will be removed in v3.
1 parent 17f6fd2 commit 0697d0d

File tree

6 files changed

+242
-225
lines changed

6 files changed

+242
-225
lines changed

src/core/core.controller.js

Lines changed: 85 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,16 +35,80 @@ defaults._set('global', {
3535
responsiveAnimationDuration: 0
3636
});
3737

38+
/**
39+
* Recursively merge the given config objects representing the `scales` option
40+
* by incorporating scale defaults in `xAxes` and `yAxes` array items, then
41+
* returns a deep copy of the result, thus doesn't alter inputs.
42+
*/
43+
function mergeScaleConfig(/* config objects ... */) {
44+
return helpers.merge({}, [].slice.call(arguments), {
45+
merger: function(key, target, source, options) {
46+
if (key === 'xAxes' || key === 'yAxes') {
47+
var slen = source[key].length;
48+
var i, type, scale;
49+
50+
if (!target[key]) {
51+
target[key] = [];
52+
}
53+
54+
for (i = 0; i < slen; ++i) {
55+
scale = source[key][i];
56+
type = valueOrDefault(scale.type, key === 'xAxes' ? 'category' : 'linear');
57+
58+
if (i >= target[key].length) {
59+
target[key].push({});
60+
}
61+
62+
if (!target[key][i].type || (scale.type && scale.type !== target[key][i].type)) {
63+
// new/untyped scale or type changed: let's apply the new defaults
64+
// then merge source scale to correctly overwrite the defaults.
65+
helpers.merge(target[key][i], [scaleService.getScaleDefaults(type), scale]);
66+
} else {
67+
// scales type are the same
68+
helpers.merge(target[key][i], scale);
69+
}
70+
}
71+
} else {
72+
helpers._merger(key, target, source, options);
73+
}
74+
}
75+
});
76+
}
77+
78+
/**
79+
* Recursively merge the given config objects as the root options by handling
80+
* default scale options for the `scales` and `scale` properties, then returns
81+
* a deep copy of the result, thus doesn't alter inputs.
82+
*/
83+
function mergeConfig(/* config objects ... */) {
84+
return helpers.merge({}, [].slice.call(arguments), {
85+
merger: function(key, target, source, options) {
86+
var tval = target[key] || {};
87+
var sval = source[key];
88+
89+
if (key === 'scales') {
90+
// scale config merging is complex. Add our own function here for that
91+
target[key] = mergeScaleConfig(tval, sval);
92+
} else if (key === 'scale') {
93+
// used in polar area & radar charts since there is only one scale
94+
target[key] = helpers.merge(tval, [scaleService.getScaleDefaults(sval.type), sval]);
95+
} else {
96+
helpers._merger(key, target, source, options);
97+
}
98+
}
99+
});
100+
}
101+
38102
function initConfig(config) {
39103
config = config || {};
40104

41-
// Do NOT use configMerge() for the data object because this method merges arrays
105+
// Do NOT use mergeConfig for the data object because this method merges arrays
42106
// and so would change references to labels and datasets, preventing data updates.
43107
var data = config.data = config.data || {};
44108
data.datasets = data.datasets || [];
45109
data.labels = data.labels || [];
46110

47-
config.options = helpers.configMerge(
111+
config.options = mergeConfig(
48112
defaults.global,
49113
defaults[config.type],
50114
config.options || {});
@@ -59,7 +123,7 @@ function updateConfig(chart) {
59123
layouts.removeBox(chart, scale);
60124
});
61125

62-
newOptions = helpers.configMerge(
126+
newOptions = mergeConfig(
63127
defaults.global,
64128
defaults[chart.config.type],
65129
newOptions);
@@ -981,3 +1045,21 @@ Chart.Controller = Chart;
9811045
* @private
9821046
*/
9831047
Chart.types = {};
1048+
1049+
/**
1050+
* Provided for backward compatibility, not available anymore.
1051+
* @namespace Chart.helpers.configMerge
1052+
* @deprecated since version 2.8.0
1053+
* @todo remove at version 3
1054+
* @private
1055+
*/
1056+
helpers.configMerge = mergeConfig;
1057+
1058+
/**
1059+
* Provided for backward compatibility, not available anymore.
1060+
* @namespace Chart.helpers.scaleMerge
1061+
* @deprecated since version 2.8.0
1062+
* @todo remove at version 3
1063+
* @private
1064+
*/
1065+
helpers.scaleMerge = mergeScaleConfig;

src/core/core.helpers.js

Lines changed: 0 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -5,66 +5,11 @@
55
var color = require('chartjs-color');
66
var defaults = require('./core.defaults');
77
var helpers = require('../helpers/index');
8-
var scaleService = require('../core/core.scaleService');
98

109
module.exports = function() {
1110

1211
// -- Basic js utility methods
1312

14-
helpers.configMerge = function(/* objects ... */) {
15-
return helpers.merge(helpers.clone(arguments[0]), [].slice.call(arguments, 1), {
16-
merger: function(key, target, source, options) {
17-
var tval = target[key] || {};
18-
var sval = source[key];
19-
20-
if (key === 'scales') {
21-
// scale config merging is complex. Add our own function here for that
22-
target[key] = helpers.scaleMerge(tval, sval);
23-
} else if (key === 'scale') {
24-
// used in polar area & radar charts since there is only one scale
25-
target[key] = helpers.merge(tval, [scaleService.getScaleDefaults(sval.type), sval]);
26-
} else {
27-
helpers._merger(key, target, source, options);
28-
}
29-
}
30-
});
31-
};
32-
33-
helpers.scaleMerge = function(/* objects ... */) {
34-
return helpers.merge(helpers.clone(arguments[0]), [].slice.call(arguments, 1), {
35-
merger: function(key, target, source, options) {
36-
if (key === 'xAxes' || key === 'yAxes') {
37-
var slen = source[key].length;
38-
var i, type, scale;
39-
40-
if (!target[key]) {
41-
target[key] = [];
42-
}
43-
44-
for (i = 0; i < slen; ++i) {
45-
scale = source[key][i];
46-
type = helpers.valueOrDefault(scale.type, key === 'xAxes' ? 'category' : 'linear');
47-
48-
if (i >= target[key].length) {
49-
target[key].push({});
50-
}
51-
52-
if (!target[key][i].type || (scale.type && scale.type !== target[key][i].type)) {
53-
// new/untyped scale or type changed: let's apply the new defaults
54-
// then merge source scale to correctly overwrite the defaults.
55-
helpers.merge(target[key][i], [scaleService.getScaleDefaults(type), scale]);
56-
} else {
57-
// scales type are the same
58-
helpers.merge(target[key][i], scale);
59-
}
60-
}
61-
} else {
62-
helpers._merger(key, target, source, options);
63-
}
64-
}
65-
});
66-
};
67-
6813
helpers.where = function(collection, filterCallback) {
6914
if (helpers.isArray(collection) && Array.prototype.filter) {
7015
return collection.filter(filterCallback);

src/helpers/helpers.core.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ var helpers = {
192192

193193
/**
194194
* The default merger when Chart.helpers.merge is called without merger option.
195-
* Note(SB): this method is also used by configMerge and scaleMerge as fallback.
195+
* Note(SB): also used by mergeConfig and mergeScaleConfig as fallback.
196196
* @private
197197
*/
198198
_merger: function(key, target, source, options) {

test/specs/core.controller.tests.js

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,150 @@ describe('Chart', function() {
159159
});
160160
});
161161

162+
describe('when merging scale options', function() {
163+
beforeEach(function() {
164+
Chart.helpers.merge(Chart.defaults.scale, {
165+
_jasmineCheckA: 'a0',
166+
_jasmineCheckB: 'b0',
167+
_jasmineCheckC: 'c0'
168+
});
169+
170+
Chart.helpers.merge(Chart.scaleService.defaults.logarithmic, {
171+
_jasmineCheckB: 'b1',
172+
_jasmineCheckC: 'c1',
173+
});
174+
});
175+
176+
afterEach(function() {
177+
delete Chart.defaults.scale._jasmineCheckA;
178+
delete Chart.defaults.scale._jasmineCheckB;
179+
delete Chart.defaults.scale._jasmineCheckC;
180+
delete Chart.scaleService.defaults.logarithmic._jasmineCheckB;
181+
delete Chart.scaleService.defaults.logarithmic._jasmineCheckC;
182+
});
183+
184+
it('should default to "category" for x scales and "linear" for y scales', function() {
185+
var chart = acquireChart({
186+
type: 'line',
187+
options: {
188+
scales: {
189+
xAxes: [
190+
{id: 'foo0'},
191+
{id: 'foo1'}
192+
],
193+
yAxes: [
194+
{id: 'bar0'},
195+
{id: 'bar1'}
196+
]
197+
}
198+
}
199+
});
200+
201+
expect(chart.scales.foo0.type).toBe('category');
202+
expect(chart.scales.foo1.type).toBe('category');
203+
expect(chart.scales.bar0.type).toBe('linear');
204+
expect(chart.scales.bar1.type).toBe('linear');
205+
});
206+
207+
it('should correctly apply defaults on central scale', function() {
208+
var chart = acquireChart({
209+
type: 'line',
210+
options: {
211+
scale: {
212+
id: 'foo',
213+
type: 'logarithmic',
214+
_jasmineCheckC: 'c2',
215+
_jasmineCheckD: 'd2'
216+
}
217+
}
218+
});
219+
220+
// let's check a few values from the user options and defaults
221+
222+
expect(chart.scales.foo.type).toBe('logarithmic');
223+
expect(chart.scales.foo.options).toBe(chart.options.scale);
224+
expect(chart.scales.foo.options).toEqual(
225+
jasmine.objectContaining({
226+
_jasmineCheckA: 'a0',
227+
_jasmineCheckB: 'b1',
228+
_jasmineCheckC: 'c2',
229+
_jasmineCheckD: 'd2'
230+
}));
231+
});
232+
233+
it('should correctly apply defaults on xy scales', function() {
234+
var chart = acquireChart({
235+
type: 'line',
236+
options: {
237+
scales: {
238+
xAxes: [{
239+
id: 'foo',
240+
type: 'logarithmic',
241+
_jasmineCheckC: 'c2',
242+
_jasmineCheckD: 'd2'
243+
}],
244+
yAxes: [{
245+
id: 'bar',
246+
type: 'time',
247+
_jasmineCheckC: 'c2',
248+
_jasmineCheckE: 'e2'
249+
}]
250+
}
251+
}
252+
});
253+
254+
expect(chart.scales.foo.type).toBe('logarithmic');
255+
expect(chart.scales.foo.options).toBe(chart.options.scales.xAxes[0]);
256+
expect(chart.scales.foo.options).toEqual(
257+
jasmine.objectContaining({
258+
_jasmineCheckA: 'a0',
259+
_jasmineCheckB: 'b1',
260+
_jasmineCheckC: 'c2',
261+
_jasmineCheckD: 'd2'
262+
}));
263+
264+
expect(chart.scales.bar.type).toBe('time');
265+
expect(chart.scales.bar.options).toBe(chart.options.scales.yAxes[0]);
266+
expect(chart.scales.bar.options).toEqual(
267+
jasmine.objectContaining({
268+
_jasmineCheckA: 'a0',
269+
_jasmineCheckB: 'b0',
270+
_jasmineCheckC: 'c2',
271+
_jasmineCheckE: 'e2'
272+
}));
273+
});
274+
275+
it('should not alter defaults when merging config', function() {
276+
var chart = acquireChart({
277+
type: 'line',
278+
options: {
279+
_jasmineCheck: 42,
280+
scales: {
281+
xAxes: [{
282+
id: 'foo',
283+
type: 'linear',
284+
_jasmineCheck: 42,
285+
}],
286+
yAxes: [{
287+
id: 'bar',
288+
type: 'category',
289+
_jasmineCheck: 42,
290+
}]
291+
}
292+
}
293+
});
294+
295+
expect(chart.options._jasmineCheck).toBeDefined();
296+
expect(chart.scales.foo.options._jasmineCheck).toBeDefined();
297+
expect(chart.scales.bar.options._jasmineCheck).toBeDefined();
298+
299+
expect(Chart.defaults.line._jasmineCheck).not.toBeDefined();
300+
expect(Chart.defaults.global._jasmineCheck).not.toBeDefined();
301+
expect(Chart.scaleService.defaults.linear._jasmineCheck).not.toBeDefined();
302+
expect(Chart.scaleService.defaults.category._jasmineCheck).not.toBeDefined();
303+
});
304+
});
305+
162306
describe('config.options.responsive: false', function() {
163307
it('should not inject the resizer element', function() {
164308
var chart = acquireChart({

0 commit comments

Comments
 (0)