diff --git a/src/controllers/controller.line.js b/src/controllers/controller.line.js index fddd5ce9889..d06f4d3c1e1 100644 --- a/src/controllers/controller.line.js +++ b/src/controllers/controller.line.js @@ -75,7 +75,7 @@ export default class LineController extends DatasetController { updateElements(points, start, count, mode) { const reset = mode === 'reset'; - const {iScale, vScale, _stacked, _dataset} = this._cachedMeta; + const {iScale, vScale, _stacked} = this._cachedMeta; const {sharedOptions, includeOptions} = this._getSharedOptions(start, mode); const iAxis = iScale.axis; const vAxis = vScale.axis; @@ -104,7 +104,7 @@ export default class LineController extends DatasetController { properties.stop = i > 0 && (Math.abs(parsed[iAxis] - prevParsed[iAxis])) > maxGapLength; if (segment) { properties.parsed = parsed; - properties.raw = _dataset.data[i]; + properties.raw = this._data[i]; } if (includeOptions) { diff --git a/src/controllers/controller.scatter.js b/src/controllers/controller.scatter.js index 15445ea8ae3..3caed1cf8cd 100644 --- a/src/controllers/controller.scatter.js +++ b/src/controllers/controller.scatter.js @@ -110,7 +110,7 @@ export default class ScatterController extends DatasetController { updateElements(points, start, count, mode) { const reset = mode === 'reset'; - const {iScale, vScale, _stacked, _dataset} = this._cachedMeta; + const {iScale, vScale, _stacked} = this._cachedMeta; const firstOpts = this.resolveDataElementOptions(start, mode); const sharedOptions = this.getSharedOptions(firstOpts); const includeOptions = this.includeOptions(mode, sharedOptions); @@ -133,7 +133,7 @@ export default class ScatterController extends DatasetController { properties.stop = i > 0 && (Math.abs(parsed[iAxis] - prevParsed[iAxis])) > maxGapLength; if (segment) { properties.parsed = parsed; - properties.raw = _dataset.data[i]; + properties.raw = this._data[i]; } if (includeOptions) { diff --git a/src/core/core.datasetController.js b/src/core/core.datasetController.js index 145a2b6a11e..11e6acdf47f 100644 --- a/src/core/core.datasetController.js +++ b/src/core/core.datasetController.js @@ -364,7 +364,7 @@ export default class DatasetController { */ _dataCheck() { const dataset = this.getDataset(); - const data = dataset.data || (dataset.data = []); + const data = dataset._decimated || dataset.data || (dataset.data = []); const _data = this._data; // In order to correctly handle data addition/deletion animation (and thus simulate @@ -767,7 +767,7 @@ export default class DatasetController { context = element.$context || (element.$context = createDataContext(this.getContext(), index, element)); context.parsed = this.getParsed(index); - context.raw = dataset.data[index]; + context.raw = this._data[index]; context.index = context.dataIndex = index; } else { context = this.$context || diff --git a/src/plugins/plugin.decimation.js b/src/plugins/plugin.decimation.js index 2c2a19a375a..da55d77b689 100644 --- a/src/plugins/plugin.decimation.js +++ b/src/plugins/plugin.decimation.js @@ -248,15 +248,15 @@ export default { if (isNullOrUndef(_data)) { // First time we are seeing this dataset - // We override the 'data' property with a setter that stores the - // raw data in _data, but reads the decimated data from _decimated + // We override the 'data' property with an accessor that stores and + // reads the raw data in _data. Dataset controllers use _decimated. dataset._data = data; delete dataset.data; Object.defineProperty(dataset, 'data', { configurable: true, enumerable: true, get: function() { - return this._decimated; + return this._data; }, set: function(d) { this._data = d; diff --git a/src/plugins/plugin.tooltip.js b/src/plugins/plugin.tooltip.js index b39681ce2ca..b63ab08ee99 100644 --- a/src/plugins/plugin.tooltip.js +++ b/src/plugins/plugin.tooltip.js @@ -133,7 +133,7 @@ function createTooltipItem(chart, item) { chart, label, parsed: controller.getParsed(index), - raw: chart.data.datasets[datasetIndex].data[index], + raw: controller._data[index], formattedValue: value, dataset: controller.getDataset(), dataIndex: index, diff --git a/test/specs/plugin.decimation.tests.js b/test/specs/plugin.decimation.tests.js index 9f8320b1e72..44cbf383e6f 100644 --- a/test/specs/plugin.decimation.tests.js +++ b/test/specs/plugin.decimation.tests.js @@ -51,7 +51,7 @@ describe('Plugin.decimation', function() { } }); - expect(chart.data.datasets[0].data.length).toBe(10); + expect(chart.getDatasetMeta(0).data.length).toBe(10); }); it('should draw the specified number of elements based on canvas width', function() { @@ -91,7 +91,7 @@ describe('Plugin.decimation', function() { } }); - expect(chart.data.datasets[0].data.length).toBe(7); + expect(chart.getDatasetMeta(0).data.length).toBe(7); }); it('should draw the specified number of elements based on threshold', function() { @@ -130,7 +130,59 @@ describe('Plugin.decimation', function() { } }); - expect(chart.data.datasets[0].data.length).toBe(5); + expect(chart.getDatasetMeta(0).data.length).toBe(5); + }); + + it('should append data after decimation', function() { + const data = originalData.slice(); + const point = {x: 10, y: 10}; + var chart = window.acquireChart({ + type: 'line', + data: { + datasets: [{ + data, + label: 'dataset1' + }] + }, + options: { + parsing: false, + scales: { + x: { + type: 'linear' + } + }, + plugins: { + decimation: { + enabled: true, + algorithm: 'lttb', + samples: 5, + threshold: 7 + } + } + } + }, { + canvas: { + height: 100, + width: 100 + }, + wrapper: { + height: 100, + width: 100 + } + }); + + chart.data.datasets[0].data.push(point); + chart.update(); + + expect(data.length).toBe(11); + const meta = chart.getDatasetMeta(0); + const parsed = meta._parsed; + expect(parsed[parsed.length - 1]).toBe(point); + expect(meta.controller.getContext(parsed.length - 1).raw).toBe(point); + + chart.tooltip.setActiveElements([{datasetIndex: 0, index: parsed.length - 1}], {x: 0, y: 0}); + chart.update(); + expect(chart.tooltip.dataPoints[0].raw).toBe(point); }); it('should draw all element only in range', function() { @@ -172,12 +224,13 @@ describe('Plugin.decimation', function() { // Data range is 4 (3->6) and the first point is added const expectedPoints = 5; - expect(chart.data.datasets[0].data.length).toBe(expectedPoints); - expect(chart.data.datasets[0].data[0].x).toBe(originalData[2].x); - expect(chart.data.datasets[0].data[1].x).toBe(originalData[3].x); - expect(chart.data.datasets[0].data[2].x).toBe(originalData[4].x); - expect(chart.data.datasets[0].data[3].x).toBe(originalData[5].x); - expect(chart.data.datasets[0].data[4].x).toBe(originalData[6].x); + const parsed = chart.getDatasetMeta(0)._parsed; + expect(parsed.length).toBe(expectedPoints); + expect(parsed[0].x).toBe(originalData[2].x); + expect(parsed[1].x).toBe(originalData[3].x); + expect(parsed[2].x).toBe(originalData[4].x); + expect(parsed[3].x).toBe(originalData[5].x); + expect(parsed[4].x).toBe(originalData[6].x); }); it('should not crash with uneven points', function() {