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
// 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,
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);
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);
}
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
};
},
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 {
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) {
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);
}
}
*/
_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
});
}
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 {
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,
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,
return {
label: vScale._getLabels()[index],
- value: '' + vScale.getLabelForValue(parsed[vScale.id])
+ value: '' + vScale.getLabelForValue(parsed[vScale.axis])
};
},
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;
}
}
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;
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;
*/
_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);
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;
* @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;
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;
*/
_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;
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;
* @private
*/
_getParsed: function(index) {
- const data = this._cachedMeta._parsed;
- if (index < 0 || index >= data.length) {
- return;
- }
- return data[index];
+ return this._cachedMeta._parsed[index];
},
/**
_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);
},
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);
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);
}
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);
}
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]) : ''
};
},
});
});
+ 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({