]> git.ipfire.org Git - thirdparty/Chart.js.git/commitdiff
Internal data by axis instead of scale id (#6912)
authorJukka Kurkela <jukka.kurkela@gmail.com>
Mon, 6 Jan 2020 12:22:18 +0000 (14:22 +0200)
committerEvert Timberg <evert.timberg+github@gmail.com>
Mon, 6 Jan 2020 12:22:18 +0000 (07:22 -0500)
* Internal data by axis instead of scale id

* Test

* Update test

* Update docs

docs/general/data-structures.md
src/controllers/controller.bar.js
src/controllers/controller.bubble.js
src/controllers/controller.line.js
src/controllers/controller.radar.js
src/core/core.datasetController.js
test/specs/core.datasetController.tests.js

index 70bed1cc2cd50dc2d5058a61c6eccc382c6aad7d..aead2af635fce39d72bde4d269185875d4454945 100644 (file)
@@ -25,7 +25,7 @@ data: [{x:'2016-12-25', y:20}, {x:'2016-12-26', y:10}]
 data: [{x:'Sales', y:20}, {x:'Revenue', y:10}]
 ```
 
-This is also the internal format used for parsed data. Property names are matched to scale-id. In this mode, parsing can be disabled by specifying `parsing: false` at chart options or dataset. If parsing is disabled, data must be sorted and in the formats the associated chart type and scales use internally.
+This is also the internal format used for parsed data. In this mode, parsing can be disabled by specifying `parsing: false` at chart options or dataset. If parsing is disabled, data must be sorted and in the formats the associated chart type and scales use internally.
 
 ## Object
 
index 2326d0b94673a7a88e54763064d8f32d88d2bfda..7a72ce29ed949e129dfe3872b0caeec8d34b7f1b 100644 (file)
@@ -144,7 +144,7 @@ function parseFloatBar(arr, item, vScale, i) {
 
        // Store `barEnd` (furthest away from origin) as parsed value,
        // to make stacking straight forward
-       item[vScale.id] = barEnd;
+       item[vScale.axis] = barEnd;
 
        item._custom = {
                barStart: barStart,
@@ -167,12 +167,12 @@ function parseArrayOrPrimitive(meta, data, start, count) {
        for (i = start, ilen = start + count; i < ilen; ++i) {
                entry = data[i];
                item = {};
-               item[iScale.id] = singleScale || iScale._parse(labels[i], i);
+               item[iScale.axis] = singleScale || iScale._parse(labels[i], i);
 
                if (helpers.isArray(entry)) {
                        parseFloatBar(entry, item, vScale, i);
                } else {
-                       item[vScale.id] = vScale._parse(entry, i);
+                       item[vScale.axis] = vScale._parse(entry, i);
                }
 
                parsed.push(item);
@@ -230,12 +230,12 @@ module.exports = DatasetController.extend({
                for (i = start, ilen = start + count; i < ilen; ++i) {
                        obj = data[i];
                        item = {};
-                       item[iScale.id] = iScale._parseObject(obj, iScale.axis, i);
+                       item[iScale.axis] = iScale._parseObject(obj, iScale.axis, i);
                        value = obj[vProp];
                        if (helpers.isArray(value)) {
                                parseFloatBar(value, item, vScale, i);
                        } else {
-                               item[vScale.id] = vScale._parseObject(obj, vProp, i);
+                               item[vScale.axis] = vScale._parseObject(obj, vProp, i);
                        }
                        parsed.push(item);
                }
@@ -253,10 +253,10 @@ module.exports = DatasetController.extend({
                const custom = parsed._custom;
                const value = custom
                        ? '[' + custom.start + ', ' + custom.end + ']'
-                       : '' + vScale.getLabelForValue(parsed[vScale.id]);
+                       : '' + vScale.getLabelForValue(parsed[vScale.axis]);
 
                return {
-                       label: '' + iScale.getLabelForValue(parsed[iScale.id]),
+                       label: '' + iScale.getLabelForValue(parsed[iScale.axis]),
                        value: value
                };
        },
@@ -394,7 +394,7 @@ module.exports = DatasetController.extend({
                let i, ilen;
 
                for (i = 0, ilen = meta.data.length; i < ilen; ++i) {
-                       pixels.push(iScale.getPixelForValue(me._getParsed(i)[iScale.id]));
+                       pixels.push(iScale.getPixelForValue(me._getParsed(i)[iScale.axis]));
                }
 
                return {
@@ -417,9 +417,9 @@ module.exports = DatasetController.extend({
                const minBarLength = options.minBarLength;
                const parsed = me._getParsed(index);
                const custom = parsed._custom;
-               let value = parsed[vScale.id];
+               let value = parsed[vScale.axis];
                let start = 0;
-               let length = meta._stacked ? me._applyStack(vScale, parsed) : parsed[vScale.id];
+               let length = meta._stacked ? me._applyStack(vScale, parsed) : parsed[vScale.axis];
                let base, head, size;
 
                if (length !== value) {
@@ -489,7 +489,7 @@ module.exports = DatasetController.extend({
                helpers.canvas.clipArea(chart.ctx, chart.chartArea);
 
                for (; i < ilen; ++i) {
-                       if (!isNaN(me._getParsed(i)[vScale.id])) {
+                       if (!isNaN(me._getParsed(i)[vScale.axis])) {
                                rects[i].draw(me._ctx);
                        }
                }
index efb453bce490b3769d0b072cc7b184acc96219d5..70e934afea0d04669b3874eb335de0f8c8c257c2 100644 (file)
@@ -59,15 +59,13 @@ module.exports = DatasetController.extend({
         */
        _parseObjectData: function(meta, data, start, count) {
                const {xScale, yScale} = meta;
-               const xId = xScale.id;
-               const yId = yScale.id;
                const parsed = [];
                let i, ilen, item;
                for (i = start, ilen = start + count; i < ilen; ++i) {
                        item = data[i];
                        parsed.push({
-                               [xId]: xScale._parseObject(item, 'x', i),
-                               [yId]: yScale._parseObject(item, 'y', i),
+                               x: xScale._parseObject(item, 'x', i),
+                               y: yScale._parseObject(item, 'y', i),
                                _custom: item && item.r && +item.r
                        });
                }
@@ -96,8 +94,8 @@ module.exports = DatasetController.extend({
                const meta = me._cachedMeta;
                const {xScale, yScale} = meta;
                const parsed = me._getParsed(index);
-               const x = xScale.getLabelForValue(parsed[xScale.id]);
-               const y = yScale.getLabelForValue(parsed[yScale.id]);
+               const x = xScale.getLabelForValue(parsed.x);
+               const y = yScale.getLabelForValue(parsed.y);
                const r = parsed._custom;
 
                return {
@@ -133,8 +131,8 @@ module.exports = DatasetController.extend({
                        const point = points[i];
                        const index = start + i;
                        const parsed = !reset && me._getParsed(index);
-                       const x = reset ? xScale.getPixelForDecimal(0.5) : xScale.getPixelForValue(parsed[xScale.id]);
-                       const y = reset ? yScale.getBasePixel() : yScale.getPixelForValue(parsed[yScale.id]);
+                       const x = reset ? xScale.getPixelForDecimal(0.5) : xScale.getPixelForValue(parsed.x);
+                       const y = reset ? yScale.getBasePixel() : yScale.getPixelForValue(parsed.y);
                        const properties = {
                                x,
                                y,
index dd8eded5bf0eb5a59fbf0e1c7c65e8f344de47e5..d56f04cf35818a5360d1885034565a34d059e51c 100644 (file)
@@ -104,8 +104,8 @@ module.exports = DatasetController.extend({
                        const index = start + i;
                        const point = points[i];
                        const parsed = me._getParsed(index);
-                       const x = xScale.getPixelForValue(parsed[xScale.id]);
-                       const y = reset ? yScale.getBasePixel() : yScale.getPixelForValue(_stacked ? me._applyStack(yScale, parsed) : parsed[yScale.id]);
+                       const x = xScale.getPixelForValue(parsed.x);
+                       const y = reset ? yScale.getBasePixel() : yScale.getPixelForValue(_stacked ? me._applyStack(yScale, parsed) : parsed.y);
                        const properties = {
                                x,
                                y,
index ab1f18c1cd1426a95caf5e74cb4f4c3d9d8b6f24..834ff698ff94765867cc046844247b0556fe32a0 100644 (file)
@@ -81,7 +81,7 @@ module.exports = DatasetController.extend({
 
                return {
                        label: vScale._getLabels()[index],
-                       value: '' + vScale.getLabelForValue(parsed[vScale.id])
+                       value: '' + vScale.getLabelForValue(parsed[vScale.axis])
                };
        },
 
index 8ed4310f504ab0602333a034173e922b8698eb21..ec5f260ca5f527edc86de5a6670a5f1a5de5ac42 100644 (file)
@@ -193,17 +193,17 @@ function updateStacks(controller, parsed) {
        const {chart, _cachedMeta: meta} = controller;
        const stacks = chart._stacks || (chart._stacks = {}); // map structure is {stackKey: {datasetIndex: value}}
        const {iScale, vScale, index: datasetIndex} = meta;
-       const iId = iScale.id;
-       const vId = vScale.id;
+       const iAxis = iScale.axis;
+       const vAxis = vScale.axis;
        const key = getStackKey(iScale, vScale, meta);
        const ilen = parsed.length;
        let stack;
 
        for (let i = 0; i < ilen; ++i) {
                const item = parsed[i];
-               const {[iId]: index, [vId]: value} = item;
+               const {[iAxis]: index, [vAxis]: value} = item;
                const itemStacks = item._stacks || (item._stacks = {});
-               stack = itemStacks[vId] = getOrCreateStack(stacks, key, index);
+               stack = itemStacks[vAxis] = getOrCreateStack(stacks, key, index);
                stack[datasetIndex] = value;
        }
 }
@@ -478,7 +478,7 @@ helpers.extend(DatasetController.prototype, {
                const me = this;
                const {_cachedMeta: meta, _data: data} = me;
                const {iScale, vScale, _stacked} = meta;
-               const iScaleId = iScale.id;
+               const iAxis = iScale.axis;
                let sorted = true;
                let i, parsed, cur, prev;
 
@@ -503,7 +503,7 @@ helpers.extend(DatasetController.prototype, {
                        for (i = 0; i < count; ++i) {
                                meta._parsed[i + start] = cur = parsed[i];
                                if (sorted) {
-                                       if (prev && cur[iScaleId] < prev[iScaleId]) {
+                                       if (prev && cur[iAxis] < prev[iAxis]) {
                                                sorted = false;
                                        }
                                        prev = cur;
@@ -533,8 +533,8 @@ helpers.extend(DatasetController.prototype, {
         */
        _parsePrimitiveData: function(meta, data, start, count) {
                const {iScale, vScale} = meta;
-               const iId = iScale.id;
-               const vId = vScale.id;
+               const iAxis = iScale.axis;
+               const vAxis = vScale.axis;
                const labels = iScale._getLabels();
                const singleScale = iScale === vScale;
                const parsed = new Array(count);
@@ -543,8 +543,8 @@ helpers.extend(DatasetController.prototype, {
                for (i = 0, ilen = count; i < ilen; ++i) {
                        index = i + start;
                        parsed[i] = {
-                               [iId]: singleScale || iScale._parse(labels[index], index),
-                               [vId]: vScale._parse(data[index], index)
+                               [iAxis]: singleScale || iScale._parse(labels[index], index),
+                               [vAxis]: vScale._parse(data[index], index)
                        };
                }
                return parsed;
@@ -558,13 +558,11 @@ helpers.extend(DatasetController.prototype, {
         * @param {number} count - number of items to parse
         * @returns {object} parsed item - item containing index and a parsed value
         * for each scale id.
-        * Example: {xScale0: 0, yScale0: 1}
+        * Example: {x: 0, y: 1}
         * @private
         */
        _parseArrayData: function(meta, data, start, count) {
                const {xScale, yScale} = meta;
-               const xId = xScale.id;
-               const yId = yScale.id;
                const parsed = new Array(count);
                let i, ilen, index, item;
 
@@ -572,8 +570,8 @@ helpers.extend(DatasetController.prototype, {
                        index = i + start;
                        item = data[index];
                        parsed[i] = {
-                               [xId]: xScale._parse(item[0], index),
-                               [yId]: yScale._parse(item[1], index)
+                               x: xScale._parse(item[0], index),
+                               y: yScale._parse(item[1], index)
                        };
                }
                return parsed;
@@ -592,8 +590,6 @@ helpers.extend(DatasetController.prototype, {
         */
        _parseObjectData: function(meta, data, start, count) {
                const {xScale, yScale} = meta;
-               const xId = xScale.id;
-               const yId = yScale.id;
                const parsed = new Array(count);
                let i, ilen, index, item;
 
@@ -601,8 +597,8 @@ helpers.extend(DatasetController.prototype, {
                        index = i + start;
                        item = data[index];
                        parsed[i] = {
-                               [xId]: xScale._parseObject(item, 'x', index),
-                               [yId]: yScale._parseObject(item, 'y', index)
+                               x: xScale._parseObject(item, 'x', index),
+                               y: yScale._parseObject(item, 'y', index)
                        };
                }
                return parsed;
@@ -612,11 +608,7 @@ helpers.extend(DatasetController.prototype, {
         * @private
         */
        _getParsed: function(index) {
-               const data = this._cachedMeta._parsed;
-               if (index < 0 || index >= data.length) {
-                       return;
-               }
-               return data[index];
+               return this._cachedMeta._parsed[index];
        },
 
        /**
@@ -625,10 +617,10 @@ helpers.extend(DatasetController.prototype, {
        _applyStack: function(scale, parsed) {
                const chart = this.chart;
                const meta = this._cachedMeta;
-               const value = parsed[scale.id];
+               const value = parsed[scale.axis];
                const stack = {
                        keys: getSortedDatasetIndices(chart, true),
-                       values: parsed._stacks[scale.id]
+                       values: parsed._stacks[scale.axis]
                };
                return applyStack(stack, value, meta.index);
        },
@@ -651,7 +643,7 @@ helpers.extend(DatasetController.prototype, {
 
                function _compute() {
                        if (stack) {
-                               stack.values = parsed._stacks[scale.id];
+                               stack.values = parsed._stacks[scale.axis];
                                // Need to consider individual stack values for data range,
                                // in addition to the stacked value
                                min = Math.min(min, value);
@@ -668,8 +660,8 @@ helpers.extend(DatasetController.prototype, {
                function _skip() {
                        item = data[i];
                        parsed = _parsed[i];
-                       value = parsed[scale.id];
-                       otherValue = parsed[otherScale.id];
+                       value = parsed[scale.axis];
+                       otherValue = parsed[otherScale.axis];
                        return ((item && item.hidden) || isNaN(value) || otherMin > otherValue || otherMax < otherValue);
                }
 
@@ -703,7 +695,7 @@ helpers.extend(DatasetController.prototype, {
                let i, ilen, value;
 
                for (i = 0, ilen = parsed.length; i < ilen; ++i) {
-                       value = parsed[i][scale.id];
+                       value = parsed[i][scale.axis];
                        if (!isNaN(value)) {
                                values.push(value);
                        }
@@ -759,8 +751,8 @@ helpers.extend(DatasetController.prototype, {
                const vScale = meta.vScale;
                const parsed = me._getParsed(index);
                return {
-                       label: iScale ? '' + iScale.getLabelForValue(parsed[iScale.id]) : '',
-                       value: vScale ? '' + vScale.getLabelForValue(parsed[vScale.id]) : ''
+                       label: iScale ? '' + iScale.getLabelForValue(parsed[iScale.axis]) : '',
+                       value: vScale ? '' + vScale.getLabelForValue(parsed[vScale.axis]) : ''
                };
        },
 
index ca7182eb33c018d0935a25457f79d9a7563df8a7..37545d79b2bcc611bef9180b5aaff1f112aa4ac9 100644 (file)
@@ -118,6 +118,55 @@ describe('Chart.DatasetController', function() {
                });
        });
 
+       it('should parse data using correct scales', function() {
+               const data1 = [0, 1, 2, 3, 4, 5];
+               const data2 = ['a', 'b', 'c', 'd', 'a'];
+               const chart = acquireChart({
+                       type: 'line',
+                       data: {
+                               datasets: [
+                                       {data: data1},
+                                       {data: data2, xAxisID: 'x2', yAxisID: 'y2'}
+                               ]
+                       },
+                       options: {
+                               scales: {
+                                       x: {
+                                               type: 'category',
+                                               labels: ['one', 'two', 'three', 'four', 'five', 'six']
+                                       },
+                                       x2: {
+                                               type: 'logarithmic',
+                                               labels: ['1', '10', '100', '1000', '2000']
+                                       },
+                                       y: {
+                                               type: 'linear'
+                                       },
+                                       y2: {
+                                               type: 'category',
+                                               labels: ['a', 'b', 'c', 'd', 'e']
+                                       }
+                               }
+                       }
+               });
+
+               const meta1 = chart.getDatasetMeta(0);
+               const parsedXValues1 = meta1._parsed.map(p => p.x);
+               const parsedYValues1 = meta1._parsed.map(p => p.y);
+
+               expect(meta1.data.length).toBe(6);
+               expect(parsedXValues1).toEqual([0, 1, 2, 3, 4, 5]); // label indices
+               expect(parsedYValues1).toEqual(data1);
+
+               const meta2 = chart.getDatasetMeta(1);
+               const parsedXValues2 = meta2._parsed.map(p => p.x);
+               const parsedYValues2 = meta2._parsed.map(p => p.y);
+
+               expect(meta2.data.length).toBe(5);
+               expect(parsedXValues2).toEqual([1, 10, 100, 1000, 2000]); // logarithmic scale labels
+               expect(parsedYValues2).toEqual([0, 1, 2, 3, 0]); // label indices
+       });
+
        it('should synchronize metadata when data are inserted or removed and parsing is on', function() {
                const data = [0, 1, 2, 3, 4, 5];
                const chart = acquireChart({