]> git.ipfire.org Git - thirdparty/Chart.js.git/commitdiff
Allow updating the config of a chart at runtime
authoretimberg <evert.timberg@gmail.com>
Sun, 13 Nov 2016 03:38:25 +0000 (22:38 -0500)
committerEvert Timberg <evert.timberg+github@gmail.com>
Fri, 25 Nov 2016 12:19:59 +0000 (07:19 -0500)
src/core/core.controller.js
src/core/core.legend.js
src/core/core.title.js
test/core.controller.tests.js
test/core.legend.tests.js
test/core.title.tests.js

index bdc98ee04aa9bad165e8dea8bd96f15838db2aaf..ebbd081afa6c3380f01164fdebfa4084fc06c34b 100644 (file)
@@ -168,6 +168,26 @@ module.exports = function(Chart) {
                return config;
        }
 
+       /**
+        * Updates the config of the chart
+        * @param chart {Chart.Controller} chart to update the options for
+        */
+       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;
+                       });
+               }
+
+               // Tooltip
+               chart.tooltip._options = newOptions.tooltips;
+       }
+
        /**
         * @class Chart.Controller
         * The main controller of a chart.
@@ -435,8 +455,11 @@ module.exports = function(Chart) {
                        this.tooltip.initialize();
                },
 
+
                update: function(animationDuration, lazy) {
                        var me = this;
+
+                       updateConfig(me);
                        Chart.plugins.notify('beforeUpdate', [me]);
 
                        // In case the entire data object changed
index 07349fd80b938347b5d798201e4ceb5c7f12cd90..4ab51ba5dbf94c9f2afbc3e6a733a9ee50fc1006 100644 (file)
@@ -489,20 +489,39 @@ module.exports = function(Chart) {
                }
        });
 
+       function createNewLegendAndAttach(chartInstance, legendOpts) {
+               var legend = new Chart.Legend({
+                       ctx: chartInstance.chart.ctx,
+                       options: legendOpts,
+                       chart: chartInstance
+               });
+               chartInstance.legend = legend;
+               Chart.layoutService.addBox(chartInstance, legend);
+       }
+
        // Register the legend plugin
        Chart.plugins.register({
                beforeInit: function(chartInstance) {
-                       var opts = chartInstance.options;
-                       var legendOpts = opts.legend;
+                       var legendOpts = chartInstance.options.legend;
 
                        if (legendOpts) {
-                               chartInstance.legend = new Chart.Legend({
-                                       ctx: chartInstance.chart.ctx,
-                                       options: legendOpts,
-                                       chart: chartInstance
-                               });
+                               createNewLegendAndAttach(chartInstance, legendOpts);
+                       }
+               },
+               beforeUpdate: function(chartInstance) {
+                       var legendOpts = chartInstance.options.legend;
 
-                               Chart.layoutService.addBox(chartInstance, chartInstance.legend);
+                       if (legendOpts) {
+                               legendOpts = helpers.configMerge(Chart.defaults.global.legend, legendOpts);
+
+                               if (chartInstance.legend) {
+                                       chartInstance.legend.options = legendOpts;
+                               } else {
+                                       createNewLegendAndAttach(chartInstance, legendOpts);
+                               }
+                       } else {
+                               Chart.layoutService.removeBox(chartInstance, chartInstance.legend);
+                               delete chartInstance.legend;
                        }
                }
        });
index a7663258a130cae297cd1b21d487ea3713c42fa4..5b2d989f8a7e24b9c16d1145dfaa0cbe563a2eb5 100644 (file)
@@ -22,7 +22,6 @@ module.exports = function(Chart) {
                initialize: function(config) {
                        var me = this;
                        helpers.extend(me, config);
-                       me.options = helpers.configMerge(Chart.defaults.global.title, config.options);
 
                        // Contains hit boxes for each dataset (in dataset order)
                        me.legendHitBoxes = [];
@@ -30,12 +29,7 @@ module.exports = function(Chart) {
 
                // These methods are ordered by lifecycle. Utilities then follow.
 
-               beforeUpdate: function() {
-                       var chartOpts = this.chart.options;
-                       if (chartOpts && chartOpts.title) {
-                               this.options = helpers.configMerge(Chart.defaults.global.title, chartOpts.title);
-                       }
-               },
+               beforeUpdate: noop,
                update: function(maxWidth, maxHeight, margins) {
                        var me = this;
 
@@ -187,20 +181,39 @@ module.exports = function(Chart) {
                }
        });
 
+       function createNewTitleBlockAndAttach(chartInstance, titleOpts) {
+               var title = new Chart.Title({
+                       ctx: chartInstance.chart.ctx,
+                       options: titleOpts,
+                       chart: chartInstance
+               });
+               chartInstance.titleBlock = title;
+               Chart.layoutService.addBox(chartInstance, title);
+       }
+
        // Register the title plugin
        Chart.plugins.register({
                beforeInit: function(chartInstance) {
-                       var opts = chartInstance.options;
-                       var titleOpts = opts.title;
+                       var titleOpts = chartInstance.options.title;
+
+                       if (titleOpts) {
+                               createNewTitleBlockAndAttach(chartInstance, titleOpts);
+                       }
+               },
+               beforeUpdate: function(chartInstance) {
+                       var titleOpts = chartInstance.options.title;
 
                        if (titleOpts) {
-                               chartInstance.titleBlock = new Chart.Title({
-                                       ctx: chartInstance.chart.ctx,
-                                       options: titleOpts,
-                                       chart: chartInstance
-                               });
+                               titleOpts = helpers.configMerge(Chart.defaults.global.title, titleOpts);
 
-                               Chart.layoutService.addBox(chartInstance, chartInstance.titleBlock);
+                               if (chartInstance.titleBlock) {
+                                       chartInstance.titleBlock.options = titleOpts;
+                               } else {
+                                       createNewTitleBlockAndAttach(chartInstance, titleOpts);
+                               }
+                       } else {
+                               Chart.layoutService.removeBox(chartInstance, chartInstance.titleBlock);
+                               delete chartInstance.titleBlock;
                        }
                }
        });
index cc99b0d7fb1ed0d4833075ded601640bb26680a0..44e7d3d21edfc00391ccddefa0bcb03ab7fb3ef2 100644 (file)
@@ -830,4 +830,53 @@ describe('Chart.Controller', function() {
                        expect(meta.data[3]._model.y).toBe(484);
                });
        });
+
+       describe('config update', function() {
+               it ('should update scales options', function() {
+                       var chart = acquireChart({
+                               type: 'line',
+                               data: {
+                                       labels: ['A', 'B', 'C', 'D'],
+                                       datasets: [{
+                                               data: [10, 20, 30, 100]
+                                       }]
+                               },
+                               options: {
+                                       responsive: true
+                               }
+                       });
+
+                       chart.options.scales.yAxes[0].ticks.min = 0;
+                       chart.options.scales.yAxes[0].ticks.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 tooltip options', function() {
+                       var chart = acquireChart({
+                               type: 'line',
+                               data: {
+                                       labels: ['A', 'B', 'C', 'D'],
+                                       datasets: [{
+                                               data: [10, 20, 30, 100]
+                                       }]
+                               },
+                               options: {
+                                       responsive: true
+                               }
+                       });
+
+                       var newTooltipConfig = {
+                               mode: 'dataset',
+                               intersect: false
+                       };
+                       chart.options.tooltips = newTooltipConfig;
+
+                       chart.update();
+                       expect(chart.tooltip._options).toEqual(jasmine.objectContaining(newTooltipConfig));
+               });
+       });
 });
index 3cdeddc903c5d7873733b29e04a73dabf8c425b5..109a209e05cfe4402466e42abdbb08491d1457f8 100644 (file)
@@ -367,4 +367,66 @@ describe('Legend block tests', function() {
                        "args": ["dataset3", 228, 132]
                }]);*/
        });
+
+       describe('config update', function() {
+               it ('should update the options', function() {
+                       var chart = acquireChart({
+                               type: 'line',
+                               data: {
+                                       labels: ['A', 'B', 'C', 'D'],
+                                       datasets: [{
+                                               data: [10, 20, 30, 100]
+                                       }]
+                               },
+                               options: {
+                                       legend: {
+                                               display: true
+                                       }
+                               }
+                       });
+                       expect(chart.legend.options.display).toBe(true);
+
+                       chart.options.legend.display = false;
+                       chart.update();
+                       expect(chart.legend.options.display).toBe(false);
+               });
+
+               it ('should remove the legend if the new options are false', function() {
+                       var chart = acquireChart({
+                               type: 'line',
+                               data: {
+                                       labels: ['A', 'B', 'C', 'D'],
+                                       datasets: [{
+                                               data: [10, 20, 30, 100]
+                                       }]
+                               }
+                       });
+                       expect(chart.legend).not.toBe(undefined);
+
+                       chart.options.legend = false;
+                       chart.update();
+                       expect(chart.legend).toBe(undefined);
+               });
+
+               it ('should create the legend if the legend options are changed to exist', function() {
+                       var chart = acquireChart({
+                               type: 'line',
+                               data: {
+                                       labels: ['A', 'B', 'C', 'D'],
+                                       datasets: [{
+                                               data: [10, 20, 30, 100]
+                                       }]
+                               },
+                               options: {
+                                       legend: false
+                               }
+                       });
+                       expect(chart.legend).toBe(undefined);
+
+                       chart.options.legend = {};
+                       chart.update();
+                       expect(chart.legend).not.toBe(undefined);
+                       expect(chart.legend.options).toEqual(jasmine.objectContaining(Chart.defaults.global.legend));
+               });
+       });
 });
index 7046052781eae507535db435020de74505e43da0..f334a1c6c674b8e11cf2e9277cd82c7dce5d09f0 100644 (file)
@@ -207,4 +207,66 @@ describe('Title block tests', function() {
                        args: []
                }]);
        });
+
+       describe('config update', function() {
+               it ('should update the options', function() {
+                       var chart = acquireChart({
+                               type: 'line',
+                               data: {
+                                       labels: ['A', 'B', 'C', 'D'],
+                                       datasets: [{
+                                               data: [10, 20, 30, 100]
+                                       }]
+                               },
+                               options: {
+                                       title: {
+                                               display: true
+                                       }
+                               }
+                       });
+                       expect(chart.titleBlock.options.display).toBe(true);
+
+                       chart.options.title.display = false;
+                       chart.update();
+                       expect(chart.titleBlock.options.display).toBe(false);
+               });
+
+               it ('should remove the title if the new options are false', function() {
+                       var chart = acquireChart({
+                               type: 'line',
+                               data: {
+                                       labels: ['A', 'B', 'C', 'D'],
+                                       datasets: [{
+                                               data: [10, 20, 30, 100]
+                                       }]
+                               }
+                       });
+                       expect(chart.titleBlock).not.toBe(undefined);
+
+                       chart.options.title = false;
+                       chart.update();
+                       expect(chart.titleBlock).toBe(undefined);
+               });
+
+               it ('should create the title if the title options are changed to exist', function() {
+                       var chart = acquireChart({
+                               type: 'line',
+                               data: {
+                                       labels: ['A', 'B', 'C', 'D'],
+                                       datasets: [{
+                                               data: [10, 20, 30, 100]
+                                       }]
+                               },
+                               options: {
+                                       title: false
+                               }
+                       });
+                       expect(chart.titleBlock).toBe(undefined);
+
+                       chart.options.title = {};
+                       chart.update();
+                       expect(chart.titleBlock).not.toBe(undefined);
+                       expect(chart.titleBlock.options).toEqual(jasmine.objectContaining(Chart.defaults.global.title));
+               });
+       });
 });