Skip to content

Commit

Permalink
add property setters for better options update
Browse files Browse the repository at this point in the history
- _optionsNew, _scaleNew, _scalesNew as flags to indicate how options update
- modified configMerge for scales
  • Loading branch information
xg-wang committed Aug 13, 2017
1 parent 1643fc0 commit 3557635
Show file tree
Hide file tree
Showing 2 changed files with 96 additions and 26 deletions.
109 changes: 87 additions & 22 deletions src/core/core.controller.js
Expand Up @@ -38,33 +38,58 @@ module.exports = function(Chart) {
return config;
}

function resetNewFlags(chart) {
helpers.each(['_optionsNew', '_scaleNew', '_scalesNew'], function(flag) {
chart[flag] = false;
});
}

/**
* Updates the config of the chart
* If new option is created as a new object, default should be merged/
* If there are axes specified in the new option,
* we should replace the old axes with the new axes.
* If not then we should keep the old ones, and put a console warning.
* @param chart {Chart} chart to update the options for
*/
function updateConfig(chart) {
var newOptions = chart.options;

// Update Scale(s) or Tooltip with options if needed
if (newOptions.scale || newOptions.scales || newOptions.tooltips) {
newOptions = helpers.configMerge(
Chart.defaults.global,
Chart.defaults[chart.config.type],
newOptions);
chart.options = newOptions;
chart.ensureScalesHaveIDs();

// use old scales if user didn't specify explicitly
if (!chart._optionsNew && !chart._scaleNew && !chart._scalesNew) {
// If no new Object, just update chart.scale(s) options, chart.options already updated.
if (newOptions.scale) {
chart.scale.options = newOptions.scale;
} else if (newOptions.scales) {
newOptions.scales.xAxes.concat(newOptions.scales.yAxes).forEach(function(scaleOptions) {
chart.scales[scaleOptions.id].options = scaleOptions;
});
}

// Tooltip
chart.tooltip._options = newOptions.tooltips;
} else {
// if anything is new object, we need to rebuild scales
helpers.each(chart.scales, function(scale) {
Chart.layoutService.removeBox(chart, scale);
});
newOptions = helpers.configMerge(
Chart.defaults.global,
Chart.defaults[chart.config.type],
newOptions);
if (chart._optionsNew) {
// if options are new, remerge all options
// then build new chart.scales from chart.options if needed
chart.options = chart.config.options = newOptions;
} else {
// if user only set new scales, only remerge scales options
helpers.each(['scales', 'scale'], function(type) {
chart.options[type] = chart.config.options[type] = newOptions[type];
});
}
resetNewFlags(chart);
chart.ensureScalesHaveIDs();
chart.buildScales();
}
// Tooltip
chart.tooltip._options = newOptions.tooltips;
}

function positionIsHorizontal(position) {
Expand All @@ -77,6 +102,7 @@ module.exports = function(Chart) {
*/
construct: function(item, config) {
var me = this;
me.setupAliases();

config = initConfig(config);

Expand All @@ -94,6 +120,7 @@ module.exports = function(Chart) {
me.aspectRatio = height ? width / height : null;
me.options = config.options;
me._bufferedRender = false;
resetNewFlags(me);

/**
* Provided for backward compatibility, Chart and Chart.Controller have been merged,
Expand All @@ -109,16 +136,6 @@ module.exports = function(Chart) {
// Add the chart instance to the global namespace
Chart.instances[me.id] = me;

// Define alias to the config data: `chart.data === chart.config.data`
Object.defineProperty(me, 'data', {
get: function() {
return me.config.data;
},
set: function(value) {
me.config.data = value;
}
});

if (!context || !canvas) {
// The given item is not a compatible context2d element, let's return before finalizing
// the chart initialization but after setting basic chart / controller properties that
Expand All @@ -132,6 +149,54 @@ module.exports = function(Chart) {
me.update();
},

/**
* @private
*/
setupAliases: function() {
var me = this;
// Define alias to the config data: `chart.data === chart.config.data`
Object.defineProperty(me, 'data', {
get: function() {
return me.config.data;
},
set: function(value) {
me.config.data = value;
}
});

var Options = function(opt) {
opt = opt || {};
var keys = Object.keys(opt);
var klen = keys.length;
var k = 0;
for (; k < klen; ++k) {
this[keys[k]] = opt[keys[k]];
}
};
helpers.each(['scale', 'scales'], function(type) {
Object.defineProperty(Options.prototype, type, {
get: function() {
return this['_' + type];
},
set: function(value) {
me['_' + type + 'New'] = true;
this['_' + type] = value;
}
});
});
Object.defineProperty(me, 'options', {
get: function() {
return me._options;
},
set: function(value) {
me._optionsNew = true;
me._options = new Options(value);
}
});

me.options = new Options();
},

/**
* @private
*/
Expand Down
13 changes: 9 additions & 4 deletions src/core/core.helpers.js
Expand Up @@ -23,13 +23,18 @@ module.exports = function(Chart) {
helpers.configMerge = function(/* objects ... */) {
return helpers.merge(helpers.clone(arguments[0]), [].slice.call(arguments, 1), {
merger: function(key, target, source, options) {
var tval = target[key] || {};
var sval = source[key];
var tval, sval;

if (key === 'scales') {
if (key === 'scales' || key === '_scales') {
key = 'scales';
tval = target[key] || {};
sval = source[key];
// scale config merging is complex. Add our own function here for that
target[key] = helpers.scaleMerge(tval, sval);
} else if (key === 'scale') {
} else if (key === 'scale' || key === '_scale') {
key = 'scale';
tval = target[key] || {};
sval = source[key];
// used in polar area & radar charts since there is only one scale
target[key] = helpers.merge(tval, [Chart.scaleService.getScaleDefaults(sval.type), sval]);
} else {
Expand Down

0 comments on commit 3557635

Please sign in to comment.