}
function parseArrayOrPrimitive(meta, data, start, count) {
- var iScale = this._getIndexScale();
- var vScale = this._getValueScale();
- var labels = iScale._getLabels();
- var singleScale = iScale === vScale;
- var parsed = [];
- var i, ilen, item, entry;
+ const iScale = meta.iScale;
+ const vScale = meta.vScale;
+ const labels = iScale._getLabels();
+ const singleScale = iScale === vScale;
+ const parsed = [];
+ let i, ilen, item, entry;
for (i = start, ilen = start + count; i < ilen; ++i) {
entry = data[i];
* @private
*/
_parseObjectData: function(meta, data, start, count) {
- var iScale = this._getIndexScale();
- var vScale = this._getValueScale();
- var vProp = vScale._getAxis();
- var parsed = [];
- var i, ilen, item, obj, value;
+ const iScale = meta.iScale;
+ const vScale = meta.vScale;
+ const vProp = vScale._getAxis();
+ const parsed = [];
+ let i, ilen, item, obj, value;
for (i = start, ilen = start + count; i < ilen; ++i) {
obj = data[i];
item = {};
*/
_getLabelAndValue: function(index) {
const me = this;
- const indexScale = me._getIndexScale();
- const valueScale = me._getValueScale();
+ const meta = me._cachedMeta;
+ const indexScale = meta.iScale;
+ const valueScale = meta.vScale;
const parsed = me._getParsed(index);
const custom = parsed._custom;
const value = custom
DatasetController.prototype.initialize.apply(me, arguments);
- meta = me.getMeta();
+ meta = me._cachedMeta;
meta.stack = me.getDataset().stack;
meta.bar = true;
},
update: function(reset) {
var me = this;
- var rects = me.getMeta().data;
+ var rects = me._cachedMeta.data;
var i, ilen;
me._ruler = me.getRuler();
* @private
*/
_updateElementGeometry: function(rectangle, index, reset, options) {
- var me = this;
- var model = rectangle._model;
- var vscale = me._getValueScale();
- var base = vscale.getBasePixel();
- var horizontal = vscale.isHorizontal();
- var ruler = me._ruler || me.getRuler();
- var vpixels = me.calculateBarValuePixels(index, options);
- var ipixels = me.calculateBarIndexPixels(index, ruler, options);
+ const me = this;
+ const meta = me._cachedMeta;
+ const model = rectangle._model;
+ const vScale = meta.vScale;
+ const base = vScale.getBasePixel();
+ const horizontal = vScale.isHorizontal();
+ const ruler = me._ruler || me.getRuler();
+ const vpixels = me.calculateBarValuePixels(index, options);
+ const ipixels = me.calculateBarIndexPixels(index, ruler, options);
model.horizontal = horizontal;
model.base = reset ? base : vpixels.base;
* @private
*/
_getStacks: function(last) {
- var me = this;
- var scale = me._getIndexScale();
- var metasets = scale._getMatchingVisibleMetas(me._type);
- var stacked = scale.options.stacked;
- var ilen = metasets.length;
- var stacks = [];
- var i, meta;
+ const me = this;
+ const meta = me._cachedMeta;
+ const iScale = meta.iScale;
+ const metasets = iScale._getMatchingVisibleMetas(me._type);
+ const stacked = iScale.options.stacked;
+ const ilen = metasets.length;
+ const stacks = [];
+ let i, item;
for (i = 0; i < ilen; ++i) {
- meta = metasets[i];
+ item = metasets[i];
// stacked | meta.stack
// | found | not found | undefined
// false | x | x | x
// true | | x |
// undefined | | x | x
- if (stacked === false || stacks.indexOf(meta.stack) === -1 ||
- (stacked === undefined && meta.stack === undefined)) {
- stacks.push(meta.stack);
+ if (stacked === false || stacks.indexOf(item.stack) === -1 ||
+ (stacked === undefined && item.stack === undefined)) {
+ stacks.push(item.stack);
}
- if (meta.index === last) {
+ if (item.index === last) {
break;
}
}
* @private
*/
getRuler: function() {
- var me = this;
- var scale = me._getIndexScale();
- var pixels = [];
- var i, ilen;
+ const me = this;
+ const meta = me._cachedMeta;
+ const iScale = meta.iScale;
+ const pixels = [];
+ let i, ilen;
- for (i = 0, ilen = me.getMeta().data.length; i < ilen; ++i) {
- pixels.push(scale.getPixelForValue(me._getParsed(i)[scale.id]));
+ for (i = 0, ilen = meta.data.length; i < ilen; ++i) {
+ pixels.push(iScale.getPixelForValue(me._getParsed(i)[iScale.id]));
}
return {
- pixels: pixels,
- start: scale._startPixel,
- end: scale._endPixel,
+ pixels,
+ start: iScale._startPixel,
+ end: iScale._endPixel,
stackCount: me.getStackCount(),
- scale: scale
+ scale: iScale
};
},
* @private
*/
calculateBarValuePixels: function(index, options) {
- var me = this;
- var valueScale = me._getValueScale();
- var minBarLength = options.minBarLength;
- var start = 0;
- var parsed = me._getParsed(index);
- var value = parsed[valueScale.id];
- var custom = parsed._custom;
- var length = me._cachedMeta._stacked ? me._applyStack(valueScale, parsed) : parsed[valueScale.id];
- var base, head, size;
+ const me = this;
+ const meta = me._cachedMeta;
+ const vScale = meta.vScale;
+ const minBarLength = options.minBarLength;
+ const parsed = me._getParsed(index);
+ const custom = parsed._custom;
+ let value = parsed[vScale.id];
+ let start = 0;
+ let length = meta._stacked ? me._applyStack(vScale, parsed) : parsed[vScale.id];
+ let base, head, size;
if (length !== value) {
start = length - value;
start += value;
}
- base = valueScale.getPixelForValue(start);
- head = valueScale.getPixelForValue(start + length);
+ base = vScale.getPixelForValue(start);
+ head = vScale.getPixelForValue(start + length);
size = head - base;
if (minBarLength !== undefined && Math.abs(size) < minBarLength) {
? computeFlexCategoryTraits(index, ruler, options)
: computeFitCategoryTraits(index, ruler, options);
- var stackIndex = me.getStackIndex(me.index, me.getMeta().stack);
+ var stackIndex = me.getStackIndex(me.index, me._cachedMeta.stack);
var center = range.start + (range.chunk * stackIndex) + (range.chunk / 2);
var size = Math.min(
valueOrDefault(options.maxBarThickness, Infinity),
},
draw: function() {
- var me = this;
- var chart = me.chart;
- var scale = me._getValueScale();
- var rects = me.getMeta().data;
- var ilen = rects.length;
- var i = 0;
+ const me = this;
+ const chart = me.chart;
+ const meta = me._cachedMeta;
+ const vScale = meta.vScale;
+ const rects = meta.data;
+ const ilen = rects.length;
+ let i = 0;
helpers.canvas.clipArea(chart.ctx, chart.chartArea);
for (; i < ilen; ++i) {
- if (!isNaN(me._getParsed(i)[scale.id])) {
+ if (!isNaN(me._getParsed(i)[vScale.id])) {
rects[i].draw();
}
}
max: maxDefined ? max : Number.POSITIVE_INFINITY
};
}
+
+function getOrCreateStack(stacks, stackKey, indexValue) {
+ const subStack = stacks[stackKey] || (stacks[stackKey] = {});
+ return subStack[indexValue] || (subStack[indexValue] = {});
+}
+
+function updateStacks(controller, parsed) {
+ const chart = controller.chart;
+ const meta = controller._cachedMeta;
+ const stacks = chart._stacks || (chart._stacks = {}); // map structure is {stackKey: {datasetIndex: value}}
+ const xScale = meta.xScale;
+ const yScale = meta.yScale;
+ const xId = xScale.id;
+ const yId = yScale.id;
+ const xStacked = isStacked(xScale, meta);
+ const yStacked = isStacked(yScale, meta);
+ const xKey = yStacked && getStackKey(xScale, yScale, meta);
+ const yKey = xStacked && getStackKey(yScale, xScale, meta);
+ const ilen = parsed.length;
+ const datasetIndex = meta.index;
+ let stack;
+
+ for (let i = 0; i < ilen; ++i) {
+ const item = parsed[i];
+ const x = item[xId];
+ const y = item[yId];
+ const itemStacks = item._stacks || (item._stacks = {});
+
+ if (yStacked) {
+ stack = itemStacks[yId] = getOrCreateStack(stacks, xKey, x);
+ stack[datasetIndex] = y;
+ }
+ if (xStacked) {
+ stack = itemStacks[xId] = getOrCreateStack(stacks, yKey, y);
+ stack[datasetIndex] = x;
+ }
+ }
+}
+
// Base class for all dataset controllers (line, bar, etc)
var DatasetController = function(chart, datasetIndex) {
this.initialize(chart, datasetIndex);
],
initialize: function(chart, datasetIndex) {
- var me = this;
- var meta;
+ const me = this;
+ let meta;
me.chart = chart;
me.index = datasetIndex;
me._cachedMeta = meta = me.getMeta();
me._type = meta.type;
me.linkScales();
- meta._stacked = isStacked(me._getValueScale(), meta);
+ meta._stacked = isStacked(meta.vScale, meta);
me.addElements();
},
},
linkScales: function() {
- var chart = this.chart;
- var meta = this._cachedMeta;
- var dataset = this.getDataset();
-
- meta.xAxisID = dataset.xAxisID || getFirstScaleId(chart, 'x');
- meta.yAxisID = dataset.yAxisID || getFirstScaleId(chart, 'y');
+ const me = this;
+ const chart = me.chart;
+ const meta = me._cachedMeta;
+ const dataset = me.getDataset();
+ const xid = meta.xAxisID = dataset.xAxisID || getFirstScaleId(chart, 'x');
+ const yid = meta.yAxisID = dataset.yAxisID || getFirstScaleId(chart, 'y');
+ meta.xScale = me.getScaleForId(xid);
+ meta.yScale = me.getScaleForId(yid);
+ meta.iScale = me._getIndexScale();
+ meta.vScale = me._getValueScale();
},
getDataset: function() {
* @private
*/
_getOtherScale: function(scale) {
- return scale.id === this._getIndexScaleId()
- ? this._getValueScale()
- : this._getIndexScale();
+ const meta = this._cachedMeta;
+ return scale === meta.iScale
+ ? meta.vScale
+ : meta.iScale;
},
reset: function() {
* @private
*/
_labelCheck: function() {
- var me = this;
- var scale = me._getIndexScale();
- var labels = scale ? scale._getLabels() : me.chart.data.labels;
+ const me = this;
+ const iScale = me._cachedMeta.iScale;
+ const labels = iScale ? iScale._getLabels() : me.chart.data.labels;
if (me._labels === labels) {
return false;
},
buildOrUpdateElements: function() {
- var me = this;
- var dataChanged = me._dataCheck();
- var labelsChanged = me._labelCheck();
- var scaleChanged = me._scaleCheck();
- var meta = me._cachedMeta;
+ const me = this;
+ const dataChanged = me._dataCheck();
+ const labelsChanged = me._labelCheck();
+ const scaleChanged = me._scaleCheck();
+ const meta = me._cachedMeta;
// make sure cached _stacked status is current
- meta._stacked = isStacked(me._getValueScale(), meta);
+ meta._stacked = isStacked(meta.vScale, meta);
// Re-sync meta data in case the user replaced the data array or if we missed
// any updates and so make sure that we handle number of datapoints changing.
* @private
*/
_configure: function() {
- var me = this;
+ const me = this;
me._config = helpers.merge({}, [
me.chart.options.datasets[me._type],
me.getDataset(),
*/
_parse: function(start, count) {
const me = this;
- const chart = me.chart;
const meta = me._cachedMeta;
const data = me._data;
- const stacks = chart._stacks || (chart._stacks = {}); // map structure is {stackKey: {datasetIndex: value}}
- const xScale = me._getIndexScale();
- const yScale = me._getValueScale();
- const xId = xScale.id;
- const yId = yScale.id;
- const xStacked = isStacked(xScale, meta);
- const yStacked = isStacked(yScale, meta);
- const xKey = yStacked && getStackKey(xScale, yScale, meta);
- const yKey = xStacked && getStackKey(yScale, xScale, meta);
- const stacked = xStacked || yStacked;
- var i, ilen, parsed, stack, item, x, y;
+ const iScale = meta.iScale;
+ const vScale = meta.vScale;
+ const stacked = isStacked(iScale, meta) || isStacked(vScale, meta);
+ let i, ilen, parsed;
if (helpers.isArray(data[start])) {
parsed = me._parseArrayData(meta, data, start, count);
parsed = me._parsePrimitiveData(meta, data, start, count);
}
- function storeStack(stackKey, indexValue, scaleId, value) {
- stackKey += '.' + indexValue;
- item._stackKeys[scaleId] = stackKey;
- stack = stacks[stackKey] || (stacks[stackKey] = {});
- stack[meta.index] = value;
- }
-
for (i = 0, ilen = parsed.length; i < ilen; ++i) {
- item = parsed[i];
- meta.data[start + i]._parsed = item;
-
- if (stacked) {
- item._stackKeys = {};
- x = item[xId];
- y = item[yId];
-
- if (yStacked) {
- storeStack(xKey, x, yId, y);
- }
- if (xStacked) {
- storeStack(yKey, y, xId, x);
- }
- }
+ meta.data[start + i]._parsed = parsed[i];
+ }
+ if (stacked) {
+ updateStacks(me, parsed);
}
- xScale._invalidateCaches();
- if (yScale !== xScale) {
- yScale._invalidateCaches();
+ iScale._invalidateCaches();
+ if (vScale !== iScale) {
+ vScale._invalidateCaches();
}
},
* @private
*/
_parsePrimitiveData: function(meta, data, start, count) {
- var iScale = this._getIndexScale();
- var vScale = this._getValueScale();
- var labels = iScale._getLabels();
- var singleScale = iScale === vScale;
- var parsed = [];
- var i, ilen, item;
+ const iScale = meta.iScale;
+ const vScale = meta.vScale;
+ const labels = iScale._getLabels();
+ const singleScale = iScale === vScale;
+ const parsed = [];
+ let i, ilen, item;
for (i = start, ilen = start + count; i < ilen; ++i) {
item = {};
* @private
*/
_parseArrayData: function(meta, data, start, count) {
- var xScale = this.getScaleForId(meta.xAxisID);
- var yScale = this.getScaleForId(meta.yAxisID);
- var parsed = [];
- var i, ilen, item, arr;
+ const xScale = meta.xScale;
+ const yScale = meta.yScale;
+ const parsed = [];
+ let i, ilen, item, arr;
for (i = start, ilen = start + count; i < ilen; ++i) {
arr = data[i];
item = {};
* @private
*/
_parseObjectData: function(meta, data, start, count) {
- var xScale = this.getScaleForId(meta.xAxisID);
- var yScale = this.getScaleForId(meta.yAxisID);
- var parsed = [];
- var i, ilen, item, obj;
+ const xScale = meta.xScale;
+ const yScale = meta.yScale;
+ const parsed = [];
+ let i, ilen, item, obj;
for (i = start, ilen = start + count; i < ilen; ++i) {
obj = data[i];
item = {};
* @private
*/
_getParsed: function(index) {
- var data = this._cachedMeta.data;
+ const data = this._cachedMeta.data;
if (index < 0 || index >= data.length) {
return;
}
* @private
*/
_applyStack: function(scale, parsed) {
- var chart = this.chart;
- var meta = this._cachedMeta;
- var value = parsed[scale.id];
- var stack = {
+ const chart = this.chart;
+ const meta = this._cachedMeta;
+ const value = parsed[scale.id];
+ const stack = {
keys: getSortedDatasetIndices(chart, true),
- values: chart._stacks[parsed._stackKeys[scale.id]]
+ values: parsed._stacks[scale.id]
};
return applyStack(stack, value, meta.index);
},
* @private
*/
_getMinMax: function(scale, canStack) {
- var chart = this.chart;
- var meta = this._cachedMeta;
- var metaData = meta.data;
- var ilen = metaData.length;
- var stacks = chart._stacks || (chart._stacks = {});
- var max = Number.NEGATIVE_INFINITY;
- var stacked = canStack && meta._stacked;
- var indices = getSortedDatasetIndices(chart, true);
- var otherScale = this._getOtherScale(scale);
- var {min: otherMin, max: otherMax} = getUserBounds(otherScale);
- var i, item, value, parsed, stack, min, minPositive, otherValue;
+ const chart = this.chart;
+ const meta = this._cachedMeta;
+ const metaData = meta.data;
+ const ilen = metaData.length;
+ const stacked = canStack && meta._stacked;
+ const indices = getSortedDatasetIndices(chart, true);
+ const otherScale = this._getOtherScale(scale);
+ let max = Number.NEGATIVE_INFINITY;
+ let {min: otherMin, max: otherMax} = getUserBounds(otherScale);
+ let i, item, value, parsed, stack, min, minPositive, otherValue;
min = minPositive = Number.POSITIVE_INFINITY;
if (stacked) {
stack = {
keys: indices,
- values: stacks[parsed._stackKeys[scale.id]]
+ values: parsed._stacks[scale.id]
};
value = applyStack(stack, value, meta.index, true);
}
* @private
*/
_getAllParsedValues: function(scale) {
- var meta = this._cachedMeta;
- var metaData = meta.data;
- var values = [];
- var i, ilen, value;
+ const meta = this._cachedMeta;
+ const metaData = meta.data;
+ const values = [];
+ let i, ilen, value;
for (i = 0, ilen = metaData.length; i < ilen; ++i) {
value = metaData[i]._parsed[scale.id];
* @private
*/
_cacheScaleStackStatus: function() {
- var me = this;
- var indexScale = me._getIndexScale();
- var valueScale = me._getValueScale();
- var cache = me._scaleStacked = {};
- if (indexScale && valueScale) {
- cache[indexScale.id] = indexScale.options.stacked;
- cache[valueScale.id] = valueScale.options.stacked;
+ const me = this;
+ const meta = me._cachedMeta;
+ const iScale = meta.iScale;
+ const vScale = meta.vScale;
+ const cache = me._scaleStacked = {};
+ if (iScale && vScale) {
+ cache[iScale.id] = iScale.options.stacked;
+ cache[vScale.id] = vScale.options.stacked;
}
},
* @private
*/
_scaleCheck: function() {
- var me = this;
- var indexScale = me._getIndexScale();
- var valueScale = me._getValueScale();
- var cache = me._scaleStacked;
+ const me = this;
+ const meta = me._cachedMeta;
+ const iScale = meta.iScale;
+ const vScale = meta.vScale;
+ const cache = me._scaleStacked;
return !cache ||
- !indexScale ||
- !valueScale ||
- cache[indexScale.id] !== indexScale.options.stacked ||
- cache[valueScale.id] !== valueScale.options.stacked;
+ !iScale ||
+ !vScale ||
+ cache[iScale.id] !== iScale.options.stacked ||
+ cache[vScale.id] !== vScale.options.stacked;
},
/**
*/
_getLabelAndValue: function(index) {
const me = this;
- const indexScale = me._getIndexScale();
- const valueScale = me._getValueScale();
+ const meta = me._cachedMeta;
+ const iScale = meta.iScale;
+ const vScale = meta.vScale;
const parsed = me._getParsed(index);
return {
- label: indexScale ? '' + indexScale.getLabelForValue(parsed[indexScale.id]) : '',
- value: valueScale ? '' + valueScale.getLabelForValue(parsed[valueScale.id]) : ''
+ label: iScale ? '' + iScale.getLabelForValue(parsed[iScale.id]) : '',
+ value: vScale ? '' + vScale.getLabelForValue(parsed[vScale.id]) : ''
};
},
* @private
*/
_update: function(reset) {
- var me = this;
+ const me = this;
+ const meta = me._cachedMeta;
me._configure();
me._cachedDataOpts = null;
me.update(reset);
- me._cachedMeta._clip = toClip(helpers.valueOrDefault(me._config.clip, defaultClip(me._xScale, me._yScale, me._getMaxOverflow())));
+ meta._clip = toClip(helpers.valueOrDefault(me._config.clip, defaultClip(meta.xScale, meta.yScale, me._getMaxOverflow())));
me._cacheScaleStackStatus();
},
update: helpers.noop,
transition: function(easingValue) {
- var meta = this._cachedMeta;
- var elements = meta.data || [];
- var ilen = elements.length;
- var i = 0;
+ const meta = this._cachedMeta;
+ const elements = meta.data || [];
+ const ilen = elements.length;
+ let i = 0;
for (; i < ilen; ++i) {
elements[i].transition(easingValue);
},
draw: function() {
- var meta = this._cachedMeta;
- var elements = meta.data || [];
- var ilen = elements.length;
- var i = 0;
+ const meta = this._cachedMeta;
+ const elements = meta.data || [];
+ const ilen = elements.length;
+ let i = 0;
if (meta.dataset) {
meta.dataset.draw();
* @return {IStyleInterface} style object
*/
getStyle: function(index) {
- var me = this;
- var meta = me._cachedMeta;
- var dataset = meta.dataset;
- var style;
+ const me = this;
+ const meta = me._cachedMeta;
+ const dataset = meta.dataset;
+ let style;
me._configure();
if (dataset && index === undefined) {
* @private
*/
_resolveDatasetElementOptions: function(active) {
- var me = this;
- var chart = me.chart;
- var datasetOpts = me._config;
- var options = chart.options.elements[me.datasetElementType.prototype._type] || {};
- var elementOptions = me._datasetElementOptions;
- var values = {};
- var i, ilen, key, readKey;
-
- // Scriptable options
- var context = {
+ const me = this;
+ const chart = me.chart;
+ const datasetOpts = me._config;
+ const options = chart.options.elements[me.datasetElementType.prototype._type] || {};
+ const elementOptions = me._datasetElementOptions;
+ const values = {};
+ const context = {
chart,
dataset: me.getDataset(),
datasetIndex: me.index,
active
};
+ let i, ilen, key, readKey;
for (i = 0, ilen = elementOptions.length; i < ilen; ++i) {
key = elementOptions[i];
* @private
*/
_resolveDataElementOptions: function(index) {
- var me = this;
- var cached = me._cachedDataOpts;
+ const me = this;
+ const cached = me._cachedDataOpts;
if (cached) {
return cached;
}
- var chart = me.chart;
- var datasetOpts = me._config;
- var options = chart.options.elements[me.dataElementType.prototype._type] || {};
- var elementOptions = me._dataElementOptions;
- var values = {};
-
- // Scriptable options
- var context = {
+ const chart = me.chart;
+ const datasetOpts = me._config;
+ const options = chart.options.elements[me.dataElementType.prototype._type] || {};
+ const elementOptions = me._dataElementOptions;
+ const values = {};
+ const context = {
chart: chart,
dataIndex: index,
dataset: me.getDataset(),
datasetIndex: me.index
};
-
- // `resolve` sets cacheable to `false` if any option is indexed or scripted
- var info = {cacheable: true};
-
- var keys, i, ilen, key;
+ const info = {cacheable: true};
+ let keys, i, ilen, key;
if (helpers.isArray(elementOptions)) {
for (i = 0, ilen = elementOptions.length; i < ilen; ++i) {
},
setHoverStyle: function(element, datasetIndex, index) {
- var dataset = this.chart.data.datasets[datasetIndex];
- var model = element._model;
- var getHoverColor = helpers.getHoverColor;
+ const dataset = this.chart.data.datasets[datasetIndex];
+ const model = element._model;
+ const getHoverColor = helpers.getHoverColor;
element.$previousStyle = {
backgroundColor: model.backgroundColor,
* @private
*/
_removeDatasetHoverStyle: function() {
- var element = this.getMeta().dataset;
+ const element = this._cachedMeta.dataset;
if (element) {
this.removeHoverStyle(element);
* @private
*/
_setDatasetHoverStyle: function() {
- var element = this.getMeta().dataset;
- var prev = {};
- var i, ilen, key, keys, hoverOptions, model;
+ const element = this._cachedMeta.dataset;
+ const prev = {};
+ let i, ilen, key, keys, hoverOptions, model;
if (!element) {
return;
* @private
*/
resyncElements: function(changed) {
- var me = this;
- var meta = me._cachedMeta;
- var numMeta = meta.data.length;
- var numData = me._data.length;
+ const me = this;
+ const meta = me._cachedMeta;
+ const numMeta = meta.data.length;
+ const numData = me._data.length;
if (numData > numMeta) {
me.insertElements(numMeta, numData - numMeta);
insertElements: function(start, count) {
const me = this;
const elements = [];
- var i;
+ let i;
for (i = start; i < start + count; ++i) {
elements.push(me.createElement(me.dataElementType));
}
* @private
*/
onDataPush: function() {
- var count = arguments.length;
+ const count = arguments.length;
this.insertElements(this.getDataset().data.length - count, count);
},