]> git.ipfire.org Git - thirdparty/Chart.js.git/commitdiff
Resync metasets array when indices change. (#6864)
authorJukka Kurkela <jukka.kurkela@gmail.com>
Sat, 28 Dec 2019 14:49:34 +0000 (16:49 +0200)
committerEvert Timberg <evert.timberg+github@gmail.com>
Sat, 28 Dec 2019 14:49:34 +0000 (09:49 -0500)
* Resync metasets array when indices change.
* Make sure _metasets is initialized

src/core/core.controller.js
test/specs/core.controller.tests.js

index b970f05b3f372bbc4b6c37c6b765ae4f161baaa8..81075d127d520f5cbcbb3fbaca76267d67d35a64 100644 (file)
@@ -195,6 +195,7 @@ helpers.extend(Chart.prototype, /** @lends Chart */ {
                me.options = config.options;
                me._bufferedRender = false;
                me._layers = [];
+               me._metasets = [];
 
                // Add the chart instance to the global namespace
                Chart.instances[me.id] = me;
@@ -399,11 +400,45 @@ helpers.extend(Chart.prototype, /** @lends Chart */ {
                scaleService.addScalesToLayout(this);
        },
 
+       /**
+        * Updates the given metaset with the given dataset index. Ensures it's stored at that index
+        * in the _metasets array by swapping with the metaset at that index if necessary.
+        * @param {Object} meta - the dataset metadata
+        * @param {number} index - the dataset index
+        * @private
+        */
+       _updateMetasetIndex: function(meta, index) {
+               const metasets = this._metasets;
+               const oldIndex = meta.index;
+               if (oldIndex !== index) {
+                       metasets[oldIndex] = metasets[index];
+                       metasets[index] = meta;
+                       meta.index = index;
+               }
+       },
+
+       /**
+        * @private
+        */
+       _updateMetasets: function() {
+               const me = this;
+               const metasets = me._metasets;
+               const numData = me.data.datasets.length;
+               const numMeta = metasets.length;
+
+               if (numMeta > numData) {
+                       for (let i = numData; i < numMeta; ++i) {
+                               me.destroyDatasetMeta(i);
+                       }
+                       metasets.splice(numData, numMeta - numData);
+               }
+               me._sortedMetasets = metasets.slice(0).sort(compare2Level('order', 'index'));
+       },
+
        buildOrUpdateControllers: function() {
                var me = this;
                var newControllers = [];
                var datasets = me.data.datasets;
-               var sorted = me._sortedMetasets = [];
                var i, ilen;
 
                for (i = 0, ilen = datasets.length; i < ilen; i++) {
@@ -417,7 +452,7 @@ helpers.extend(Chart.prototype, /** @lends Chart */ {
                        }
                        meta.type = type;
                        meta.order = dataset.order || 0;
-                       meta.index = i;
+                       me._updateMetasetIndex(meta, i);
                        meta.label = '' + dataset.label;
                        meta.visible = me.isDatasetVisible(i);
 
@@ -433,11 +468,9 @@ helpers.extend(Chart.prototype, /** @lends Chart */ {
                                meta.controller = new ControllerClass(me, i);
                                newControllers.push(meta.controller);
                        }
-                       sorted.push(meta);
                }
 
-               sorted.sort(compare2Level('order', 'index'));
-
+               me._updateMetasets();
                return newControllers;
        },
 
@@ -768,8 +801,8 @@ helpers.extend(Chart.prototype, /** @lends Chart */ {
        getDatasetMeta: function(datasetIndex) {
                const me = this;
                const dataset = me.data.datasets[datasetIndex];
-               const metasets = me._metasets = me._metasets || [];
-               let meta = metasets[datasetIndex];
+               const metasets = me._metasets;
+               let meta = metasets.filter(x => x._dataset === dataset).pop();
 
                if (!meta) {
                        meta = metasets[datasetIndex] = {
@@ -782,6 +815,7 @@ helpers.extend(Chart.prototype, /** @lends Chart */ {
                                yAxisID: null,
                                order: dataset.order || 0,
                                index: datasetIndex,
+                               _dataset: dataset,
                                _parsed: []
                        };
                }
index cc707f26bd33c3f224241be00e5008c288183406..e22fd7c4ae6da786b5184fd718657e0b85770baf 100644 (file)
@@ -1276,4 +1276,75 @@ describe('Chart', function() {
                        ]);
                });
        });
+
+       describe('metasets', function() {
+               beforeEach(function() {
+                       this.chart = acquireChart({
+                               type: 'line',
+                               data: {
+                                       datasets: [
+                                               {label: '1', order: 2},
+                                               {label: '2', order: 1},
+                                               {label: '3', order: 4},
+                                               {label: '4', order: 3},
+                                       ]
+                               }
+                       });
+               });
+               afterEach(function() {
+                       const metasets = this.chart._metasets;
+                       expect(metasets.length).toEqual(this.chart.data.datasets.length);
+                       for (let i = 0; i < metasets.length; i++) {
+                               expect(metasets[i].index).toEqual(i);
+                               expect(metasets[i]._dataset).toEqual(this.chart.data.datasets[i]);
+                       }
+               });
+               it('should build metasets array in order', function() {
+                       const metasets = this.chart._metasets;
+                       expect(metasets[0].order).toEqual(2);
+                       expect(metasets[1].order).toEqual(1);
+                       expect(metasets[2].order).toEqual(4);
+                       expect(metasets[3].order).toEqual(3);
+               });
+               it('should build sorted metasets array in correct order', function() {
+                       const metasets = this.chart._sortedMetasets;
+                       expect(metasets[0].order).toEqual(1);
+                       expect(metasets[1].order).toEqual(2);
+                       expect(metasets[2].order).toEqual(3);
+                       expect(metasets[3].order).toEqual(4);
+               });
+               it('should be moved when datasets are removed from begining', function() {
+                       this.chart.data.datasets.splice(0, 2);
+                       this.chart.update();
+                       const metasets = this.chart._metasets;
+                       expect(metasets[0].order).toEqual(4);
+                       expect(metasets[1].order).toEqual(3);
+               });
+               it('should be moved when datasets are removed from middle', function() {
+                       this.chart.data.datasets.splice(1, 2);
+                       this.chart.update();
+                       const metasets = this.chart._metasets;
+                       expect(metasets[0].order).toEqual(2);
+                       expect(metasets[1].order).toEqual(3);
+               });
+               it('should be moved when datasets are inserted', function() {
+                       this.chart.data.datasets.splice(1, 0, {label: '1.5', order: 5});
+                       this.chart.update();
+                       const metasets = this.chart._metasets;
+                       expect(metasets[0].order).toEqual(2);
+                       expect(metasets[1].order).toEqual(5);
+                       expect(metasets[2].order).toEqual(1);
+                       expect(metasets[3].order).toEqual(4);
+                       expect(metasets[4].order).toEqual(3);
+               });
+               it('should be replaced when dataset is replaced', function() {
+                       this.chart.data.datasets.splice(1, 1, {label: '1.5', order: 5});
+                       this.chart.update();
+                       const metasets = this.chart._metasets;
+                       expect(metasets[0].order).toEqual(2);
+                       expect(metasets[1].order).toEqual(5);
+                       expect(metasets[2].order).toEqual(4);
+                       expect(metasets[3].order).toEqual(3);
+               });
+       });
 });