diff --git a/samples/samples.js b/samples/samples.js
index 235685bf2fa..d7e986c446a 100644
--- a/samples/samples.js
+++ b/samples/samples.js
@@ -133,6 +133,9 @@
}, {
title: 'Non numeric Y Axis',
path: 'scales/non-numeric-y.html'
+ }, {
+ title: 'Toggle Scale Type',
+ path: 'scales/toggle-scale-type.html'
}]
}, {
title: 'Legend',
diff --git a/samples/scales/toggle-scale-type.html b/samples/scales/toggle-scale-type.html
new file mode 100644
index 00000000000..e6bcd25a843
--- /dev/null
+++ b/samples/scales/toggle-scale-type.html
@@ -0,0 +1,104 @@
+
+
+
+
+ Toggle Scale Type
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/core/core.controller.js b/src/core/core.controller.js
index 28dd9765095..3e7cc3803b0 100644
--- a/src/core/core.controller.js
+++ b/src/core/core.controller.js
@@ -45,17 +45,21 @@ module.exports = function(Chart) {
function updateConfig(chart) {
var newOptions = chart.options;
- // Update Scale(s) with options
- 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;
- });
- }
-
+ helpers.each(chart.scales, function(scale) {
+ Chart.layoutService.removeBox(chart, scale);
+ });
+
+ newOptions = helpers.configMerge(
+ Chart.defaults.global,
+ Chart.defaults[chart.config.type],
+ newOptions);
+
+ chart.options = chart.config.options = newOptions;
+ chart.ensureScalesHaveIDs();
+ chart.buildOrUpdateScales();
// Tooltip
chart.tooltip._options = newOptions.tooltips;
+ chart.tooltip.initialize();
}
function positionIsHorizontal(position) {
@@ -143,7 +147,7 @@ module.exports = function(Chart) {
// Make sure scales have IDs and are built before we build any controllers.
me.ensureScalesHaveIDs();
- me.buildScales();
+ me.buildOrUpdateScales();
me.initToolTip();
// After init plugin notification
@@ -223,11 +227,15 @@ module.exports = function(Chart) {
/**
* Builds a map of scale ID to scale object for future lookup.
*/
- buildScales: function() {
+ buildOrUpdateScales: function() {
var me = this;
var options = me.options;
- var scales = me.scales = {};
+ var scales = me.scales || {};
var items = [];
+ var updated = Object.keys(scales).reduce(function(obj, id) {
+ obj[id] = false;
+ return obj;
+ }, {});
if (options.scales) {
items = items.concat(
@@ -251,24 +259,35 @@ module.exports = function(Chart) {
helpers.each(items, function(item) {
var scaleOptions = item.options;
+ var id = scaleOptions.id;
var scaleType = helpers.valueOrDefault(scaleOptions.type, item.dtype);
- var scaleClass = Chart.scaleService.getScaleConstructor(scaleType);
- if (!scaleClass) {
- return;
- }
if (positionIsHorizontal(scaleOptions.position) !== positionIsHorizontal(item.dposition)) {
scaleOptions.position = item.dposition;
}
- var scale = new scaleClass({
- id: scaleOptions.id,
- options: scaleOptions,
- ctx: me.ctx,
- chart: me
- });
+ updated[id] = true;
+ var scale = null;
+ if (id in scales && scales[id].type === scaleType) {
+ scale = scales[id];
+ scale.options = scaleOptions;
+ scale.ctx = me.ctx;
+ scale.chart = me;
+ } else {
+ var scaleClass = Chart.scaleService.getScaleConstructor(scaleType);
+ if (!scaleClass) {
+ return;
+ }
+ scale = new scaleClass({
+ id: id,
+ type: scaleType,
+ options: scaleOptions,
+ ctx: me.ctx,
+ chart: me
+ });
+ scales[scale.id] = scale;
+ }
- scales[scale.id] = scale;
scale.mergeTicksOptions();
// TODO(SB): I think we should be able to remove this custom case (options.scale)
@@ -278,6 +297,14 @@ module.exports = function(Chart) {
me.scale = scale;
}
});
+ // clear up discarded scales
+ helpers.each(updated, function(hasUpdated, id) {
+ if (!hasUpdated) {
+ delete scales[id];
+ }
+ });
+
+ me.scales = scales;
Chart.scaleService.addScalesToLayout(this);
},
@@ -301,6 +328,7 @@ module.exports = function(Chart) {
if (meta.controller) {
meta.controller.updateIndex(datasetIndex);
+ meta.controller.linkScales();
} else {
var ControllerClass = Chart.controllers[meta.type];
if (ControllerClass === undefined) {
diff --git a/src/core/core.datasetController.js b/src/core/core.datasetController.js
index 67dbe27f200..ee6158c35b1 100644
--- a/src/core/core.datasetController.js
+++ b/src/core/core.datasetController.js
@@ -111,10 +111,10 @@ module.exports = function(Chart) {
var meta = me.getMeta();
var dataset = me.getDataset();
- if (meta.xAxisID === null) {
+ if (meta.xAxisID === null || !(meta.xAxisID in me.chart.scales)) {
meta.xAxisID = dataset.xAxisID || me.chart.options.scales.xAxes[0].id;
}
- if (meta.yAxisID === null) {
+ if (meta.yAxisID === null || !(meta.yAxisID in me.chart.scales)) {
meta.yAxisID = dataset.yAxisID || me.chart.options.scales.yAxes[0].id;
}
},
diff --git a/test/specs/core.controller.tests.js b/test/specs/core.controller.tests.js
index beac21e0daa..3bb7c68952b 100644
--- a/test/specs/core.controller.tests.js
+++ b/test/specs/core.controller.tests.js
@@ -736,6 +736,38 @@ describe('Chart', function() {
});
describe('config update', function() {
+ it ('should update options', function() {
+ var chart = acquireChart({
+ type: 'line',
+ data: {
+ labels: ['A', 'B', 'C', 'D'],
+ datasets: [{
+ data: [10, 20, 30, 100]
+ }]
+ },
+ options: {
+ responsive: true
+ }
+ });
+
+ chart.options = {
+ responsive: false,
+ scales: {
+ yAxes: [{
+ ticks: {
+ min: 0,
+ max: 10
+ }
+ }]
+ }
+ };
+ chart.update();
+
+ var yScale = chart.scales['y-axis-0'];
+ expect(yScale.options.ticks.min).toBe(0);
+ expect(yScale.options.ticks.max).toBe(10);
+ });
+
it ('should update scales options', function() {
var chart = acquireChart({
type: 'line',
@@ -759,6 +791,79 @@ describe('Chart', function() {
expect(yScale.options.ticks.max).toBe(10);
});
+ it ('should update scales options from new object', function() {
+ var chart = acquireChart({
+ type: 'line',
+ data: {
+ labels: ['A', 'B', 'C', 'D'],
+ datasets: [{
+ data: [10, 20, 30, 100]
+ }]
+ },
+ options: {
+ responsive: true
+ }
+ });
+
+ var newScalesConfig = {
+ yAxes: [{
+ ticks: {
+ min: 0,
+ max: 10
+ }
+ }]
+ };
+ chart.options.scales = newScalesConfig;
+
+ chart.update();
+
+ var yScale = chart.scales['y-axis-0'];
+ expect(yScale.options.ticks.min).toBe(0);
+ expect(yScale.options.ticks.max).toBe(10);
+ });
+
+ it ('should remove discarded scale', function() {
+ var chart = acquireChart({
+ type: 'line',
+ data: {
+ labels: ['A', 'B', 'C', 'D'],
+ datasets: [{
+ data: [10, 20, 30, 100]
+ }]
+ },
+ options: {
+ responsive: true,
+ scales: {
+ yAxes: [{
+ id: 'yAxis0',
+ ticks: {
+ min: 0,
+ max: 10
+ }
+ }]
+ }
+ }
+ });
+
+ var newScalesConfig = {
+ yAxes: [{
+ ticks: {
+ min: 0,
+ max: 10
+ }
+ }]
+ };
+ chart.options.scales = newScalesConfig;
+
+ chart.update();
+
+ var yScale = chart.scales.yAxis0;
+ expect(yScale).toBeUndefined();
+ var newyScale = chart.scales['y-axis-0'];
+ expect(newyScale.options.ticks.min).toBe(0);
+ expect(newyScale.options.ticks.max).toBe(10);
+ });
+
it ('should update tooltip options', function() {
var chart = acquireChart({
type: 'line',