From b7caa2410c59d98abd6b37eda11d4dd439fbff81 Mon Sep 17 00:00:00 2001 From: Ben McCann <322311+benmccann@users.noreply.github.com> Date: Sun, 8 Dec 2019 05:52:11 -0800 Subject: [PATCH] Store parsed data more similarly to provided data (#6814) * Store parsed data more similarly to provided data * Add test --- src/controllers/controller.doughnut.js | 25 ++++----- src/core/core.controller.js | 3 +- src/core/core.datasetController.js | 34 ++++++------- test/specs/core.datasetController.tests.js | 59 ++++++++++++++++++++++ 4 files changed, 91 insertions(+), 30 deletions(-) diff --git a/src/controllers/controller.doughnut.js b/src/controllers/controller.doughnut.js index 2fcb7d272..ad5fa86ea 100644 --- a/src/controllers/controller.doughnut.js +++ b/src/controllers/controller.doughnut.js @@ -140,10 +140,10 @@ module.exports = DatasetController.extend({ */ _parse: function(start, count) { var data = this.getDataset().data; - var metaData = this._cachedMeta.data; + var meta = this._cachedMeta; var i, ilen; for (i = start, ilen = start + count; i < ilen; ++i) { - metaData[i]._parsed = +data[i]; + meta._parsed[i] = +data[i]; } }, @@ -220,7 +220,6 @@ module.exports = DatasetController.extend({ me.updateElements(arcs, 0, arcs.length, reset); }, - updateElements: function(arcs, start, count, reset) { const me = this; const chart = me.chart; @@ -231,13 +230,14 @@ module.exports = DatasetController.extend({ const centerY = (chartArea.top + chartArea.bottom) / 2; const startAngle = opts.rotation; // non reset case handled later const endAngle = opts.rotation; // non reset case handled later + const meta = me.getMeta(); const innerRadius = reset && animationOpts.animateScale ? 0 : me.innerRadius; const outerRadius = reset && animationOpts.animateScale ? 0 : me.outerRadius; - var i; + let i; for (i = 0; i < start + count; ++i) { const arc = arcs[i]; - const circumference = reset && animationOpts.animateRotate ? 0 : arc.hidden ? 0 : me.calculateCircumference(arc._parsed * opts.circumference / DOUBLE_PI); + const circumference = reset && animationOpts.animateRotate ? 0 : arc.hidden ? 0 : me.calculateCircumference(meta._parsed[i] * opts.circumference / DOUBLE_PI); const options = arc._options || {}; const model = { // Desired view properties @@ -272,16 +272,17 @@ module.exports = DatasetController.extend({ }, calculateTotal: function() { - var metaData = this._cachedMeta.data; - var total = 0; - var value; + const meta = this._cachedMeta; + const metaData = meta.data; + let total = 0; + let i; - helpers.each(metaData, function(arc) { - value = arc ? arc._parsed : NaN; - if (!isNaN(value) && !arc.hidden) { + for (i = 0; i < metaData.length; i++) { + const value = meta._parsed[i]; + if (!isNaN(value) && !metaData[i].hidden) { total += Math.abs(value); } - }); + } /* if (total === 0) { total = NaN; diff --git a/src/core/core.controller.js b/src/core/core.controller.js index 5fadf0fde..d2977d12b 100644 --- a/src/core/core.controller.js +++ b/src/core/core.controller.js @@ -850,7 +850,8 @@ helpers.extend(Chart.prototype, /** @lends Chart */ { xAxisID: null, yAxisID: null, order: dataset.order || 0, - index: datasetIndex + index: datasetIndex, + _parsed: [] }; } diff --git a/src/core/core.datasetController.js b/src/core/core.datasetController.js index a2a93b56a..73658bb06 100644 --- a/src/core/core.datasetController.js +++ b/src/core/core.datasetController.js @@ -478,18 +478,19 @@ helpers.extend(DatasetController.prototype, { let i, parsed; if (parsing === false) { - parsed = data; - offset = start; - } else if (helpers.isArray(data[start])) { - parsed = me._parseArrayData(meta, data, start, count); - } else if (helpers.isObject(data[start])) { - parsed = me._parseObjectData(meta, data, start, count); + meta._parsed = data; } else { - parsed = me._parsePrimitiveData(meta, data, start, count); - } + if (helpers.isArray(data[start])) { + parsed = me._parseArrayData(meta, data, start, count); + } else if (helpers.isObject(data[start])) { + parsed = me._parseObjectData(meta, data, start, count); + } else { + parsed = me._parsePrimitiveData(meta, data, start, count); + } - for (i = 0; i < count; ++i) { - meta.data[i + start]._parsed = parsed[i + offset]; + for (i = 0; i < count; ++i) { + meta._parsed[i + start] = parsed[i + offset]; + } } if (_stacked) { @@ -594,11 +595,11 @@ helpers.extend(DatasetController.prototype, { * @private */ _getParsed: function(index) { - const data = this._cachedMeta.data; + const data = this._cachedMeta._parsed; if (index < 0 || index >= data.length) { return; } - return data[index]._parsed; + return data[index]; }, /** @@ -634,7 +635,7 @@ helpers.extend(DatasetController.prototype, { for (i = 0; i < ilen; ++i) { item = metaData[i]; - parsed = item._parsed; + parsed = meta._parsed[i]; value = parsed[scale.id]; otherValue = parsed[otherScale.id]; if (item.hidden || isNaN(value) || @@ -665,13 +666,12 @@ helpers.extend(DatasetController.prototype, { * @private */ _getAllParsedValues: function(scale) { - const meta = this._cachedMeta; - const metaData = meta.data; + const parsed = this._cachedMeta._parsed; const values = []; let i, ilen, value; - for (i = 0, ilen = metaData.length; i < ilen; ++i) { - value = metaData[i]._parsed[scale.id]; + for (i = 0, ilen = parsed.length; i < ilen; ++i) { + value = parsed[i][scale.id]; if (!isNaN(value)) { values.push(value); } diff --git a/test/specs/core.datasetController.tests.js b/test/specs/core.datasetController.tests.js index c03f6de94..d80d16bd8 100644 --- a/test/specs/core.datasetController.tests.js +++ b/test/specs/core.datasetController.tests.js @@ -170,6 +170,65 @@ describe('Chart.DatasetController', function() { expect(meta.data[9]).toBe(last); }); + it('should synchronize metadata when data are inserted or removed and parsing is off', function() { + var data = [{x: 0, y: 0}, {x: 1, y: 1}, {x: 2, y: 2}, {x: 3, y: 3}, {x: 4, y: 4}, {x: 5, y: 5}]; + var chart = acquireChart({ + type: 'line', + data: { + datasets: [{ + data: data + }] + }, + options: { + parsing: false, + scales: { + x: {type: 'linear'}, + y: {type: 'linear'} + } + } + }); + + var meta = chart.getDatasetMeta(0); + var controller = meta.controller; + var first, last; + + first = controller._getParsed(0); + last = controller._getParsed(5); + data.push({x: 6, y: 6}, {x: 7, y: 7}, {x: 8, y: 8}); + data.push({x: 9, y: 9}); + expect(meta.data.length).toBe(10); + expect(controller._getParsed(0)).toBe(first); + expect(controller._getParsed(5)).toBe(last); + + last = controller._getParsed(9); + data.pop(); + expect(meta.data.length).toBe(9); + expect(controller._getParsed(0)).toBe(first); + expect(controller._getParsed(9)).toBe(undefined); + expect(controller._getParsed(8)).toEqual({x: 8, y: 8}); + + last = controller._getParsed(8); + data.shift(); + data.shift(); + data.shift(); + expect(meta.data.length).toBe(6); + expect(controller._getParsed(5)).toBe(last); + + first = controller._getParsed(0); + last = controller._getParsed(5); + data.splice(1, 4, {x: 10, y: 10}, {x: 11, y: 11}); + expect(meta.data.length).toBe(4); + expect(controller._getParsed(0)).toBe(first); + expect(controller._getParsed(3)).toBe(last); + expect(controller._getParsed(1)).toEqual({x: 10, y: 10}); + + data.unshift({x: 12, y: 12}, {x: 13, y: 13}, {x: 14, y: 14}, {x: 15, y: 15}); + data.unshift({x: 16, y: 16}, {x: 17, y: 17}); + expect(meta.data.length).toBe(10); + expect(controller._getParsed(6)).toBe(first); + expect(controller._getParsed(9)).toBe(last); + }); + it('should re-synchronize metadata when the data object reference changes', function() { var data0 = [0, 1, 2, 3, 4, 5]; var data1 = [6, 7, 8];