* @protected
*/
getLabelAndValue(index) {
- const me = this;
- const meta = me._cachedMeta;
+ const meta = this._cachedMeta;
const {iScale, vScale} = meta;
- const parsed = me.getParsed(index);
+ const parsed = this.getParsed(index);
const custom = parsed._custom;
const value = isFloatBar(custom)
? '[' + custom.start + ', ' + custom.end + ']'
}
initialize() {
- const me = this;
- me.enableOptionSharing = true;
+ this.enableOptionSharing = true;
super.initialize();
- const meta = me._cachedMeta;
- meta.stack = me.getDataset().stack;
+ const meta = this._cachedMeta;
+ meta.stack = this.getDataset().stack;
}
update(mode) {
- const me = this;
- const meta = me._cachedMeta;
-
- me.updateElements(meta.data, 0, meta.data.length, mode);
+ const meta = this._cachedMeta;
+ this.updateElements(meta.data, 0, meta.data.length, mode);
}
updateElements(bars, start, count, mode) {
- const me = this;
const reset = mode === 'reset';
- const {index, _cachedMeta: {vScale}} = me;
+ const {index, _cachedMeta: {vScale}} = this;
const base = vScale.getBasePixel();
const horizontal = vScale.isHorizontal();
- const ruler = me._getRuler();
- const firstOpts = me.resolveDataElementOptions(start, mode);
- const sharedOptions = me.getSharedOptions(firstOpts);
- const includeOptions = me.includeOptions(mode, sharedOptions);
+ const ruler = this._getRuler();
+ const firstOpts = this.resolveDataElementOptions(start, mode);
+ const sharedOptions = this.getSharedOptions(firstOpts);
+ const includeOptions = this.includeOptions(mode, sharedOptions);
- me.updateSharedOptions(sharedOptions, mode, firstOpts);
+ this.updateSharedOptions(sharedOptions, mode, firstOpts);
for (let i = start; i < start + count; i++) {
- const parsed = me.getParsed(i);
- const vpixels = reset || isNullOrUndef(parsed[vScale.axis]) ? {base, head: base} : me._calculateBarValuePixels(i);
- const ipixels = me._calculateBarIndexPixels(i, ruler);
+ const parsed = this.getParsed(i);
+ const vpixels = reset || isNullOrUndef(parsed[vScale.axis]) ? {base, head: base} : this._calculateBarValuePixels(i);
+ const ipixels = this._calculateBarIndexPixels(i, ruler);
const stack = (parsed._stacks || {})[vScale.axis];
const properties = {
};
if (includeOptions) {
- properties.options = sharedOptions || me.resolveDataElementOptions(i, bars[i].active ? 'active' : mode);
+ properties.options = sharedOptions || this.resolveDataElementOptions(i, bars[i].active ? 'active' : mode);
}
setBorderSkipped(properties, properties.options || bars[i].options, stack, index);
- me.updateElement(bars[i], i, properties, mode);
+ this.updateElement(bars[i], i, properties, mode);
}
}
* @private
*/
_getStacks(last, dataIndex) {
- const me = this;
- const meta = me._cachedMeta;
+ const meta = this._cachedMeta;
const iScale = meta.iScale;
- const metasets = iScale.getMatchingVisibleMetas(me._type);
+ const metasets = iScale.getMatchingVisibleMetas(this._type);
const stacked = iScale.options.stacked;
const ilen = metasets.length;
const stacks = [];
* @private
*/
_getRuler() {
- const me = this;
- const opts = me.options;
- const meta = me._cachedMeta;
+ const opts = this.options;
+ const meta = this._cachedMeta;
const iScale = meta.iScale;
const pixels = [];
let i, ilen;
for (i = 0, ilen = meta.data.length; i < ilen; ++i) {
- pixels.push(iScale.getPixelForValue(me.getParsed(i)[iScale.axis], i));
+ pixels.push(iScale.getPixelForValue(this.getParsed(i)[iScale.axis], i));
}
const barThickness = opts.barThickness;
pixels,
start: iScale._startPixel,
end: iScale._endPixel,
- stackCount: me._getStackCount(),
+ stackCount: this._getStackCount(),
scale: iScale,
grouped: opts.grouped,
// bar thickness ratio used for non-grouped bars
* @private
*/
_calculateBarValuePixels(index) {
- const me = this;
- const {_cachedMeta: {vScale, _stacked}, options: {base: baseValue, minBarLength}} = me;
+ const {_cachedMeta: {vScale, _stacked}, options: {base: baseValue, minBarLength}} = this;
const actualBase = baseValue || 0;
- const parsed = me.getParsed(index);
+ const parsed = this.getParsed(index);
const custom = parsed._custom;
const floating = isFloatBar(custom);
let value = parsed[vScale.axis];
let start = 0;
- let length = _stacked ? me.applyStack(vScale, parsed, _stacked) : value;
+ let length = _stacked ? this.applyStack(vScale, parsed, _stacked) : value;
let head, size;
if (length !== value) {
const startValue = !isNullOrUndef(baseValue) && !floating ? baseValue : start;
let base = vScale.getPixelForValue(startValue);
- if (me.chart.getDataVisibility(index)) {
+ if (this.chart.getDataVisibility(index)) {
head = vScale.getPixelForValue(start + length);
} else {
// When not visible, no height
* @private
*/
_calculateBarIndexPixels(index, ruler) {
- const me = this;
const scale = ruler.scale;
- const options = me.options;
+ const options = this.options;
const skipNull = options.skipNull;
const maxBarThickness = valueOrDefault(options.maxBarThickness, Infinity);
let center, size;
if (ruler.grouped) {
- const stackCount = skipNull ? me._getStackCount(index) : ruler.stackCount;
+ const stackCount = skipNull ? this._getStackCount(index) : ruler.stackCount;
const range = options.barThickness === 'flex'
? computeFlexCategoryTraits(index, ruler, options, stackCount)
: computeFitCategoryTraits(index, ruler, options, stackCount);
- const stackIndex = me._getStackIndex(me.index, me._cachedMeta.stack, skipNull ? index : undefined);
+ const stackIndex = this._getStackIndex(this.index, this._cachedMeta.stack, skipNull ? index : undefined);
center = range.start + (range.chunk * stackIndex) + (range.chunk / 2);
size = Math.min(maxBarThickness, range.chunk * range.ratio);
} else {
// For non-grouped bar charts, exact pixel values are used
- center = scale.getPixelForValue(me.getParsed(index)[scale.axis], index);
+ center = scale.getPixelForValue(this.getParsed(index)[scale.axis], index);
size = Math.min(maxBarThickness, ruler.min * ruler.ratio);
}
}
draw() {
- const me = this;
- const meta = me._cachedMeta;
+ const meta = this._cachedMeta;
const vScale = meta.vScale;
const rects = meta.data;
const ilen = rects.length;
let i = 0;
for (; i < ilen; ++i) {
- if (me.getParsed(i)[vScale.axis] !== null) {
- rects[i].draw(me._ctx);
+ if (this.getParsed(i)[vScale.axis] !== null) {
+ rects[i].draw(this._ctx);
}
}
}
* @protected
*/
getLabelAndValue(index) {
- const me = this;
- const meta = me._cachedMeta;
+ const meta = this._cachedMeta;
const {xScale, yScale} = meta;
- const parsed = me.getParsed(index);
+ const parsed = this.getParsed(index);
const x = xScale.getLabelForValue(parsed.x);
const y = yScale.getLabelForValue(parsed.y);
const r = parsed._custom;
}
update(mode) {
- const me = this;
- const points = me._cachedMeta.data;
+ const points = this._cachedMeta.data;
// Update Points
- me.updateElements(points, 0, points.length, mode);
+ this.updateElements(points, 0, points.length, mode);
}
updateElements(points, start, count, mode) {
- const me = this;
const reset = mode === 'reset';
- const {iScale, vScale} = me._cachedMeta;
- const firstOpts = me.resolveDataElementOptions(start, mode);
- const sharedOptions = me.getSharedOptions(firstOpts);
- const includeOptions = me.includeOptions(mode, sharedOptions);
+ const {iScale, vScale} = this._cachedMeta;
+ const firstOpts = this.resolveDataElementOptions(start, mode);
+ const sharedOptions = this.getSharedOptions(firstOpts);
+ const includeOptions = this.includeOptions(mode, sharedOptions);
const iAxis = iScale.axis;
const vAxis = vScale.axis;
for (let i = start; i < start + count; i++) {
const point = points[i];
- const parsed = !reset && me.getParsed(i);
+ const parsed = !reset && this.getParsed(i);
const properties = {};
const iPixel = properties[iAxis] = reset ? iScale.getPixelForDecimal(0.5) : iScale.getPixelForValue(parsed[iAxis]);
const vPixel = properties[vAxis] = reset ? vScale.getBasePixel() : vScale.getPixelForValue(parsed[vAxis]);
properties.skip = isNaN(iPixel) || isNaN(vPixel);
if (includeOptions) {
- properties.options = me.resolveDataElementOptions(i, point.active ? 'active' : mode);
+ properties.options = this.resolveDataElementOptions(i, point.active ? 'active' : mode);
if (reset) {
properties.options.radius = 0;
}
}
- me.updateElement(point, i, properties, mode);
+ this.updateElement(point, i, properties, mode);
}
- me.updateSharedOptions(sharedOptions, mode, firstOpts);
+ this.updateSharedOptions(sharedOptions, mode, firstOpts);
}
/**
let min = TAU;
let max = -TAU;
- const me = this;
-
- for (let i = 0; i < me.chart.data.datasets.length; ++i) {
- if (me.chart.isDatasetVisible(i)) {
- const controller = me.chart.getDatasetMeta(i).controller;
+ for (let i = 0; i < this.chart.data.datasets.length; ++i) {
+ if (this.chart.isDatasetVisible(i)) {
+ const controller = this.chart.getDatasetMeta(i).controller;
const rotation = controller._getRotation();
const circumference = controller._getCircumference();
* @param {string} mode
*/
update(mode) {
- const me = this;
- const chart = me.chart;
+ const chart = this.chart;
const {chartArea} = chart;
- const meta = me._cachedMeta;
+ const meta = this._cachedMeta;
const arcs = meta.data;
- const spacing = me.getMaxBorderWidth() + me.getMaxOffset(arcs) + me.options.spacing;
+ const spacing = this.getMaxBorderWidth() + this.getMaxOffset(arcs) + this.options.spacing;
const maxSize = Math.max((Math.min(chartArea.width, chartArea.height) - spacing) / 2, 0);
- const cutout = Math.min(toPercentage(me.options.cutout, maxSize), 1);
- const chartWeight = me._getRingWeight(me.index);
+ const cutout = Math.min(toPercentage(this.options.cutout, maxSize), 1);
+ const chartWeight = this._getRingWeight(this.index);
// Compute the maximal rotation & circumference limits.
// If we only consider our dataset, this can cause problems when two datasets
// are both less than a circle with different rotations (starting angles)
- const {circumference, rotation} = me._getRotationExtents();
+ const {circumference, rotation} = this._getRotationExtents();
const {ratioX, ratioY, offsetX, offsetY} = getRatioAndOffset(rotation, circumference, cutout);
const maxWidth = (chartArea.width - spacing) / ratioX;
const maxHeight = (chartArea.height - spacing) / ratioY;
const maxRadius = Math.max(Math.min(maxWidth, maxHeight) / 2, 0);
- const outerRadius = toDimension(me.options.radius, maxRadius);
+ const outerRadius = toDimension(this.options.radius, maxRadius);
const innerRadius = Math.max(outerRadius * cutout, 0);
- const radiusLength = (outerRadius - innerRadius) / me._getVisibleDatasetWeightTotal();
- me.offsetX = offsetX * outerRadius;
- me.offsetY = offsetY * outerRadius;
+ const radiusLength = (outerRadius - innerRadius) / this._getVisibleDatasetWeightTotal();
+ this.offsetX = offsetX * outerRadius;
+ this.offsetY = offsetY * outerRadius;
- meta.total = me.calculateTotal();
+ meta.total = this.calculateTotal();
- me.outerRadius = outerRadius - radiusLength * me._getRingWeightOffset(me.index);
- me.innerRadius = Math.max(me.outerRadius - radiusLength * chartWeight, 0);
+ this.outerRadius = outerRadius - radiusLength * this._getRingWeightOffset(this.index);
+ this.innerRadius = Math.max(this.outerRadius - radiusLength * chartWeight, 0);
- me.updateElements(arcs, 0, arcs.length, mode);
+ this.updateElements(arcs, 0, arcs.length, mode);
}
/**
* @private
*/
_circumference(i, reset) {
- const me = this;
- const opts = me.options;
- const meta = me._cachedMeta;
- const circumference = me._getCircumference();
+ const opts = this.options;
+ const meta = this._cachedMeta;
+ const circumference = this._getCircumference();
if ((reset && opts.animation.animateRotate) || !this.chart.getDataVisibility(i) || meta._parsed[i] === null || meta.data[i].hidden) {
return 0;
}
- return me.calculateCircumference(meta._parsed[i] * circumference / TAU);
+ return this.calculateCircumference(meta._parsed[i] * circumference / TAU);
}
updateElements(arcs, start, count, mode) {
- const me = this;
const reset = mode === 'reset';
- const chart = me.chart;
+ const chart = this.chart;
const chartArea = chart.chartArea;
const opts = chart.options;
const animationOpts = opts.animation;
const centerX = (chartArea.left + chartArea.right) / 2;
const centerY = (chartArea.top + chartArea.bottom) / 2;
const animateScale = reset && animationOpts.animateScale;
- const innerRadius = animateScale ? 0 : me.innerRadius;
- const outerRadius = animateScale ? 0 : me.outerRadius;
- const firstOpts = me.resolveDataElementOptions(start, mode);
- const sharedOptions = me.getSharedOptions(firstOpts);
- const includeOptions = me.includeOptions(mode, sharedOptions);
- let startAngle = me._getRotation();
+ const innerRadius = animateScale ? 0 : this.innerRadius;
+ const outerRadius = animateScale ? 0 : this.outerRadius;
+ const firstOpts = this.resolveDataElementOptions(start, mode);
+ const sharedOptions = this.getSharedOptions(firstOpts);
+ const includeOptions = this.includeOptions(mode, sharedOptions);
+ let startAngle = this._getRotation();
let i;
for (i = 0; i < start; ++i) {
- startAngle += me._circumference(i, reset);
+ startAngle += this._circumference(i, reset);
}
for (i = start; i < start + count; ++i) {
- const circumference = me._circumference(i, reset);
+ const circumference = this._circumference(i, reset);
const arc = arcs[i];
const properties = {
- x: centerX + me.offsetX,
- y: centerY + me.offsetY,
+ x: centerX + this.offsetX,
+ y: centerY + this.offsetY,
startAngle,
endAngle: startAngle + circumference,
circumference,
innerRadius
};
if (includeOptions) {
- properties.options = sharedOptions || me.resolveDataElementOptions(i, arc.active ? 'active' : mode);
+ properties.options = sharedOptions || this.resolveDataElementOptions(i, arc.active ? 'active' : mode);
}
startAngle += circumference;
- me.updateElement(arc, i, properties, mode);
+ this.updateElement(arc, i, properties, mode);
}
- me.updateSharedOptions(sharedOptions, mode, firstOpts);
+ this.updateSharedOptions(sharedOptions, mode, firstOpts);
}
calculateTotal() {
}
getLabelAndValue(index) {
- const me = this;
- const meta = me._cachedMeta;
- const chart = me.chart;
+ const meta = this._cachedMeta;
+ const chart = this.chart;
const labels = chart.data.labels || [];
const value = formatNumber(meta._parsed[index], chart.options.locale);
}
getMaxBorderWidth(arcs) {
- const me = this;
let max = 0;
- const chart = me.chart;
+ const chart = this.chart;
let i, ilen, meta, controller, options;
if (!arcs) {
meta = chart.getDatasetMeta(i);
arcs = meta.data;
controller = meta.controller;
- if (controller !== me) {
+ if (controller !== this) {
controller.configure();
}
break;
}
update(mode) {
- const me = this;
- const meta = me._cachedMeta;
+ const meta = this._cachedMeta;
const {dataset: line, data: points = [], _dataset} = meta;
// @ts-ignore
- const animationsDisabled = me.chart._animationsDisabled;
+ const animationsDisabled = this.chart._animationsDisabled;
let {start, count} = getStartAndCountOfVisiblePoints(meta, points, animationsDisabled);
- me._drawStart = start;
- me._drawCount = count;
+ this._drawStart = start;
+ this._drawCount = count;
if (scaleRangesChanged(meta)) {
start = 0;
}
// Update Line
- line._datasetIndex = me.index;
+ line._datasetIndex = this.index;
line._decimated = !!_dataset._decimated;
line.points = points;
- const options = me.resolveDatasetElementOptions(mode);
- if (!me.options.showLine) {
+ const options = this.resolveDatasetElementOptions(mode);
+ if (!this.options.showLine) {
options.borderWidth = 0;
}
- options.segment = me.options.segment;
- me.updateElement(line, undefined, {
+ options.segment = this.options.segment;
+ this.updateElement(line, undefined, {
animated: !animationsDisabled,
options
}, mode);
// Update Points
- me.updateElements(points, start, count, mode);
+ this.updateElements(points, start, count, mode);
}
updateElements(points, start, count, mode) {
- const me = this;
const reset = mode === 'reset';
- const {iScale, vScale, _stacked} = me._cachedMeta;
- const firstOpts = me.resolveDataElementOptions(start, mode);
- const sharedOptions = me.getSharedOptions(firstOpts);
- const includeOptions = me.includeOptions(mode, sharedOptions);
+ const {iScale, vScale, _stacked} = this._cachedMeta;
+ const firstOpts = this.resolveDataElementOptions(start, mode);
+ const sharedOptions = this.getSharedOptions(firstOpts);
+ const includeOptions = this.includeOptions(mode, sharedOptions);
const iAxis = iScale.axis;
const vAxis = vScale.axis;
- const spanGaps = me.options.spanGaps;
+ const spanGaps = this.options.spanGaps;
const maxGapLength = isNumber(spanGaps) ? spanGaps : Number.POSITIVE_INFINITY;
- const directUpdate = me.chart._animationsDisabled || reset || mode === 'none';
- let prevParsed = start > 0 && me.getParsed(start - 1);
+ const directUpdate = this.chart._animationsDisabled || reset || mode === 'none';
+ let prevParsed = start > 0 && this.getParsed(start - 1);
for (let i = start; i < start + count; ++i) {
const point = points[i];
- const parsed = me.getParsed(i);
+ const parsed = this.getParsed(i);
const properties = directUpdate ? point : {};
const nullData = isNullOrUndef(parsed[vAxis]);
const iPixel = properties[iAxis] = iScale.getPixelForValue(parsed[iAxis], i);
- const vPixel = properties[vAxis] = reset || nullData ? vScale.getBasePixel() : vScale.getPixelForValue(_stacked ? me.applyStack(vScale, parsed, _stacked) : parsed[vAxis], i);
+ const vPixel = properties[vAxis] = reset || nullData ? vScale.getBasePixel() : vScale.getPixelForValue(_stacked ? this.applyStack(vScale, parsed, _stacked) : parsed[vAxis], i);
properties.skip = isNaN(iPixel) || isNaN(vPixel) || nullData;
properties.stop = i > 0 && (parsed[iAxis] - prevParsed[iAxis]) > maxGapLength;
properties.parsed = parsed;
if (includeOptions) {
- properties.options = sharedOptions || me.resolveDataElementOptions(i, point.active ? 'active' : mode);
+ properties.options = sharedOptions || this.resolveDataElementOptions(i, point.active ? 'active' : mode);
}
if (!directUpdate) {
- me.updateElement(point, i, properties, mode);
+ this.updateElement(point, i, properties, mode);
}
prevParsed = parsed;
}
- me.updateSharedOptions(sharedOptions, mode, firstOpts);
+ this.updateSharedOptions(sharedOptions, mode, firstOpts);
}
/**
* @protected
*/
getMaxOverflow() {
- const me = this;
- const meta = me._cachedMeta;
+ const meta = this._cachedMeta;
const dataset = meta.dataset;
const border = dataset.options && dataset.options.borderWidth || 0;
const data = meta.data || [];
if (!data.length) {
return border;
}
- const firstPoint = data[0].size(me.resolveDataElementOptions(0));
- const lastPoint = data[data.length - 1].size(me.resolveDataElementOptions(data.length - 1));
+ const firstPoint = data[0].size(this.resolveDataElementOptions(0));
+ const lastPoint = data[data.length - 1].size(this.resolveDataElementOptions(data.length - 1));
return Math.max(border, firstPoint, lastPoint) / 2;
}
}
getLabelAndValue(index) {
- const me = this;
- const meta = me._cachedMeta;
- const chart = me.chart;
+ const meta = this._cachedMeta;
+ const chart = this.chart;
const labels = chart.data.labels || [];
const value = formatNumber(meta._parsed[index].r, chart.options.locale);
* @private
*/
_updateRadius() {
- const me = this;
- const chart = me.chart;
+ const chart = this.chart;
const chartArea = chart.chartArea;
const opts = chart.options;
const minSize = Math.min(chartArea.right - chartArea.left, chartArea.bottom - chartArea.top);
const innerRadius = Math.max(opts.cutoutPercentage ? (outerRadius / 100) * (opts.cutoutPercentage) : 1, 0);
const radiusLength = (outerRadius - innerRadius) / chart.getVisibleDatasetCount();
- me.outerRadius = outerRadius - (radiusLength * me.index);
- me.innerRadius = me.outerRadius - radiusLength;
+ this.outerRadius = outerRadius - (radiusLength * this.index);
+ this.innerRadius = this.outerRadius - radiusLength;
}
updateElements(arcs, start, count, mode) {
- const me = this;
const reset = mode === 'reset';
- const chart = me.chart;
- const dataset = me.getDataset();
+ const chart = this.chart;
+ const dataset = this.getDataset();
const opts = chart.options;
const animationOpts = opts.animation;
- const scale = me._cachedMeta.rScale;
+ const scale = this._cachedMeta.rScale;
const centerX = scale.xCenter;
const centerY = scale.yCenter;
const datasetStartAngle = scale.getIndexAngle(0) - 0.5 * PI;
let angle = datasetStartAngle;
let i;
- const defaultAngle = 360 / me.countVisibleElements();
+ const defaultAngle = 360 / this.countVisibleElements();
for (i = 0; i < start; ++i) {
- angle += me._computeAngle(i, mode, defaultAngle);
+ angle += this._computeAngle(i, mode, defaultAngle);
}
for (i = start; i < start + count; i++) {
const arc = arcs[i];
let startAngle = angle;
- let endAngle = angle + me._computeAngle(i, mode, defaultAngle);
+ let endAngle = angle + this._computeAngle(i, mode, defaultAngle);
let outerRadius = chart.getDataVisibility(i) ? scale.getDistanceFromCenterForValue(dataset.data[i]) : 0;
angle = endAngle;
outerRadius,
startAngle,
endAngle,
- options: me.resolveDataElementOptions(i, arc.active ? 'active' : mode)
+ options: this.resolveDataElementOptions(i, arc.active ? 'active' : mode)
};
- me.updateElement(arc, i, properties, mode);
+ this.updateElement(arc, i, properties, mode);
}
}
* @protected
*/
getLabelAndValue(index) {
- const me = this;
- const vScale = me._cachedMeta.vScale;
- const parsed = me.getParsed(index);
+ const vScale = this._cachedMeta.vScale;
+ const parsed = this.getParsed(index);
return {
label: vScale.getLabels()[index],
}
update(mode) {
- const me = this;
- const meta = me._cachedMeta;
+ const meta = this._cachedMeta;
const line = meta.dataset;
const points = meta.data || [];
const labels = meta.iScale.getLabels();
line.points = points;
// In resize mode only point locations change, so no need to set the points or options.
if (mode !== 'resize') {
- const options = me.resolveDatasetElementOptions(mode);
- if (!me.options.showLine) {
+ const options = this.resolveDatasetElementOptions(mode);
+ if (!this.options.showLine) {
options.borderWidth = 0;
}
options
};
- me.updateElement(line, undefined, properties, mode);
+ this.updateElement(line, undefined, properties, mode);
}
// Update Points
- me.updateElements(points, 0, points.length, mode);
+ this.updateElements(points, 0, points.length, mode);
}
updateElements(points, start, count, mode) {
- const me = this;
- const dataset = me.getDataset();
- const scale = me._cachedMeta.rScale;
+ const dataset = this.getDataset();
+ const scale = this._cachedMeta.rScale;
const reset = mode === 'reset';
for (let i = start; i < start + count; i++) {
const point = points[i];
- const options = me.resolveDataElementOptions(i, point.active ? 'active' : mode);
+ const options = this.resolveDataElementOptions(i, point.active ? 'active' : mode);
const pointPosition = scale.getPointPositionForValue(i, dataset.data[i]);
const x = reset ? scale.xCenter : pointPosition.x;
options
};
- me.updateElement(point, i, properties, mode);
+ this.updateElement(point, i, properties, mode);
}
}
}
}
update(cfg, to, date) {
- const me = this;
- if (me._active) {
- me._notify(false);
-
- const currentValue = me._target[me._prop];
- const elapsed = date - me._start;
- const remain = me._duration - elapsed;
- me._start = date;
- me._duration = Math.floor(Math.max(remain, cfg.duration));
- me._total += elapsed;
- me._loop = !!cfg.loop;
- me._to = resolve([cfg.to, to, currentValue, cfg.from]);
- me._from = resolve([cfg.from, currentValue, to]);
+ if (this._active) {
+ this._notify(false);
+
+ const currentValue = this._target[this._prop];
+ const elapsed = date - this._start;
+ const remain = this._duration - elapsed;
+ this._start = date;
+ this._duration = Math.floor(Math.max(remain, cfg.duration));
+ this._total += elapsed;
+ this._loop = !!cfg.loop;
+ this._to = resolve([cfg.to, to, currentValue, cfg.from]);
+ this._from = resolve([cfg.from, currentValue, to]);
}
}
cancel() {
- const me = this;
- if (me._active) {
+ if (this._active) {
// update current evaluated value, for smoother animations
- me.tick(Date.now());
- me._active = false;
- me._notify(false);
+ this.tick(Date.now());
+ this._active = false;
+ this._notify(false);
}
}
tick(date) {
- const me = this;
- const elapsed = date - me._start;
- const duration = me._duration;
- const prop = me._prop;
- const from = me._from;
- const loop = me._loop;
- const to = me._to;
+ const elapsed = date - this._start;
+ const duration = this._duration;
+ const prop = this._prop;
+ const from = this._from;
+ const loop = this._loop;
+ const to = this._to;
let factor;
- me._active = from !== to && (loop || (elapsed < duration));
+ this._active = from !== to && (loop || (elapsed < duration));
- if (!me._active) {
- me._target[prop] = to;
- me._notify(true);
+ if (!this._active) {
+ this._target[prop] = to;
+ this._notify(true);
return;
}
if (elapsed < 0) {
- me._target[prop] = from;
+ this._target[prop] = from;
return;
}
factor = (elapsed / duration) % 2;
factor = loop && factor > 1 ? 2 - factor : factor;
- factor = me._easing(Math.min(1, Math.max(0, factor)));
+ factor = this._easing(Math.min(1, Math.max(0, factor)));
- me._target[prop] = me._fn(from, to, factor);
+ this._target[prop] = this._fn(from, to, factor);
}
wait() {
* @private
*/
_refresh() {
- const me = this;
-
- if (me._request) {
+ if (this._request) {
return;
}
- me._running = true;
+ this._running = true;
- me._request = requestAnimFrame.call(window, () => {
- me._update();
- me._request = null;
+ this._request = requestAnimFrame.call(window, () => {
+ this._update();
+ this._request = null;
- if (me._running) {
- me._refresh();
+ if (this._running) {
+ this._refresh();
}
});
}
* @private
*/
_update(date = Date.now()) {
- const me = this;
let remaining = 0;
- me._charts.forEach((anims, chart) => {
+ this._charts.forEach((anims, chart) => {
if (!anims.running || !anims.items.length) {
return;
}
if (draw) {
chart.draw();
- me._notify(chart, anims, date, 'progress');
+ this._notify(chart, anims, date, 'progress');
}
if (!items.length) {
anims.running = false;
- me._notify(chart, anims, date, 'complete');
+ this._notify(chart, anims, date, 'complete');
anims.initial = false;
}
remaining += items.length;
});
- me._lastDate = date;
+ this._lastDate = date;
if (remaining === 0) {
- me._running = false;
+ this._running = false;
}
}
// eslint-disable-next-line max-statements
constructor(item, userConfig) {
- const me = this;
-
const config = this.config = new Config(userConfig);
const initialCanvas = getCanvas(item);
const existingChart = getChart(initialCanvas);
);
}
- const options = config.createResolver(config.chartOptionScopes(), me.getContext());
+ const options = config.createResolver(config.chartOptionScopes(), this.getContext());
this.platform = new (config.platform || _detectPlatform(initialCanvas))();
- const context = me.platform.acquireContext(initialCanvas, options.aspectRatio);
+ const context = this.platform.acquireContext(initialCanvas, options.aspectRatio);
const canvas = context && context.canvas;
const height = canvas && canvas.height;
const width = canvas && canvas.width;
this._doResize = debounce(mode => this.update(mode), options.resizeDelay || 0);
// Add the chart instance to the global namespace
- instances[me.id] = me;
+ instances[this.id] = this;
if (!context || !canvas) {
// The given item is not a compatible context2d element, let's return before finalizing
return;
}
- animator.listen(me, 'complete', onAnimationsComplete);
- animator.listen(me, 'progress', onAnimationProgress);
+ animator.listen(this, 'complete', onAnimationsComplete);
+ animator.listen(this, 'progress', onAnimationProgress);
- me._initialize();
- if (me.attached) {
- me.update();
+ this._initialize();
+ if (this.attached) {
+ this.update();
}
}
* @private
*/
_initialize() {
- const me = this;
-
// Before init plugin notification
- me.notifyPlugins('beforeInit');
+ this.notifyPlugins('beforeInit');
- if (me.options.responsive) {
- me.resize();
+ if (this.options.responsive) {
+ this.resize();
} else {
- retinaScale(me, me.options.devicePixelRatio);
+ retinaScale(this, this.options.devicePixelRatio);
}
- me.bindEvents();
+ this.bindEvents();
// After init plugin notification
- me.notifyPlugins('afterInit');
+ this.notifyPlugins('afterInit');
- return me;
+ return this;
}
clear() {
}
_resize(width, height) {
- const me = this;
- const options = me.options;
- const canvas = me.canvas;
- const aspectRatio = options.maintainAspectRatio && me.aspectRatio;
- const newSize = me.platform.getMaximumSize(canvas, width, height, aspectRatio);
- const newRatio = options.devicePixelRatio || me.platform.getDevicePixelRatio();
- const mode = me.width ? 'resize' : 'attach';
-
- me.width = newSize.width;
- me.height = newSize.height;
- me._aspectRatio = me.aspectRatio;
- if (!retinaScale(me, newRatio, true)) {
+ const options = this.options;
+ const canvas = this.canvas;
+ const aspectRatio = options.maintainAspectRatio && this.aspectRatio;
+ const newSize = this.platform.getMaximumSize(canvas, width, height, aspectRatio);
+ const newRatio = options.devicePixelRatio || this.platform.getDevicePixelRatio();
+ const mode = this.width ? 'resize' : 'attach';
+
+ this.width = newSize.width;
+ this.height = newSize.height;
+ this._aspectRatio = this.aspectRatio;
+ if (!retinaScale(this, newRatio, true)) {
return;
}
- me.notifyPlugins('resize', {size: newSize});
+ this.notifyPlugins('resize', {size: newSize});
- callCallback(options.onResize, [me, newSize], me);
+ callCallback(options.onResize, [this, newSize], this);
- if (me.attached) {
- if (me._doResize(mode)) {
+ if (this.attached) {
+ if (this._doResize(mode)) {
// The resize update is delayed, only draw without updating.
- me.render();
+ this.render();
}
}
}
* Builds a map of scale ID to scale object for future lookup.
*/
buildOrUpdateScales() {
- const me = this;
- const options = me.options;
+ const options = this.options;
const scaleOpts = options.scales;
- const scales = me.scales;
+ const scales = this.scales;
const updated = Object.keys(scales).reduce((obj, id) => {
obj[id] = false;
return obj;
scale = new scaleClass({
id,
type: scaleType,
- ctx: me.ctx,
- chart: me
+ ctx: this.ctx,
+ chart: this
});
scales[scale.id] = scale;
}
});
each(scales, (scale) => {
- layouts.configure(me, scale, scale.options);
- layouts.addBox(me, scale);
+ layouts.configure(this, scale, scale.options);
+ layouts.addBox(this, scale);
});
}
* @private
*/
_updateMetasets() {
- const me = this;
- const metasets = me._metasets;
- const numData = me.data.datasets.length;
+ const metasets = this._metasets;
+ const numData = this.data.datasets.length;
const numMeta = metasets.length;
metasets.sort((a, b) => a.index - b.index);
if (numMeta > numData) {
for (let i = numData; i < numMeta; ++i) {
- me._destroyDatasetMeta(i);
+ this._destroyDatasetMeta(i);
}
metasets.splice(numData, numMeta - numData);
}
- me._sortedMetasets = metasets.slice(0).sort(compare2Level('order', 'index'));
+ this._sortedMetasets = metasets.slice(0).sort(compare2Level('order', 'index'));
}
/**
* @private
*/
_removeUnreferencedMetasets() {
- const me = this;
- const {_metasets: metasets, data: {datasets}} = me;
+ const {_metasets: metasets, data: {datasets}} = this;
if (metasets.length > datasets.length) {
- delete me._stacks;
+ delete this._stacks;
}
metasets.forEach((meta, index) => {
if (datasets.filter(x => x === meta._dataset).length === 0) {
- me._destroyDatasetMeta(index);
+ this._destroyDatasetMeta(index);
}
});
}
buildOrUpdateControllers() {
- const me = this;
const newControllers = [];
- const datasets = me.data.datasets;
+ const datasets = this.data.datasets;
let i, ilen;
- me._removeUnreferencedMetasets();
+ this._removeUnreferencedMetasets();
for (i = 0, ilen = datasets.length; i < ilen; i++) {
const dataset = datasets[i];
- let meta = me.getDatasetMeta(i);
- const type = dataset.type || me.config.type;
+ let meta = this.getDatasetMeta(i);
+ const type = dataset.type || this.config.type;
if (meta.type && meta.type !== type) {
- me._destroyDatasetMeta(i);
- meta = me.getDatasetMeta(i);
+ this._destroyDatasetMeta(i);
+ meta = this.getDatasetMeta(i);
}
meta.type = type;
- meta.indexAxis = dataset.indexAxis || getIndexAxis(type, me.options);
+ meta.indexAxis = dataset.indexAxis || getIndexAxis(type, this.options);
meta.order = dataset.order || 0;
meta.index = i;
meta.label = '' + dataset.label;
- meta.visible = me.isDatasetVisible(i);
+ meta.visible = this.isDatasetVisible(i);
if (meta.controller) {
meta.controller.updateIndex(i);
dataElementType: registry.getElement(dataElementType),
datasetElementType: datasetElementType && registry.getElement(datasetElementType)
});
- meta.controller = new ControllerClass(me, i);
+ meta.controller = new ControllerClass(this, i);
newControllers.push(meta.controller);
}
}
- me._updateMetasets();
+ this._updateMetasets();
return newControllers;
}
* @private
*/
_resetElements() {
- const me = this;
- each(me.data.datasets, (dataset, datasetIndex) => {
- me.getDatasetMeta(datasetIndex).controller.reset();
- }, me);
+ each(this.data.datasets, (dataset, datasetIndex) => {
+ this.getDatasetMeta(datasetIndex).controller.reset();
+ }, this);
}
/**
}
update(mode) {
- const me = this;
- const config = me.config;
+ const config = this.config;
config.update();
- me._options = config.createResolver(config.chartOptionScopes(), me.getContext());
+ this._options = config.createResolver(config.chartOptionScopes(), this.getContext());
- each(me.scales, (scale) => {
- layouts.removeBox(me, scale);
+ each(this.scales, (scale) => {
+ layouts.removeBox(this, scale);
});
- const animsDisabled = me._animationsDisabled = !me.options.animation;
+ const animsDisabled = this._animationsDisabled = !this.options.animation;
- me.ensureScalesHaveIDs();
- me.buildOrUpdateScales();
+ this.ensureScalesHaveIDs();
+ this.buildOrUpdateScales();
- const existingEvents = new Set(Object.keys(me._listeners));
- const newEvents = new Set(me.options.events);
+ const existingEvents = new Set(Object.keys(this._listeners));
+ const newEvents = new Set(this.options.events);
- if (!setsEqual(existingEvents, newEvents) || !!this._responsiveListeners !== me.options.responsive) {
+ if (!setsEqual(existingEvents, newEvents) || !!this._responsiveListeners !== this.options.responsive) {
// The configured events have changed. Rebind.
- me.unbindEvents();
- me.bindEvents();
+ this.unbindEvents();
+ this.bindEvents();
}
// plugins options references might have change, let's invalidate the cache
// https://github.com/chartjs/Chart.js/issues/5111#issuecomment-355934167
- me._plugins.invalidate();
+ this._plugins.invalidate();
- if (me.notifyPlugins('beforeUpdate', {mode, cancelable: true}) === false) {
+ if (this.notifyPlugins('beforeUpdate', {mode, cancelable: true}) === false) {
return;
}
// Make sure dataset controllers are updated and new controllers are reset
- const newControllers = me.buildOrUpdateControllers();
+ const newControllers = this.buildOrUpdateControllers();
- me.notifyPlugins('beforeElementsUpdate');
+ this.notifyPlugins('beforeElementsUpdate');
// Make sure all dataset controllers have correct meta data counts
let minPadding = 0;
- for (let i = 0, ilen = me.data.datasets.length; i < ilen; i++) {
- const {controller} = me.getDatasetMeta(i);
+ for (let i = 0, ilen = this.data.datasets.length; i < ilen; i++) {
+ const {controller} = this.getDatasetMeta(i);
const reset = !animsDisabled && newControllers.indexOf(controller) === -1;
// New controllers will be reset after the layout pass, so we only want to modify
// elements added to new datasets
controller.buildOrUpdateElements(reset);
minPadding = Math.max(+controller.getMaxOverflow(), minPadding);
}
- me._minPadding = minPadding;
- me._updateLayout(minPadding);
+ this._minPadding = minPadding;
+ this._updateLayout(minPadding);
// Only reset the controllers if we have animations
if (!animsDisabled) {
});
}
- me._updateDatasets(mode);
+ this._updateDatasets(mode);
// Do this before render so that any plugins that need final scale updates can use it
- me.notifyPlugins('afterUpdate', {mode});
+ this.notifyPlugins('afterUpdate', {mode});
- me._layers.sort(compare2Level('z', '_idx'));
+ this._layers.sort(compare2Level('z', '_idx'));
// Replay last event from before update
- if (me._lastEvent) {
- me._eventHandler(me._lastEvent, true);
+ if (this._lastEvent) {
+ this._eventHandler(this._lastEvent, true);
}
- me.render();
+ this.render();
}
/**
* @private
*/
_updateLayout(minPadding) {
- const me = this;
-
- if (me.notifyPlugins('beforeLayout', {cancelable: true}) === false) {
+ if (this.notifyPlugins('beforeLayout', {cancelable: true}) === false) {
return;
}
- layouts.update(me, me.width, me.height, minPadding);
+ layouts.update(this, this.width, this.height, minPadding);
- const area = me.chartArea;
+ const area = this.chartArea;
const noArea = area.width <= 0 || area.height <= 0;
- me._layers = [];
- each(me.boxes, (box) => {
+ this._layers = [];
+ each(this.boxes, (box) => {
if (noArea && box.position === 'chartArea') {
// Skip drawing and configuring chartArea boxes when chartArea is zero or negative
return;
if (box.configure) {
box.configure();
}
- me._layers.push(...box._layers());
- }, me);
+ this._layers.push(...box._layers());
+ }, this);
- me._layers.forEach((item, index) => {
+ this._layers.forEach((item, index) => {
item._idx = index;
});
- me.notifyPlugins('afterLayout');
+ this.notifyPlugins('afterLayout');
}
/**
* @private
*/
_updateDatasets(mode) {
- const me = this;
const isFunction = typeof mode === 'function';
- if (me.notifyPlugins('beforeDatasetsUpdate', {mode, cancelable: true}) === false) {
+ if (this.notifyPlugins('beforeDatasetsUpdate', {mode, cancelable: true}) === false) {
return;
}
- for (let i = 0, ilen = me.data.datasets.length; i < ilen; ++i) {
- me._updateDataset(i, isFunction ? mode({datasetIndex: i}) : mode);
+ for (let i = 0, ilen = this.data.datasets.length; i < ilen; ++i) {
+ this._updateDataset(i, isFunction ? mode({datasetIndex: i}) : mode);
}
- me.notifyPlugins('afterDatasetsUpdate', {mode});
+ this.notifyPlugins('afterDatasetsUpdate', {mode});
}
/**
* @private
*/
_updateDataset(index, mode) {
- const me = this;
- const meta = me.getDatasetMeta(index);
+ const meta = this.getDatasetMeta(index);
const args = {meta, index, mode, cancelable: true};
- if (me.notifyPlugins('beforeDatasetUpdate', args) === false) {
+ if (this.notifyPlugins('beforeDatasetUpdate', args) === false) {
return;
}
meta.controller._update(mode);
args.cancelable = false;
- me.notifyPlugins('afterDatasetUpdate', args);
+ this.notifyPlugins('afterDatasetUpdate', args);
}
render() {
- const me = this;
- if (me.notifyPlugins('beforeRender', {cancelable: true}) === false) {
+ if (this.notifyPlugins('beforeRender', {cancelable: true}) === false) {
return;
}
- if (animator.has(me)) {
- if (me.attached && !animator.running(me)) {
- animator.start(me);
+ if (animator.has(this)) {
+ if (this.attached && !animator.running(this)) {
+ animator.start(this);
}
} else {
- me.draw();
- onAnimationsComplete({chart: me});
+ this.draw();
+ onAnimationsComplete({chart: this});
}
}
draw() {
- const me = this;
let i;
- if (me._resizeBeforeDraw) {
- const {width, height} = me._resizeBeforeDraw;
- me._resize(width, height);
- me._resizeBeforeDraw = null;
+ if (this._resizeBeforeDraw) {
+ const {width, height} = this._resizeBeforeDraw;
+ this._resize(width, height);
+ this._resizeBeforeDraw = null;
}
- me.clear();
+ this.clear();
- if (me.width <= 0 || me.height <= 0) {
+ if (this.width <= 0 || this.height <= 0) {
return;
}
- if (me.notifyPlugins('beforeDraw', {cancelable: true}) === false) {
+ if (this.notifyPlugins('beforeDraw', {cancelable: true}) === false) {
return;
}
// Because of plugin hooks (before/afterDatasetsDraw), datasets can't
// currently be part of layers. Instead, we draw
// layers <= 0 before(default, backward compat), and the rest after
- const layers = me._layers;
+ const layers = this._layers;
for (i = 0; i < layers.length && layers[i].z <= 0; ++i) {
- layers[i].draw(me.chartArea);
+ layers[i].draw(this.chartArea);
}
- me._drawDatasets();
+ this._drawDatasets();
// Rest of layers
for (; i < layers.length; ++i) {
- layers[i].draw(me.chartArea);
+ layers[i].draw(this.chartArea);
}
- me.notifyPlugins('afterDraw');
+ this.notifyPlugins('afterDraw');
}
/**
* @private
*/
_getSortedDatasetMetas(filterVisible) {
- const me = this;
- const metasets = me._sortedMetasets;
+ const metasets = this._sortedMetasets;
const result = [];
let i, ilen;
* @private
*/
_drawDatasets() {
- const me = this;
-
- if (me.notifyPlugins('beforeDatasetsDraw', {cancelable: true}) === false) {
+ if (this.notifyPlugins('beforeDatasetsDraw', {cancelable: true}) === false) {
return;
}
- const metasets = me.getSortedVisibleDatasetMetas();
+ const metasets = this.getSortedVisibleDatasetMetas();
for (let i = metasets.length - 1; i >= 0; --i) {
- me._drawDataset(metasets[i]);
+ this._drawDataset(metasets[i]);
}
- me.notifyPlugins('afterDatasetsDraw');
+ this.notifyPlugins('afterDatasetsDraw');
}
/**
* @private
*/
_drawDataset(meta) {
- const me = this;
- const ctx = me.ctx;
+ const ctx = this.ctx;
const clip = meta._clip;
const useClip = !clip.disabled;
- const area = me.chartArea;
+ const area = this.chartArea;
const args = {
meta,
index: meta.index,
cancelable: true
};
- if (me.notifyPlugins('beforeDatasetDraw', args) === false) {
+ if (this.notifyPlugins('beforeDatasetDraw', args) === false) {
return;
}
if (useClip) {
clipArea(ctx, {
left: clip.left === false ? 0 : area.left - clip.left,
- right: clip.right === false ? me.width : area.right + clip.right,
+ right: clip.right === false ? this.width : area.right + clip.right,
top: clip.top === false ? 0 : area.top - clip.top,
- bottom: clip.bottom === false ? me.height : area.bottom + clip.bottom
+ bottom: clip.bottom === false ? this.height : area.bottom + clip.bottom
});
}
}
args.cancelable = false;
- me.notifyPlugins('afterDatasetDraw', args);
+ this.notifyPlugins('afterDatasetDraw', args);
}
getElementsAtEventForMode(e, mode, options, useFinalPosition) {
}
getDatasetMeta(datasetIndex) {
- const me = this;
- const dataset = me.data.datasets[datasetIndex];
- const metasets = me._metasets;
+ const dataset = this.data.datasets[datasetIndex];
+ const metasets = this._metasets;
let meta = metasets.filter(x => x && x._dataset === dataset).pop();
if (!meta) {
* @private
*/
_updateVisibility(datasetIndex, dataIndex, visible) {
- const me = this;
const mode = visible ? 'show' : 'hide';
- const meta = me.getDatasetMeta(datasetIndex);
+ const meta = this.getDatasetMeta(datasetIndex);
const anims = meta.controller._resolveAnimations(undefined, mode);
if (defined(dataIndex)) {
meta.data[dataIndex].hidden = !visible;
- me.update();
+ this.update();
} else {
- me.setDatasetVisibility(datasetIndex, visible);
+ this.setDatasetVisibility(datasetIndex, visible);
// Animate visible state, so hide animation can be seen. This could be handled better if update / updateDataset returned a Promise.
anims.update(meta, {visible});
- me.update((ctx) => ctx.datasetIndex === datasetIndex ? mode : undefined);
+ this.update((ctx) => ctx.datasetIndex === datasetIndex ? mode : undefined);
}
}
* @private
*/
_destroyDatasetMeta(datasetIndex) {
- const me = this;
- const meta = me._metasets && me._metasets[datasetIndex];
+ const meta = this._metasets && this._metasets[datasetIndex];
if (meta && meta.controller) {
meta.controller._destroy();
- delete me._metasets[datasetIndex];
+ delete this._metasets[datasetIndex];
}
}
_stop() {
- const me = this;
let i, ilen;
- me.stop();
- animator.remove(me);
+ this.stop();
+ animator.remove(this);
- for (i = 0, ilen = me.data.datasets.length; i < ilen; ++i) {
- me._destroyDatasetMeta(i);
+ for (i = 0, ilen = this.data.datasets.length; i < ilen; ++i) {
+ this._destroyDatasetMeta(i);
}
}
destroy() {
- const me = this;
- const {canvas, ctx} = me;
+ const {canvas, ctx} = this;
- me._stop();
- me.config.clearCache();
+ this._stop();
+ this.config.clearCache();
if (canvas) {
- me.unbindEvents();
+ this.unbindEvents();
clearCanvas(canvas, ctx);
- me.platform.releaseContext(ctx);
- me.canvas = null;
- me.ctx = null;
+ this.platform.releaseContext(ctx);
+ this.canvas = null;
+ this.ctx = null;
}
- me.notifyPlugins('destroy');
+ this.notifyPlugins('destroy');
- delete instances[me.id];
+ delete instances[this.id];
}
toBase64Image(...args) {
* @private
*/
bindUserEvents() {
- const me = this;
- const listeners = me._listeners;
- const platform = me.platform;
+ const listeners = this._listeners;
+ const platform = this.platform;
const _add = (type, listener) => {
- platform.addEventListener(me, type, listener);
+ platform.addEventListener(this, type, listener);
listeners[type] = listener;
};
- const listener = function(e, x, y) {
+ const listener = (e, x, y) => {
e.offsetX = x;
e.offsetY = y;
- me._eventHandler(e);
+ this._eventHandler(e);
};
- each(me.options.events, (type) => _add(type, listener));
+ each(this.options.events, (type) => _add(type, listener));
}
/**
* @private
*/
bindResponsiveEvents() {
- const me = this;
- if (!me._responsiveListeners) {
- me._responsiveListeners = {};
+ if (!this._responsiveListeners) {
+ this._responsiveListeners = {};
}
- const listeners = me._responsiveListeners;
- const platform = me.platform;
+ const listeners = this._responsiveListeners;
+ const platform = this.platform;
const _add = (type, listener) => {
- platform.addEventListener(me, type, listener);
+ platform.addEventListener(this, type, listener);
listeners[type] = listener;
};
const _remove = (type, listener) => {
if (listeners[type]) {
- platform.removeEventListener(me, type, listener);
+ platform.removeEventListener(this, type, listener);
delete listeners[type];
}
};
const listener = (width, height) => {
- if (me.canvas) {
- me.resize(width, height);
+ if (this.canvas) {
+ this.resize(width, height);
}
};
const attached = () => {
_remove('attach', attached);
- me.attached = true;
- me.resize();
+ this.attached = true;
+ this.resize();
_add('resize', listener);
_add('detach', detached);
};
detached = () => {
- me.attached = false;
+ this.attached = false;
_remove('resize', listener);
// Stop animating and remove metasets, so when re-attached, the animations start from begining.
- me._stop();
- me._resize(0, 0);
+ this._stop();
+ this._resize(0, 0);
_add('attach', attached);
};
- if (platform.isAttached(me.canvas)) {
+ if (platform.isAttached(this.canvas)) {
attached();
} else {
detached();
* @private
*/
unbindEvents() {
- const me = this;
-
- each(me._listeners, (listener, type) => {
- me.platform.removeEventListener(me, type, listener);
+ each(this._listeners, (listener, type) => {
+ this.platform.removeEventListener(this, type, listener);
});
- me._listeners = {};
+ this._listeners = {};
- each(me._responsiveListeners, (listener, type) => {
- me.platform.removeEventListener(me, type, listener);
+ each(this._responsiveListeners, (listener, type) => {
+ this.platform.removeEventListener(this, type, listener);
});
- me._responsiveListeners = undefined;
+ this._responsiveListeners = undefined;
}
updateHoverStyle(items, mode, enabled) {
* @param {array} activeElements New active data points
*/
setActiveElements(activeElements) {
- const me = this;
- const lastActive = me._active || [];
+ const lastActive = this._active || [];
const active = activeElements.map(({datasetIndex, index}) => {
- const meta = me.getDatasetMeta(datasetIndex);
+ const meta = this.getDatasetMeta(datasetIndex);
if (!meta) {
throw new Error('No dataset found at index ' + datasetIndex);
}
const changed = !_elementsEqual(active, lastActive);
if (changed) {
- me._active = active;
- me._updateHoverStyles(active, lastActive);
+ this._active = active;
+ this._updateHoverStyles(active, lastActive);
}
}
* @private
*/
_updateHoverStyles(active, lastActive, replay) {
- const me = this;
- const hoverOptions = me.options.hover;
+ const hoverOptions = this.options.hover;
const diff = (a, b) => a.filter(x => !b.some(y => x.datasetIndex === y.datasetIndex && x.index === y.index));
const deactivated = diff(lastActive, active);
const activated = replay ? active : diff(active, lastActive);
if (deactivated.length) {
- me.updateHoverStyle(deactivated, hoverOptions.mode, false);
+ this.updateHoverStyle(deactivated, hoverOptions.mode, false);
}
if (activated.length && hoverOptions.mode) {
- me.updateHoverStyle(activated, hoverOptions.mode, true);
+ this.updateHoverStyle(activated, hoverOptions.mode, true);
}
}
* @private
*/
_eventHandler(e, replay) {
- const me = this;
const args = {event: e, replay, cancelable: true};
const eventFilter = (plugin) => (plugin.options.events || this.options.events).includes(e.native.type);
- if (me.notifyPlugins('beforeEvent', args, eventFilter) === false) {
+ if (this.notifyPlugins('beforeEvent', args, eventFilter) === false) {
return;
}
- const changed = me._handleEvent(e, replay);
+ const changed = this._handleEvent(e, replay);
args.cancelable = false;
- me.notifyPlugins('afterEvent', args, eventFilter);
+ this.notifyPlugins('afterEvent', args, eventFilter);
if (changed || args.changed) {
- me.render();
+ this.render();
}
- return me;
+ return this;
}
/**
* @private
*/
_handleEvent(e, replay) {
- const me = this;
- const {_active: lastActive = [], options} = me;
+ const {_active: lastActive = [], options} = this;
const hoverOptions = options.hover;
// If the event is replayed from `update`, we should evaluate with the final positions.
// Find Active Elements for hover and tooltips
if (e.type !== 'mouseout') {
- active = me.getElementsAtEventForMode(e, hoverOptions.mode, hoverOptions, useFinalPosition);
- lastEvent = e.type === 'click' ? me._lastEvent : e;
+ active = this.getElementsAtEventForMode(e, hoverOptions.mode, hoverOptions, useFinalPosition);
+ lastEvent = e.type === 'click' ? this._lastEvent : e;
}
// Set _lastEvent to null while we are processing the event handlers.
// This prevents recursion if the handler calls chart.update()
- me._lastEvent = null;
+ this._lastEvent = null;
- if (_isPointInArea(e, me.chartArea, me._minPadding)) {
+ if (_isPointInArea(e, this.chartArea, this._minPadding)) {
// Invoke onHover hook
- callCallback(options.onHover, [e, active, me], me);
+ callCallback(options.onHover, [e, active, this], this);
if (e.type === 'mouseup' || e.type === 'click' || e.type === 'contextmenu') {
- callCallback(options.onClick, [e, active, me], me);
+ callCallback(options.onClick, [e, active, this], this);
}
}
changed = !_elementsEqual(active, lastActive);
if (changed || replay) {
- me._active = active;
- me._updateHoverStyles(active, lastActive, replay);
+ this._active = active;
+ this._updateHoverStyles(active, lastActive, replay);
}
- me._lastEvent = lastEvent;
+ this._lastEvent = lastEvent;
return changed;
}
}
initialize() {
- const me = this;
- const meta = me._cachedMeta;
- me.configure();
- me.linkScales();
+ const meta = this._cachedMeta;
+ this.configure();
+ this.linkScales();
meta._stacked = isStacked(meta.vScale, meta);
- me.addElements();
+ this.addElements();
}
updateIndex(datasetIndex) {
}
linkScales() {
- const me = this;
- const chart = me.chart;
- const meta = me._cachedMeta;
- const dataset = me.getDataset();
+ const chart = this.chart;
+ const meta = this._cachedMeta;
+ const dataset = this.getDataset();
const chooseId = (axis, x, y, r) => axis === 'x' ? x : axis === 'r' ? r : y;
const indexAxis = meta.indexAxis;
const iid = meta.iAxisID = chooseId(indexAxis, xid, yid, rid);
const vid = meta.vAxisID = chooseId(indexAxis, yid, xid, rid);
- meta.xScale = me.getScaleForId(xid);
- meta.yScale = me.getScaleForId(yid);
- meta.rScale = me.getScaleForId(rid);
- meta.iScale = me.getScaleForId(iid);
- meta.vScale = me.getScaleForId(vid);
+ meta.xScale = this.getScaleForId(xid);
+ meta.yScale = this.getScaleForId(yid);
+ meta.rScale = this.getScaleForId(rid);
+ meta.iScale = this.getScaleForId(iid);
+ meta.vScale = this.getScaleForId(vid);
}
getDataset() {
* @private
*/
_dataCheck() {
- const me = this;
- const dataset = me.getDataset();
+ const dataset = this.getDataset();
const data = dataset.data || (dataset.data = []);
- const _data = me._data;
+ const _data = this._data;
// In order to correctly handle data addition/deletion animation (an thus simulate
// real-time charts), we need to monitor these data modifications and synchronize
// the internal meta data accordingly.
if (isObject(data)) {
- me._data = convertObjectDataToArray(data);
+ this._data = convertObjectDataToArray(data);
} else if (_data !== data) {
if (_data) {
// This case happens when the user replaced the data array instance.
- unlistenArrayEvents(_data, me);
+ unlistenArrayEvents(_data, this);
// Discard old parsed data and stacks
- const meta = me._cachedMeta;
+ const meta = this._cachedMeta;
clearStacks(meta);
meta._parsed = [];
}
if (data && Object.isExtensible(data)) {
- listenArrayEvents(data, me);
+ listenArrayEvents(data, this);
}
- me._syncList = [];
- me._data = data;
+ this._syncList = [];
+ this._data = data;
}
}
addElements() {
- const me = this;
- const meta = me._cachedMeta;
+ const meta = this._cachedMeta;
- me._dataCheck();
+ this._dataCheck();
- if (me.datasetElementType) {
- meta.dataset = new me.datasetElementType();
+ if (this.datasetElementType) {
+ meta.dataset = new this.datasetElementType();
}
}
buildOrUpdateElements(resetNewElements) {
- const me = this;
- const meta = me._cachedMeta;
- const dataset = me.getDataset();
+ const meta = this._cachedMeta;
+ const dataset = this.getDataset();
let stackChanged = false;
- me._dataCheck();
+ this._dataCheck();
// make sure cached _stacked status is current
const oldStacked = meta._stacked;
// 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.
- me._resyncElements(resetNewElements);
+ this._resyncElements(resetNewElements);
// if stack changed, update stack values for the whole dataset
if (stackChanged || oldStacked !== meta._stacked) {
- updateStacks(me, meta._parsed);
+ updateStacks(this, meta._parsed);
}
}
* @private
*/
configure() {
- const me = this;
- const config = me.chart.config;
- const scopeKeys = config.datasetScopeKeys(me._type);
- const scopes = config.getOptionScopes(me.getDataset(), scopeKeys, true);
- me.options = config.createResolver(scopes, me.getContext());
- me._parsing = me.options.parsing;
+ const config = this.chart.config;
+ const scopeKeys = config.datasetScopeKeys(this._type);
+ const scopes = config.getOptionScopes(this.getDataset(), scopeKeys, true);
+ this.options = config.createResolver(scopes, this.getContext());
+ this._parsing = this.options.parsing;
}
/**
* @param {number} count
*/
parse(start, count) {
- const me = this;
- const {_cachedMeta: meta, _data: data} = me;
+ const {_cachedMeta: meta, _data: data} = this;
const {iScale, _stacked} = meta;
const iAxis = iScale.axis;
let prev = start > 0 && meta._parsed[start - 1];
let i, cur, parsed;
- if (me._parsing === false) {
+ if (this._parsing === false) {
meta._parsed = data;
meta._sorted = true;
parsed = data;
} else {
if (isArray(data[start])) {
- parsed = me.parseArrayData(meta, data, start, count);
+ parsed = this.parseArrayData(meta, data, start, count);
} else if (isObject(data[start])) {
- parsed = me.parseObjectData(meta, data, start, count);
+ parsed = this.parseObjectData(meta, data, start, count);
} else {
- parsed = me.parsePrimitiveData(meta, data, start, count);
+ parsed = this.parsePrimitiveData(meta, data, start, count);
}
const isNotInOrderComparedToPrev = () => cur[iAxis] === null || (prev && cur[iAxis] < prev[iAxis]);
}
if (_stacked) {
- updateStacks(me, parsed);
+ updateStacks(this, parsed);
}
}
* @protected
*/
getMinMax(scale, canStack) {
- const me = this;
- const meta = me._cachedMeta;
+ const meta = this._cachedMeta;
const _parsed = meta._parsed;
const sorted = meta._sorted && scale === meta.iScale;
const ilen = _parsed.length;
- const otherScale = me._getOtherScale(scale);
- const stack = canStack && meta._stacked && {keys: getSortedDatasetIndices(me.chart, true), values: null};
+ const otherScale = this._getOtherScale(scale);
+ const stack = canStack && meta._stacked && {keys: getSortedDatasetIndices(this.chart, true), values: null};
const range = {min: Number.POSITIVE_INFINITY, max: Number.NEGATIVE_INFINITY};
const {min: otherMin, max: otherMax} = getUserBounds(otherScale);
let i, value, parsed, otherValue;
if (_skip()) {
continue;
}
- me.updateRangeFromParsed(range, scale, parsed, stack);
+ this.updateRangeFromParsed(range, scale, parsed, stack);
if (sorted) {
// if the data is sorted, we don't need to check further from this end of array
break;
if (_skip()) {
continue;
}
- me.updateRangeFromParsed(range, scale, parsed, stack);
+ this.updateRangeFromParsed(range, scale, parsed, stack);
break;
}
}
* @protected
*/
getLabelAndValue(index) {
- const me = this;
- const meta = me._cachedMeta;
+ const meta = this._cachedMeta;
const iScale = meta.iScale;
const vScale = meta.vScale;
- const parsed = me.getParsed(index);
+ const parsed = this.getParsed(index);
return {
label: iScale ? '' + iScale.getLabelForValue(parsed[iScale.axis]) : '',
value: vScale ? '' + vScale.getLabelForValue(parsed[vScale.axis]) : ''
* @private
*/
_update(mode) {
- const me = this;
- const meta = me._cachedMeta;
- me.configure();
- me._cachedDataOpts = {};
- me.update(mode || 'default');
- meta._clip = toClip(valueOrDefault(me.options.clip, defaultClip(meta.xScale, meta.yScale, me.getMaxOverflow())));
+ const meta = this._cachedMeta;
+ this.configure();
+ this._cachedDataOpts = {};
+ this.update(mode || 'default');
+ meta._clip = toClip(valueOrDefault(this.options.clip, defaultClip(meta.xScale, meta.yScale, this.getMaxOverflow())));
}
/**
update(mode) {} // eslint-disable-line no-unused-vars
draw() {
- const me = this;
- const ctx = me._ctx;
- const chart = me.chart;
- const meta = me._cachedMeta;
+ const ctx = this._ctx;
+ const chart = this.chart;
+ const meta = this._cachedMeta;
const elements = meta.data || [];
const area = chart.chartArea;
const active = [];
- const start = me._drawStart || 0;
- const count = me._drawCount || (elements.length - start);
+ const start = this._drawStart || 0;
+ const count = this._drawCount || (elements.length - start);
let i;
if (meta.dataset) {
* @protected
*/
getContext(index, active, mode) {
- const me = this;
- const dataset = me.getDataset();
+ const dataset = this.getDataset();
let context;
- if (index >= 0 && index < me._cachedMeta.data.length) {
- const element = me._cachedMeta.data[index];
+ if (index >= 0 && index < this._cachedMeta.data.length) {
+ const element = this._cachedMeta.data[index];
context = element.$context ||
- (element.$context = createDataContext(me.getContext(), index, element));
- context.parsed = me.getParsed(index);
+ (element.$context = createDataContext(this.getContext(), index, element));
+ context.parsed = this.getParsed(index);
context.raw = dataset.data[index];
context.index = context.dataIndex = index;
} else {
- context = me.$context ||
- (me.$context = createDatasetContext(me.chart.getContext(), me.index));
+ context = this.$context ||
+ (this.$context = createDatasetContext(this.chart.getContext(), this.index));
context.dataset = dataset;
- context.index = context.datasetIndex = me.index;
+ context.index = context.datasetIndex = this.index;
}
context.active = !!active;
* @private
*/
_resolveElementOptions(elementType, mode = 'default', index) {
- const me = this;
const active = mode === 'active';
- const cache = me._cachedDataOpts;
+ const cache = this._cachedDataOpts;
const cacheKey = elementType + '-' + mode;
const cached = cache[cacheKey];
- const sharing = me.enableOptionSharing && defined(index);
+ const sharing = this.enableOptionSharing && defined(index);
if (cached) {
return cloneIfNotShared(cached, sharing);
}
- const config = me.chart.config;
- const scopeKeys = config.datasetElementScopeKeys(me._type, elementType);
+ const config = this.chart.config;
+ const scopeKeys = config.datasetElementScopeKeys(this._type, elementType);
const prefixes = active ? [`${elementType}Hover`, 'hover', elementType, ''] : [elementType, ''];
- const scopes = config.getOptionScopes(me.getDataset(), scopeKeys);
+ const scopes = config.getOptionScopes(this.getDataset(), scopeKeys);
const names = Object.keys(defaults.elements[elementType]);
// context is provided as a function, and is called only if needed,
// so we don't create a context for each element if not needed.
- const context = () => me.getContext(index, active);
+ const context = () => this.getContext(index, active);
const values = config.resolveNamedOptions(scopes, names, context, prefixes);
if (values.$shared) {
* @private
*/
_resolveAnimations(index, transition, active) {
- const me = this;
- const chart = me.chart;
- const cache = me._cachedDataOpts;
+ const chart = this.chart;
+ const cache = this._cachedDataOpts;
const cacheKey = `animation-${transition}`;
const cached = cache[cacheKey];
if (cached) {
}
let options;
if (chart.options.animation !== false) {
- const config = me.chart.config;
- const scopeKeys = config.datasetAnimationScopeKeys(me._type, transition);
- const scopes = config.getOptionScopes(me.getDataset(), scopeKeys);
- options = config.createResolver(scopes, me.getContext(index, active, transition));
+ const config = this.chart.config;
+ const scopeKeys = config.datasetAnimationScopeKeys(this._type, transition);
+ const scopes = config.getOptionScopes(this.getDataset(), scopeKeys);
+ options = config.createResolver(scopes, this.getContext(index, active, transition));
}
const animations = new Animations(chart, options && options.animations);
if (options && options._cacheable) {
* @private
*/
_resyncElements(resetNewElements) {
- const me = this;
- const data = me._data;
- const elements = me._cachedMeta.data;
+ const data = this._data;
+ const elements = this._cachedMeta.data;
// Apply changes detected through array listeners
- for (const [method, arg1, arg2] of me._syncList) {
- me[method](arg1, arg2);
+ for (const [method, arg1, arg2] of this._syncList) {
+ this[method](arg1, arg2);
}
- me._syncList = [];
+ this._syncList = [];
const numMeta = elements.length;
const numData = data.length;
// This is done because we are not detecting direct assignments:
// chart.data.datasets[0].data[5] = 10;
// chart.data.datasets[0].data[5].y = 10;
- me.parse(0, count);
+ this.parse(0, count);
}
if (numData > numMeta) {
- me._insertElements(numMeta, numData - numMeta, resetNewElements);
+ this._insertElements(numMeta, numData - numMeta, resetNewElements);
} else if (numData < numMeta) {
- me._removeElements(numData, numMeta - numData);
+ this._removeElements(numData, numMeta - numData);
}
}
* @private
*/
_insertElements(start, count, resetNewElements = true) {
- const me = this;
- const meta = me._cachedMeta;
+ const meta = this._cachedMeta;
const data = meta.data;
const end = start + count;
let i;
move(data);
for (i = start; i < end; ++i) {
- data[i] = new me.dataElementType();
+ data[i] = new this.dataElementType();
}
- if (me._parsing) {
+ if (this._parsing) {
move(meta._parsed);
}
- me.parse(start, count);
+ this.parse(start, count);
if (resetNewElements) {
- me.updateElements(data, start, count, 'reset');
+ this.updateElements(data, start, count, 'reset');
}
}
* @private
*/
_removeElements(start, count) {
- const me = this;
- const meta = me._cachedMeta;
- if (me._parsing) {
+ const meta = this._cachedMeta;
+ if (this._parsing) {
const removed = meta._parsed.splice(start, count);
if (meta._stacked) {
clearStacks(meta, removed);
* @return {object}
*/
getProps(props, final) {
- const me = this;
const anims = this.$animations;
if (!final || !anims) {
// let's not create an object, if not needed
- return me;
+ return this;
}
const ret = {};
props.forEach(prop => {
- ret[prop] = anims[prop] && anims[prop].active() ? anims[prop]._to : me[prop];
+ ret[prop] = anims[prop] && anims[prop].active() ? anims[prop]._to : this[prop];
});
return ret;
}
* @returns {boolean} false if any of the plugins return false, else returns true.
*/
notify(chart, hook, args, filter) {
- const me = this;
-
if (hook === 'beforeInit') {
- me._init = me._createDescriptors(chart, true);
- me._notify(me._init, chart, 'install');
+ this._init = this._createDescriptors(chart, true);
+ this._notify(this._init, chart, 'install');
}
- const descriptors = filter ? me._descriptors(chart).filter(filter) : me._descriptors(chart);
- const result = me._notify(descriptors, chart, hook, args);
+ const descriptors = filter ? this._descriptors(chart).filter(filter) : this._descriptors(chart);
+ const result = this._notify(descriptors, chart, hook, args);
if (hook === 'destroy') {
- me._notify(descriptors, chart, 'stop');
- me._notify(me._init, chart, 'uninstall');
+ this._notify(descriptors, chart, 'stop');
+ this._notify(this._init, chart, 'uninstall');
}
return result;
}
* @private
*/
_each(method, args, typedRegistry) {
- const me = this;
[...args].forEach(arg => {
- const reg = typedRegistry || me._getRegistryForType(arg);
- if (typedRegistry || reg.isForType(arg) || (reg === me.plugins && arg.id)) {
- me._exec(method, reg, arg);
+ const reg = typedRegistry || this._getRegistryForType(arg);
+ if (typedRegistry || reg.isForType(arg) || (reg === this.plugins && arg.id)) {
+ this._exec(method, reg, arg);
} else {
// Handle loopable args
// Use case:
// import * as treemap from 'chartjs-chart-treemap';
// Chart.register(treemap);
- const itemReg = typedRegistry || me._getRegistryForType(item);
- me._exec(method, itemReg, item);
+ const itemReg = typedRegistry || this._getRegistryForType(item);
+ this._exec(method, itemReg, item);
});
}
});
* @since 3.0
*/
init(options) {
- const me = this;
- me.options = options.setContext(me.getContext());
+ this.options = options.setContext(this.getContext());
- me.axis = options.axis;
+ this.axis = options.axis;
// parse min/max value, so we can properly determine min/max for other scales
- me._userMin = me.parse(options.min);
- me._userMax = me.parse(options.max);
- me._suggestedMin = me.parse(options.suggestedMin);
- me._suggestedMax = me.parse(options.suggestedMax);
+ this._userMin = this.parse(options.min);
+ this._userMax = this.parse(options.max);
+ this._suggestedMin = this.parse(options.suggestedMin);
+ this._suggestedMax = this.parse(options.suggestedMax);
}
/**
* @since 3.0
*/
getMinMax(canStack) {
- const me = this;
// eslint-disable-next-line prefer-const
- let {min, max, minDefined, maxDefined} = me.getUserBounds();
+ let {min, max, minDefined, maxDefined} = this.getUserBounds();
let range;
if (minDefined && maxDefined) {
return {min, max};
}
- const metas = me.getMatchingVisibleMetas();
+ const metas = this.getMatchingVisibleMetas();
for (let i = 0, ilen = metas.length; i < ilen; ++i) {
- range = metas[i].controller.getMinMax(me, canStack);
+ range = metas[i].controller.getMinMax(this, canStack);
if (!minDefined) {
min = Math.min(min, range.min);
}
* @private
*/
getPadding() {
- const me = this;
return {
- left: me.paddingLeft || 0,
- top: me.paddingTop || 0,
- right: me.paddingRight || 0,
- bottom: me.paddingBottom || 0
+ left: this.paddingLeft || 0,
+ top: this.paddingTop || 0,
+ right: this.paddingRight || 0,
+ bottom: this.paddingBottom || 0
};
}
* - thickness of scales or legends in another orientation
*/
update(maxWidth, maxHeight, margins) {
- const me = this;
- const tickOpts = me.options.ticks;
+ const tickOpts = this.options.ticks;
const sampleSize = tickOpts.sampleSize;
// Update Lifecycle - Probably don't want to ever extend or overwrite this function ;)
- me.beforeUpdate();
+ this.beforeUpdate();
// Absorb the master measurements
- me.maxWidth = maxWidth;
- me.maxHeight = maxHeight;
- me._margins = margins = Object.assign({
+ this.maxWidth = maxWidth;
+ this.maxHeight = maxHeight;
+ this._margins = margins = Object.assign({
left: 0,
right: 0,
top: 0,
bottom: 0
}, margins);
- me.ticks = null;
- me._labelSizes = null;
- me._gridLineItems = null;
- me._labelItems = null;
+ this.ticks = null;
+ this._labelSizes = null;
+ this._gridLineItems = null;
+ this._labelItems = null;
// Dimensions
- me.beforeSetDimensions();
- me.setDimensions();
- me.afterSetDimensions();
+ this.beforeSetDimensions();
+ this.setDimensions();
+ this.afterSetDimensions();
- me._maxLength = me.isHorizontal()
- ? me.width + margins.left + margins.right
- : me.height + margins.top + margins.bottom;
+ this._maxLength = this.isHorizontal()
+ ? this.width + margins.left + margins.right
+ : this.height + margins.top + margins.bottom;
// Data min/max
- if (!me._dataLimitsCached) {
- me.beforeDataLimits();
- me.determineDataLimits();
- me.afterDataLimits();
- me._range = _addGrace(me, me.options.grace);
- me._dataLimitsCached = true;
+ if (!this._dataLimitsCached) {
+ this.beforeDataLimits();
+ this.determineDataLimits();
+ this.afterDataLimits();
+ this._range = _addGrace(this, this.options.grace);
+ this._dataLimitsCached = true;
}
- me.beforeBuildTicks();
+ this.beforeBuildTicks();
- me.ticks = me.buildTicks() || [];
+ this.ticks = this.buildTicks() || [];
// Allow modification of ticks in callback.
- me.afterBuildTicks();
+ this.afterBuildTicks();
// Compute tick rotation and fit using a sampled subset of labels
// We generally don't need to compute the size of every single label for determining scale size
- const samplingEnabled = sampleSize < me.ticks.length;
- me._convertTicksToLabels(samplingEnabled ? sample(me.ticks, sampleSize) : me.ticks);
+ const samplingEnabled = sampleSize < this.ticks.length;
+ this._convertTicksToLabels(samplingEnabled ? sample(this.ticks, sampleSize) : this.ticks);
// configure is called twice, once here, once from core.controller.updateLayout.
// Here we haven't been positioned yet, but dimensions are correct.
// Variables set in configure are needed for calculateLabelRotation, and
// it's ok that coordinates are not correct there, only dimensions matter.
- me.configure();
+ this.configure();
// Tick Rotation
- me.beforeCalculateLabelRotation();
- me.calculateLabelRotation(); // Preconditions: number of ticks and sizes of largest labels must be calculated beforehand
- me.afterCalculateLabelRotation();
+ this.beforeCalculateLabelRotation();
+ this.calculateLabelRotation(); // Preconditions: number of ticks and sizes of largest labels must be calculated beforehand
+ this.afterCalculateLabelRotation();
// Auto-skip
if (tickOpts.display && (tickOpts.autoSkip || tickOpts.source === 'auto')) {
- me.ticks = autoSkip(me, me.ticks);
- me._labelSizes = null;
+ this.ticks = autoSkip(this, this.ticks);
+ this._labelSizes = null;
}
if (samplingEnabled) {
// Generate labels using all non-skipped ticks
- me._convertTicksToLabels(me.ticks);
+ this._convertTicksToLabels(this.ticks);
}
- me.beforeFit();
- me.fit(); // Preconditions: label rotation and label sizes must be calculated beforehand
- me.afterFit();
+ this.beforeFit();
+ this.fit(); // Preconditions: label rotation and label sizes must be calculated beforehand
+ this.afterFit();
// IMPORTANT: after this point, we consider that `this.ticks` will NEVER change!
- me.afterUpdate();
+ this.afterUpdate();
}
/**
* @protected
*/
configure() {
- const me = this;
- let reversePixels = me.options.reverse;
+ let reversePixels = this.options.reverse;
let startPixel, endPixel;
- if (me.isHorizontal()) {
- startPixel = me.left;
- endPixel = me.right;
+ if (this.isHorizontal()) {
+ startPixel = this.left;
+ endPixel = this.right;
} else {
- startPixel = me.top;
- endPixel = me.bottom;
+ startPixel = this.top;
+ endPixel = this.bottom;
// by default vertical scales are from bottom to top, so pixels are reversed
reversePixels = !reversePixels;
}
- me._startPixel = startPixel;
- me._endPixel = endPixel;
- me._reversePixels = reversePixels;
- me._length = endPixel - startPixel;
- me._alignToPixels = me.options.alignToPixels;
+ this._startPixel = startPixel;
+ this._endPixel = endPixel;
+ this._reversePixels = reversePixels;
+ this._length = endPixel - startPixel;
+ this._alignToPixels = this.options.alignToPixels;
}
afterUpdate() {
call(this.options.beforeSetDimensions, [this]);
}
setDimensions() {
- const me = this;
// Set the unconstrained dimension before label rotation
- if (me.isHorizontal()) {
+ if (this.isHorizontal()) {
// Reset position before calculating rotation
- me.width = me.maxWidth;
- me.left = 0;
- me.right = me.width;
+ this.width = this.maxWidth;
+ this.left = 0;
+ this.right = this.width;
} else {
- me.height = me.maxHeight;
+ this.height = this.maxHeight;
// Reset position before calculating rotation
- me.top = 0;
- me.bottom = me.height;
+ this.top = 0;
+ this.bottom = this.height;
}
// Reset padding
- me.paddingLeft = 0;
- me.paddingTop = 0;
- me.paddingRight = 0;
- me.paddingBottom = 0;
+ this.paddingLeft = 0;
+ this.paddingTop = 0;
+ this.paddingRight = 0;
+ this.paddingBottom = 0;
}
afterSetDimensions() {
call(this.options.afterSetDimensions, [this]);
}
_callHooks(name) {
- const me = this;
- me.chart.notifyPlugins(name, me.getContext());
- call(me.options[name], [me]);
+ this.chart.notifyPlugins(name, this.getContext());
+ call(this.options[name], [this]);
}
// Data limits
* @param {Tick[]} ticks
*/
generateTickLabels(ticks) {
- const me = this;
- const tickOpts = me.options.ticks;
+ const tickOpts = this.options.ticks;
let i, ilen, tick;
for (i = 0, ilen = ticks.length; i < ilen; i++) {
tick = ticks[i];
- tick.label = call(tickOpts.callback, [tick.value, i, ticks], me);
+ tick.label = call(tickOpts.callback, [tick.value, i, ticks], this);
}
}
afterTickToLabelConversion() {
call(this.options.beforeCalculateLabelRotation, [this]);
}
calculateLabelRotation() {
- const me = this;
- const options = me.options;
+ const options = this.options;
const tickOpts = options.ticks;
- const numTicks = me.ticks.length;
+ const numTicks = this.ticks.length;
const minRotation = tickOpts.minRotation || 0;
const maxRotation = tickOpts.maxRotation;
let labelRotation = minRotation;
let tickWidth, maxHeight, maxLabelDiagonal;
- if (!me._isVisible() || !tickOpts.display || minRotation >= maxRotation || numTicks <= 1 || !me.isHorizontal()) {
- me.labelRotation = minRotation;
+ if (!this._isVisible() || !tickOpts.display || minRotation >= maxRotation || numTicks <= 1 || !this.isHorizontal()) {
+ this.labelRotation = minRotation;
return;
}
- const labelSizes = me._getLabelSizes();
+ const labelSizes = this._getLabelSizes();
const maxLabelWidth = labelSizes.widest.width;
const maxLabelHeight = labelSizes.highest.height;
// Estimate the width of each grid based on the canvas width, the maximum
// label width and the number of tick intervals
- const maxWidth = _limitValue(me.chart.width - maxLabelWidth, 0, me.maxWidth);
- tickWidth = options.offset ? me.maxWidth / numTicks : maxWidth / (numTicks - 1);
+ const maxWidth = _limitValue(this.chart.width - maxLabelWidth, 0, this.maxWidth);
+ tickWidth = options.offset ? this.maxWidth / numTicks : maxWidth / (numTicks - 1);
// Allow 3 pixels x2 padding either side for label readability
if (maxLabelWidth + 6 > tickWidth) {
tickWidth = maxWidth / (numTicks - (options.offset ? 0.5 : 1));
- maxHeight = me.maxHeight - getTickMarkLength(options.grid)
- - tickOpts.padding - getTitleHeight(options.title, me.chart.options.font);
+ maxHeight = this.maxHeight - getTickMarkLength(options.grid)
+ - tickOpts.padding - getTitleHeight(options.title, this.chart.options.font);
maxLabelDiagonal = Math.sqrt(maxLabelWidth * maxLabelWidth + maxLabelHeight * maxLabelHeight);
labelRotation = toDegrees(Math.min(
Math.asin(_limitValue((labelSizes.highest.height + 6) / tickWidth, -1, 1)),
labelRotation = Math.max(minRotation, Math.min(maxRotation, labelRotation));
}
- me.labelRotation = labelRotation;
+ this.labelRotation = labelRotation;
}
afterCalculateLabelRotation() {
call(this.options.afterCalculateLabelRotation, [this]);
call(this.options.beforeFit, [this]);
}
fit() {
- const me = this;
// Reset
const minSize = {
width: 0,
height: 0
};
- const {chart, options: {ticks: tickOpts, title: titleOpts, grid: gridOpts}} = me;
- const display = me._isVisible();
- const isHorizontal = me.isHorizontal();
+ const {chart, options: {ticks: tickOpts, title: titleOpts, grid: gridOpts}} = this;
+ const display = this._isVisible();
+ const isHorizontal = this.isHorizontal();
if (display) {
const titleHeight = getTitleHeight(titleOpts, chart.options.font);
if (isHorizontal) {
- minSize.width = me.maxWidth;
+ minSize.width = this.maxWidth;
minSize.height = getTickMarkLength(gridOpts) + titleHeight;
} else {
- minSize.height = me.maxHeight; // fill all the height
+ minSize.height = this.maxHeight; // fill all the height
minSize.width = getTickMarkLength(gridOpts) + titleHeight;
}
// Don't bother fitting the ticks if we are not showing the labels
- if (tickOpts.display && me.ticks.length) {
- const {first, last, widest, highest} = me._getLabelSizes();
+ if (tickOpts.display && this.ticks.length) {
+ const {first, last, widest, highest} = this._getLabelSizes();
const tickPadding = tickOpts.padding * 2;
- const angleRadians = toRadians(me.labelRotation);
+ const angleRadians = toRadians(this.labelRotation);
const cos = Math.cos(angleRadians);
const sin = Math.sin(angleRadians);
if (isHorizontal) {
// A horizontal axis is more constrained by the height.
const labelHeight = tickOpts.mirror ? 0 : sin * widest.width + cos * highest.height;
- minSize.height = Math.min(me.maxHeight, minSize.height + labelHeight + tickPadding);
+ minSize.height = Math.min(this.maxHeight, minSize.height + labelHeight + tickPadding);
} else {
// A vertical axis is more constrained by the width. Labels are the
// dominant factor here, so get that length first and account for padding
const labelWidth = tickOpts.mirror ? 0 : cos * widest.width + sin * highest.height;
- minSize.width = Math.min(me.maxWidth, minSize.width + labelWidth + tickPadding);
+ minSize.width = Math.min(this.maxWidth, minSize.width + labelWidth + tickPadding);
}
- me._calculatePadding(first, last, sin, cos);
+ this._calculatePadding(first, last, sin, cos);
}
}
- me._handleMargins();
+ this._handleMargins();
if (isHorizontal) {
- me.width = me._length = chart.width - me._margins.left - me._margins.right;
- me.height = minSize.height;
+ this.width = this._length = chart.width - this._margins.left - this._margins.right;
+ this.height = minSize.height;
} else {
- me.width = minSize.width;
- me.height = me._length = chart.height - me._margins.top - me._margins.bottom;
+ this.width = minSize.width;
+ this.height = this._length = chart.height - this._margins.top - this._margins.bottom;
}
}
_calculatePadding(first, last, sin, cos) {
- const me = this;
- const {ticks: {align, padding}, position} = me.options;
- const isRotated = me.labelRotation !== 0;
- const labelsBelowTicks = position !== 'top' && me.axis === 'x';
-
- if (me.isHorizontal()) {
- const offsetLeft = me.getPixelForTick(0) - me.left;
- const offsetRight = me.right - me.getPixelForTick(me.ticks.length - 1);
+ const {ticks: {align, padding}, position} = this.options;
+ const isRotated = this.labelRotation !== 0;
+ const labelsBelowTicks = position !== 'top' && this.axis === 'x';
+
+ if (this.isHorizontal()) {
+ const offsetLeft = this.getPixelForTick(0) - this.left;
+ const offsetRight = this.right - this.getPixelForTick(this.ticks.length - 1);
let paddingLeft = 0;
let paddingRight = 0;
}
// Adjust padding taking into account changes in offsets
- me.paddingLeft = Math.max((paddingLeft - offsetLeft + padding) * me.width / (me.width - offsetLeft), 0);
- me.paddingRight = Math.max((paddingRight - offsetRight + padding) * me.width / (me.width - offsetRight), 0);
+ this.paddingLeft = Math.max((paddingLeft - offsetLeft + padding) * this.width / (this.width - offsetLeft), 0);
+ this.paddingRight = Math.max((paddingRight - offsetRight + padding) * this.width / (this.width - offsetRight), 0);
} else {
let paddingTop = last.height / 2;
let paddingBottom = first.height / 2;
paddingBottom = 0;
}
- me.paddingTop = paddingTop + padding;
- me.paddingBottom = paddingBottom + padding;
+ this.paddingTop = paddingTop + padding;
+ this.paddingBottom = paddingBottom + padding;
}
}
* @private
*/
_handleMargins() {
- const me = this;
- if (me._margins) {
- me._margins.left = Math.max(me.paddingLeft, me._margins.left);
- me._margins.top = Math.max(me.paddingTop, me._margins.top);
- me._margins.right = Math.max(me.paddingRight, me._margins.right);
- me._margins.bottom = Math.max(me.paddingBottom, me._margins.bottom);
+ if (this._margins) {
+ this._margins.left = Math.max(this.paddingLeft, this._margins.left);
+ this._margins.top = Math.max(this.paddingTop, this._margins.top);
+ this._margins.right = Math.max(this.paddingRight, this._margins.right);
+ this._margins.bottom = Math.max(this.paddingBottom, this._margins.bottom);
}
}
* @private
*/
_convertTicksToLabels(ticks) {
- const me = this;
-
- me.beforeTickToLabelConversion();
+ this.beforeTickToLabelConversion();
- me.generateTickLabels(ticks);
+ this.generateTickLabels(ticks);
// Ticks should be skipped when callback returns null or undef, so lets remove those.
let i, ilen;
}
}
- me.afterTickToLabelConversion();
+ this.afterTickToLabelConversion();
}
/**
* @private
*/
_getLabelSizes() {
- const me = this;
- let labelSizes = me._labelSizes;
+ let labelSizes = this._labelSizes;
if (!labelSizes) {
- const sampleSize = me.options.ticks.sampleSize;
- let ticks = me.ticks;
+ const sampleSize = this.options.ticks.sampleSize;
+ let ticks = this.ticks;
if (sampleSize < ticks.length) {
ticks = sample(ticks, sampleSize);
}
- me._labelSizes = labelSizes = me._computeLabelSizes(ticks, ticks.length);
+ this._labelSizes = labelSizes = this._computeLabelSizes(ticks, ticks.length);
}
return labelSizes;
* @return {number}
*/
getPixelForDecimal(decimal) {
- const me = this;
-
- if (me._reversePixels) {
+ if (this._reversePixels) {
decimal = 1 - decimal;
}
- const pixel = me._startPixel + decimal * me._length;
- return _int16Range(me._alignToPixels ? _alignPixel(me.chart, pixel, 0) : pixel);
+ const pixel = this._startPixel + decimal * this._length;
+ return _int16Range(this._alignToPixels ? _alignPixel(this.chart, pixel, 0) : pixel);
}
/**
* @protected
*/
getContext(index) {
- const me = this;
- const ticks = me.ticks || [];
+ const ticks = this.ticks || [];
if (index >= 0 && index < ticks.length) {
const tick = ticks[index];
return tick.$context ||
- (tick.$context = createTickContext(me.getContext(), index, tick));
+ (tick.$context = createTickContext(this.getContext(), index, tick));
}
- return me.$context ||
- (me.$context = createScaleContext(me.chart.getContext(), me));
+ return this.$context ||
+ (this.$context = createScaleContext(this.chart.getContext(), this));
}
/**
* @private
*/
_tickSize() {
- const me = this;
- const optionTicks = me.options.ticks;
+ const optionTicks = this.options.ticks;
// Calculate space needed by label in axis direction.
- const rot = toRadians(me.labelRotation);
+ const rot = toRadians(this.labelRotation);
const cos = Math.abs(Math.cos(rot));
const sin = Math.abs(Math.sin(rot));
- const labelSizes = me._getLabelSizes();
+ const labelSizes = this._getLabelSizes();
const padding = optionTicks.autoSkipPadding || 0;
const w = labelSizes ? labelSizes.widest.width + padding : 0;
const h = labelSizes ? labelSizes.highest.height + padding : 0;
// Calculate space needed for 1 tick in axis direction.
- return me.isHorizontal()
+ return this.isHorizontal()
? h * cos > w * sin ? w / cos : h / sin
: h * sin < w * cos ? h / cos : w / sin;
}
* @private
*/
_computeGridLineItems(chartArea) {
- const me = this;
- const axis = me.axis;
- const chart = me.chart;
- const options = me.options;
+ const axis = this.axis;
+ const chart = this.chart;
+ const options = this.options;
const {grid, position} = options;
const offset = grid.offset;
- const isHorizontal = me.isHorizontal();
- const ticks = me.ticks;
+ const isHorizontal = this.isHorizontal();
+ const ticks = this.ticks;
const ticksLength = ticks.length + (offset ? 1 : 0);
const tl = getTickMarkLength(grid);
const items = [];
- const borderOpts = grid.setContext(me.getContext());
+ const borderOpts = grid.setContext(this.getContext());
const axisWidth = borderOpts.drawBorder ? borderOpts.borderWidth : 0;
const axisHalfWidth = axisWidth / 2;
const alignBorderValue = function(pixel) {
let tx1, ty1, tx2, ty2, x1, y1, x2, y2;
if (position === 'top') {
- borderValue = alignBorderValue(me.bottom);
- ty1 = me.bottom - tl;
+ borderValue = alignBorderValue(this.bottom);
+ ty1 = this.bottom - tl;
ty2 = borderValue - axisHalfWidth;
y1 = alignBorderValue(chartArea.top) + axisHalfWidth;
y2 = chartArea.bottom;
} else if (position === 'bottom') {
- borderValue = alignBorderValue(me.top);
+ borderValue = alignBorderValue(this.top);
y1 = chartArea.top;
y2 = alignBorderValue(chartArea.bottom) - axisHalfWidth;
ty1 = borderValue + axisHalfWidth;
- ty2 = me.top + tl;
+ ty2 = this.top + tl;
} else if (position === 'left') {
- borderValue = alignBorderValue(me.right);
- tx1 = me.right - tl;
+ borderValue = alignBorderValue(this.right);
+ tx1 = this.right - tl;
tx2 = borderValue - axisHalfWidth;
x1 = alignBorderValue(chartArea.left) + axisHalfWidth;
x2 = chartArea.right;
} else if (position === 'right') {
- borderValue = alignBorderValue(me.left);
+ borderValue = alignBorderValue(this.left);
x1 = chartArea.left;
x2 = alignBorderValue(chartArea.right) - axisHalfWidth;
tx1 = borderValue + axisHalfWidth;
- tx2 = me.left + tl;
+ tx2 = this.left + tl;
} else if (axis === 'x') {
if (position === 'center') {
borderValue = alignBorderValue((chartArea.top + chartArea.bottom) / 2 + 0.5);
} else if (isObject(position)) {
const positionAxisID = Object.keys(position)[0];
const value = position[positionAxisID];
- borderValue = alignBorderValue(me.chart.scales[positionAxisID].getPixelForValue(value));
+ borderValue = alignBorderValue(this.chart.scales[positionAxisID].getPixelForValue(value));
}
y1 = chartArea.top;
} else if (isObject(position)) {
const positionAxisID = Object.keys(position)[0];
const value = position[positionAxisID];
- borderValue = alignBorderValue(me.chart.scales[positionAxisID].getPixelForValue(value));
+ borderValue = alignBorderValue(this.chart.scales[positionAxisID].getPixelForValue(value));
}
tx1 = borderValue - axisHalfWidth;
const limit = valueOrDefault(options.ticks.maxTicksLimit, ticksLength);
const step = Math.max(1, Math.ceil(ticksLength / limit));
for (i = 0; i < ticksLength; i += step) {
- const optsAtIndex = grid.setContext(me.getContext(i));
+ const optsAtIndex = grid.setContext(this.getContext(i));
const lineWidth = optsAtIndex.lineWidth;
const lineColor = optsAtIndex.color;
const tickBorderDash = optsAtIndex.tickBorderDash || [];
const tickBorderDashOffset = optsAtIndex.tickBorderDashOffset;
- lineValue = getPixelForGridLine(me, i, offset);
+ lineValue = getPixelForGridLine(this, i, offset);
// Skip if the pixel is out of the range
if (lineValue === undefined) {
});
}
- me._ticksLength = ticksLength;
- me._borderValue = borderValue;
+ this._ticksLength = ticksLength;
+ this._borderValue = borderValue;
return items;
}
* @private
*/
_computeLabelItems(chartArea) {
- const me = this;
- const axis = me.axis;
- const options = me.options;
+ const axis = this.axis;
+ const options = this.options;
const {position, ticks: optionTicks} = options;
- const isHorizontal = me.isHorizontal();
- const ticks = me.ticks;
+ const isHorizontal = this.isHorizontal();
+ const ticks = this.ticks;
const {align, crossAlign, padding, mirror} = optionTicks;
const tl = getTickMarkLength(options.grid);
const tickAndPadding = tl + padding;
const hTickAndPadding = mirror ? -padding : tickAndPadding;
- const rotation = -toRadians(me.labelRotation);
+ const rotation = -toRadians(this.labelRotation);
const items = [];
let i, ilen, tick, label, x, y, textAlign, pixel, font, lineHeight, lineCount, textOffset;
let textBaseline = 'middle';
if (position === 'top') {
- y = me.bottom - hTickAndPadding;
- textAlign = me._getXAxisLabelAlignment();
+ y = this.bottom - hTickAndPadding;
+ textAlign = this._getXAxisLabelAlignment();
} else if (position === 'bottom') {
- y = me.top + hTickAndPadding;
- textAlign = me._getXAxisLabelAlignment();
+ y = this.top + hTickAndPadding;
+ textAlign = this._getXAxisLabelAlignment();
} else if (position === 'left') {
- const ret = me._getYAxisLabelAlignment(tl);
+ const ret = this._getYAxisLabelAlignment(tl);
textAlign = ret.textAlign;
x = ret.x;
} else if (position === 'right') {
- const ret = me._getYAxisLabelAlignment(tl);
+ const ret = this._getYAxisLabelAlignment(tl);
textAlign = ret.textAlign;
x = ret.x;
} else if (axis === 'x') {
} else if (isObject(position)) {
const positionAxisID = Object.keys(position)[0];
const value = position[positionAxisID];
- y = me.chart.scales[positionAxisID].getPixelForValue(value) + tickAndPadding;
+ y = this.chart.scales[positionAxisID].getPixelForValue(value) + tickAndPadding;
}
- textAlign = me._getXAxisLabelAlignment();
+ textAlign = this._getXAxisLabelAlignment();
} else if (axis === 'y') {
if (position === 'center') {
x = ((chartArea.left + chartArea.right) / 2) - tickAndPadding;
} else if (isObject(position)) {
const positionAxisID = Object.keys(position)[0];
const value = position[positionAxisID];
- x = me.chart.scales[positionAxisID].getPixelForValue(value);
+ x = this.chart.scales[positionAxisID].getPixelForValue(value);
}
- textAlign = me._getYAxisLabelAlignment(tl).textAlign;
+ textAlign = this._getYAxisLabelAlignment(tl).textAlign;
}
if (axis === 'y') {
}
}
- const labelSizes = me._getLabelSizes();
+ const labelSizes = this._getLabelSizes();
for (i = 0, ilen = ticks.length; i < ilen; ++i) {
tick = ticks[i];
label = tick.label;
- const optsAtIndex = optionTicks.setContext(me.getContext(i));
- pixel = me.getPixelForTick(i) + optionTicks.labelOffset;
- font = me._resolveTickFontOptions(i);
+ const optsAtIndex = optionTicks.setContext(this.getContext(i));
+ pixel = this.getPixelForTick(i) + optionTicks.labelOffset;
+ font = this._resolveTickFontOptions(i);
lineHeight = font.lineHeight;
lineCount = isArray(label) ? label.length : 1;
const halfCount = lineCount / 2;
}
_getXAxisLabelAlignment() {
- const me = this;
- const {position, ticks} = me.options;
- const rotation = -toRadians(me.labelRotation);
+ const {position, ticks} = this.options;
+ const rotation = -toRadians(this.labelRotation);
if (rotation) {
return position === 'top' ? 'left' : 'right';
}
_getYAxisLabelAlignment(tl) {
- const me = this;
- const {position, ticks: {crossAlign, mirror, padding}} = me.options;
- const labelSizes = me._getLabelSizes();
+ const {position, ticks: {crossAlign, mirror, padding}} = this.options;
+ const labelSizes = this._getLabelSizes();
const tickAndPadding = tl + padding;
const widest = labelSizes.widest.width;
if (position === 'left') {
if (mirror) {
- x = me.right + padding;
+ x = this.right + padding;
if (crossAlign === 'near') {
textAlign = 'left';
x += widest;
}
} else {
- x = me.right - tickAndPadding;
+ x = this.right - tickAndPadding;
if (crossAlign === 'near') {
textAlign = 'right';
x -= (widest / 2);
} else {
textAlign = 'left';
- x = me.left;
+ x = this.left;
}
}
} else if (position === 'right') {
if (mirror) {
- x = me.left + padding;
+ x = this.left + padding;
if (crossAlign === 'near') {
textAlign = 'right';
x -= widest;
}
} else {
- x = me.left + tickAndPadding;
+ x = this.left + tickAndPadding;
if (crossAlign === 'near') {
textAlign = 'left';
x += widest / 2;
} else {
textAlign = 'right';
- x = me.right;
+ x = this.right;
}
}
} else {
* @private
*/
_computeLabelArea() {
- const me = this;
-
- if (me.options.ticks.mirror) {
+ if (this.options.ticks.mirror) {
return;
}
- const chart = me.chart;
- const position = me.options.position;
+ const chart = this.chart;
+ const position = this.options.position;
if (position === 'left' || position === 'right') {
- return {top: 0, left: me.left, bottom: chart.height, right: me.right};
+ return {top: 0, left: this.left, bottom: chart.height, right: this.right};
} if (position === 'top' || position === 'bottom') {
- return {top: me.top, left: 0, bottom: me.bottom, right: chart.width};
+ return {top: this.top, left: 0, bottom: this.bottom, right: chart.width};
}
}
}
getLineWidthForValue(value) {
- const me = this;
- const grid = me.options.grid;
- if (!me._isVisible() || !grid.display) {
+ const grid = this.options.grid;
+ if (!this._isVisible() || !grid.display) {
return 0;
}
- const ticks = me.ticks;
+ const ticks = this.ticks;
const index = ticks.findIndex(t => t.value === value);
if (index >= 0) {
- const opts = grid.setContext(me.getContext(index));
+ const opts = grid.setContext(this.getContext(index));
return opts.lineWidth;
}
return 0;
* @protected
*/
drawGrid(chartArea) {
- const me = this;
- const grid = me.options.grid;
- const ctx = me.ctx;
- const items = me._gridLineItems || (me._gridLineItems = me._computeGridLineItems(chartArea));
+ const grid = this.options.grid;
+ const ctx = this.ctx;
+ const items = this._gridLineItems || (this._gridLineItems = this._computeGridLineItems(chartArea));
let i, ilen;
const drawLine = (p1, p2, style) => {
* @protected
*/
drawBorder() {
- const me = this;
- const {chart, ctx, options: {grid}} = me;
- const borderOpts = grid.setContext(me.getContext());
+ const {chart, ctx, options: {grid}} = this;
+ const borderOpts = grid.setContext(this.getContext());
const axisWidth = grid.drawBorder ? borderOpts.borderWidth : 0;
if (!axisWidth) {
return;
}
- const lastLineWidth = grid.setContext(me.getContext(0)).lineWidth;
- const borderValue = me._borderValue;
+ const lastLineWidth = grid.setContext(this.getContext(0)).lineWidth;
+ const borderValue = this._borderValue;
let x1, x2, y1, y2;
- if (me.isHorizontal()) {
- x1 = _alignPixel(chart, me.left, axisWidth) - axisWidth / 2;
- x2 = _alignPixel(chart, me.right, lastLineWidth) + lastLineWidth / 2;
+ if (this.isHorizontal()) {
+ x1 = _alignPixel(chart, this.left, axisWidth) - axisWidth / 2;
+ x2 = _alignPixel(chart, this.right, lastLineWidth) + lastLineWidth / 2;
y1 = y2 = borderValue;
} else {
- y1 = _alignPixel(chart, me.top, axisWidth) - axisWidth / 2;
- y2 = _alignPixel(chart, me.bottom, lastLineWidth) + lastLineWidth / 2;
+ y1 = _alignPixel(chart, this.top, axisWidth) - axisWidth / 2;
+ y2 = _alignPixel(chart, this.bottom, lastLineWidth) + lastLineWidth / 2;
x1 = x2 = borderValue;
}
ctx.save();
* @protected
*/
drawLabels(chartArea) {
- const me = this;
- const optionTicks = me.options.ticks;
+ const optionTicks = this.options.ticks;
if (!optionTicks.display) {
return;
}
- const ctx = me.ctx;
+ const ctx = this.ctx;
- const area = me._computeLabelArea();
+ const area = this._computeLabelArea();
if (area) {
clipArea(ctx, area);
}
- const items = me._labelItems || (me._labelItems = me._computeLabelItems(chartArea));
+ const items = this._labelItems || (this._labelItems = this._computeLabelItems(chartArea));
let i, ilen;
for (i = 0, ilen = items.length; i < ilen; ++i) {
}
draw(chartArea) {
- const me = this;
-
- if (!me._isVisible()) {
+ if (!this._isVisible()) {
return;
}
- me.drawBackground();
- me.drawGrid(chartArea);
- me.drawBorder();
- me.drawTitle();
- me.drawLabels(chartArea);
+ this.drawBackground();
+ this.drawGrid(chartArea);
+ this.drawBorder();
+ this.drawTitle();
+ this.drawLabels(chartArea);
}
/**
* @private
*/
_layers() {
- const me = this;
- const opts = me.options;
+ const opts = this.options;
const tz = opts.ticks && opts.ticks.z || 0;
const gz = valueOrDefault(opts.grid && opts.grid.z, -1);
- if (!me._isVisible() || me.draw !== Scale.prototype.draw) {
+ if (!this._isVisible() || this.draw !== Scale.prototype.draw) {
// backward compatibility: draw has been overridden by custom scale
return [{
z: tz,
- draw(chartArea) {
- me.draw(chartArea);
+ draw: (chartArea) => {
+ this.draw(chartArea);
}
}];
}
return [{
z: gz,
- draw(chartArea) {
- me.drawBackground();
- me.drawGrid(chartArea);
- me.drawTitle();
+ draw: (chartArea) => {
+ this.drawBackground();
+ this.drawGrid(chartArea);
+ this.drawTitle();
}
}, {
z: gz + 1, // TODO, v4 move border options to its own object and add z
- draw() {
- me.drawBorder();
+ draw: () => {
+ this.drawBorder();
}
}, {
z: tz,
- draw(chartArea) {
- me.drawLabels(chartArea);
+ draw: (chartArea) => {
+ this.drawLabels(chartArea);
}
}];
}
* @return {object[]}
*/
getMatchingVisibleMetas(type) {
- const me = this;
- const metas = me.chart.getSortedVisibleDatasetMetas();
- const axisID = me.axis + 'AxisID';
+ const metas = this.chart.getSortedVisibleDatasetMetas();
+ const axisID = this.axis + 'AxisID';
const result = [];
let i, ilen;
for (i = 0, ilen = metas.length; i < ilen; ++i) {
const meta = metas[i];
- if (meta[axisID] === me.id && (!type || meta.type === type)) {
+ if (meta[axisID] === this.id && (!type || meta.type === type)) {
result.push(meta);
}
}
* @protected
*/
_maxDigits() {
- const me = this;
- const fontSize = me._resolveTickFontOptions(0).lineHeight;
- return (me.isHorizontal() ? me.width : me.height) / fontSize;
+ const fontSize = this._resolveTickFontOptions(0).lineHeight;
+ return (this.isHorizontal() ? this.width : this.height) / fontSize;
}
}
* @returns {string} The scope where items defaults were registered to.
*/
register(item) {
- const me = this;
const proto = Object.getPrototypeOf(item);
let parentScope;
if (isIChartComponent(proto)) {
// Make sure the parent is registered and note the scope where its defaults are.
- parentScope = me.register(proto);
+ parentScope = this.register(proto);
}
- const items = me.items;
+ const items = this.items;
const id = item.id;
- const scope = me.scope + '.' + id;
+ const scope = this.scope + '.' + id;
if (!id) {
throw new Error('class does not have id: ' + item);
items[id] = item;
registerDefaults(item, scope, parentScope);
- if (me.override) {
+ if (this.override) {
defaults.override(item.id, item.overrides);
}
}
draw(ctx) {
- const me = this;
- const {options, circumference} = me;
+ const {options, circumference} = this;
const offset = (options.offset || 0) / 2;
const spacing = (options.spacing || 0) / 2;
- me.pixelMargin = (options.borderAlign === 'inner') ? 0.33 : 0;
- me.fullCircles = circumference > TAU ? Math.floor(circumference / TAU) : 0;
+ this.pixelMargin = (options.borderAlign === 'inner') ? 0.33 : 0;
+ this.fullCircles = circumference > TAU ? Math.floor(circumference / TAU) : 0;
- if (circumference === 0 || me.innerRadius < 0 || me.outerRadius < 0) {
+ if (circumference === 0 || this.innerRadius < 0 || this.outerRadius < 0) {
return;
}
let radiusOffset = 0;
if (offset) {
radiusOffset = offset / 2;
- const halfAngle = (me.startAngle + me.endAngle) / 2;
+ const halfAngle = (this.startAngle + this.endAngle) / 2;
ctx.translate(Math.cos(halfAngle) * radiusOffset, Math.sin(halfAngle) * radiusOffset);
- if (me.circumference >= PI) {
+ if (this.circumference >= PI) {
radiusOffset = offset;
}
}
ctx.fillStyle = options.backgroundColor;
ctx.strokeStyle = options.borderColor;
- const endAngle = drawArc(ctx, me, radiusOffset, spacing);
- drawBorder(ctx, me, radiusOffset, spacing, endAngle);
+ const endAngle = drawArc(ctx, this, radiusOffset, spacing);
+ drawBorder(ctx, this, radiusOffset, spacing, endAngle);
ctx.restore();
}
}
updateControlPoints(chartArea, indexAxis) {
- const me = this;
- const options = me.options;
- if ((options.tension || options.cubicInterpolationMode === 'monotone') && !options.stepped && !me._pointsUpdated) {
- const loop = options.spanGaps ? me._loop : me._fullLoop;
- _updateBezierControlPoints(me._points, options, chartArea, loop, indexAxis);
- me._pointsUpdated = true;
+ const options = this.options;
+ if ((options.tension || options.cubicInterpolationMode === 'monotone') && !options.stepped && !this._pointsUpdated) {
+ const loop = options.spanGaps ? this._loop : this._fullLoop;
+ _updateBezierControlPoints(this._points, options, chartArea, loop, indexAxis);
+ this._pointsUpdated = true;
}
}
set points(points) {
- const me = this;
- me._points = points;
- delete me._segments;
- delete me._path;
- me._pointsUpdated = false;
+ this._points = points;
+ delete this._segments;
+ delete this._path;
+ this._pointsUpdated = false;
}
get points() {
* @returns {PointElement|undefined}
*/
interpolate(point, property) {
- const me = this;
- const options = me.options;
+ const options = this.options;
const value = point[property];
- const points = me.points;
- const segments = _boundSegments(me, {property, start: value, end: value});
+ const points = this.points;
+ const segments = _boundSegments(this, {property, start: value, end: value});
if (!segments.length) {
return;
* @returns {undefined|boolean} - true if line is a full loop (path should be closed)
*/
path(ctx, start, count) {
- const me = this;
- const segments = me.segments;
- const segmentMethod = _getSegmentMethod(me);
- let loop = me._loop;
+ const segments = this.segments;
+ const segmentMethod = _getSegmentMethod(this);
+ let loop = this._loop;
start = start || 0;
- count = count || (me.points.length - start);
+ count = count || (this.points.length - start);
for (const segment of segments) {
- loop &= segmentMethod(ctx, me, segment, {start, end: start + count - 1});
+ loop &= segmentMethod(ctx, this, segment, {start, end: start + count - 1});
}
return !!loop;
}
* @param {number} [count]
*/
draw(ctx, chartArea, start, count) {
- const me = this;
- const options = me.options || {};
- const points = me.points || [];
+ const options = this.options || {};
+ const points = this.points || [];
if (points.length && options.borderWidth) {
ctx.save();
- draw(ctx, me, start, count);
+ draw(ctx, this, start, count);
ctx.restore();
}
- if (me.animated) {
+ if (this.animated) {
// When line is animated, the control points and path are not cached.
- me._pointsUpdated = false;
- me._path = undefined;
+ this._pointsUpdated = false;
+ this._path = undefined;
}
}
}
}
draw(ctx, area) {
- const me = this;
- const options = me.options;
+ const options = this.options;
- if (me.skip || options.radius < 0.1 || !_isPointInArea(me, area, me.size(options) / 2)) {
+ if (this.skip || options.radius < 0.1 || !_isPointInArea(this, area, this.size(options) / 2)) {
return;
}
ctx.strokeStyle = options.borderColor;
ctx.lineWidth = options.borderWidth;
ctx.fillStyle = options.backgroundColor;
- drawPoint(ctx, options, me.x, me.y);
+ drawPoint(ctx, options, this.x, this.y);
}
getRange() {
}
update(maxWidth, maxHeight, margins) {
- const me = this;
+ this.maxWidth = maxWidth;
+ this.maxHeight = maxHeight;
+ this._margins = margins;
- me.maxWidth = maxWidth;
- me.maxHeight = maxHeight;
- me._margins = margins;
-
- me.setDimensions();
- me.buildLabels();
- me.fit();
+ this.setDimensions();
+ this.buildLabels();
+ this.fit();
}
setDimensions() {
- const me = this;
-
- if (me.isHorizontal()) {
- me.width = me.maxWidth;
- me.left = me._margins.left;
- me.right = me.width;
+ if (this.isHorizontal()) {
+ this.width = this.maxWidth;
+ this.left = this._margins.left;
+ this.right = this.width;
} else {
- me.height = me.maxHeight;
- me.top = me._margins.top;
- me.bottom = me.height;
+ this.height = this.maxHeight;
+ this.top = this._margins.top;
+ this.bottom = this.height;
}
}
buildLabels() {
- const me = this;
- const labelOpts = me.options.labels || {};
- let legendItems = call(labelOpts.generateLabels, [me.chart], me) || [];
+ const labelOpts = this.options.labels || {};
+ let legendItems = call(labelOpts.generateLabels, [this.chart], this) || [];
if (labelOpts.filter) {
- legendItems = legendItems.filter((item) => labelOpts.filter(item, me.chart.data));
+ legendItems = legendItems.filter((item) => labelOpts.filter(item, this.chart.data));
}
if (labelOpts.sort) {
- legendItems = legendItems.sort((a, b) => labelOpts.sort(a, b, me.chart.data));
+ legendItems = legendItems.sort((a, b) => labelOpts.sort(a, b, this.chart.data));
}
- if (me.options.reverse) {
+ if (this.options.reverse) {
legendItems.reverse();
}
- me.legendItems = legendItems;
+ this.legendItems = legendItems;
}
fit() {
- const me = this;
- const {options, ctx} = me;
+ const {options, ctx} = this;
// The legend may not be displayed for a variety of reasons including
// the fact that the defaults got set to `false`.
// When the legend is not displayed, there are no guarantees that the options
// are correctly formatted so we need to bail out as early as possible.
if (!options.display) {
- me.width = me.height = 0;
+ this.width = this.height = 0;
return;
}
const labelOpts = options.labels;
const labelFont = toFont(labelOpts.font);
const fontSize = labelFont.size;
- const titleHeight = me._computeTitleHeight();
+ const titleHeight = this._computeTitleHeight();
const {boxWidth, itemHeight} = getBoxSize(labelOpts, fontSize);
let width, height;
ctx.font = labelFont.string;
- if (me.isHorizontal()) {
- width = me.maxWidth; // fill all the width
- height = me._fitRows(titleHeight, fontSize, boxWidth, itemHeight) + 10;
+ if (this.isHorizontal()) {
+ width = this.maxWidth; // fill all the width
+ height = this._fitRows(titleHeight, fontSize, boxWidth, itemHeight) + 10;
} else {
- height = me.maxHeight; // fill all the height
- width = me._fitCols(titleHeight, fontSize, boxWidth, itemHeight) + 10;
+ height = this.maxHeight; // fill all the height
+ width = this._fitCols(titleHeight, fontSize, boxWidth, itemHeight) + 10;
}
- me.width = Math.min(width, options.maxWidth || me.maxWidth);
- me.height = Math.min(height, options.maxHeight || me.maxHeight);
+ this.width = Math.min(width, options.maxWidth || this.maxWidth);
+ this.height = Math.min(height, options.maxHeight || this.maxHeight);
}
/**
* @private
*/
_fitRows(titleHeight, fontSize, boxWidth, itemHeight) {
- const me = this;
- const {ctx, maxWidth, options: {labels: {padding}}} = me;
- const hitboxes = me.legendHitBoxes = [];
+ const {ctx, maxWidth, options: {labels: {padding}}} = this;
+ const hitboxes = this.legendHitBoxes = [];
// Width of each line of legend boxes. Labels wrap onto multiple lines when there are too many to fit on one
- const lineWidths = me.lineWidths = [0];
+ const lineWidths = this.lineWidths = [0];
const lineHeight = itemHeight + padding;
let totalHeight = titleHeight;
let row = -1;
let top = -lineHeight;
- me.legendItems.forEach((legendItem, i) => {
+ this.legendItems.forEach((legendItem, i) => {
const itemWidth = boxWidth + (fontSize / 2) + ctx.measureText(legendItem.text).width;
if (i === 0 || lineWidths[lineWidths.length - 1] + itemWidth + 2 * padding > maxWidth) {
}
_fitCols(titleHeight, fontSize, boxWidth, itemHeight) {
- const me = this;
- const {ctx, maxHeight, options: {labels: {padding}}} = me;
- const hitboxes = me.legendHitBoxes = [];
- const columnSizes = me.columnSizes = [];
+ const {ctx, maxHeight, options: {labels: {padding}}} = this;
+ const hitboxes = this.legendHitBoxes = [];
+ const columnSizes = this.columnSizes = [];
const heightLimit = maxHeight - titleHeight;
let totalWidth = padding;
let left = 0;
let col = 0;
- me.legendItems.forEach((legendItem, i) => {
+ this.legendItems.forEach((legendItem, i) => {
const itemWidth = boxWidth + (fontSize / 2) + ctx.measureText(legendItem.text).width;
// If too tall, go to new column
}
adjustHitBoxes() {
- const me = this;
- if (!me.options.display) {
+ if (!this.options.display) {
return;
}
- const titleHeight = me._computeTitleHeight();
- const {legendHitBoxes: hitboxes, options: {align, labels: {padding}, rtl}} = me;
- const rtlHelper = getRtlAdapter(rtl, me.left, me.width);
+ const titleHeight = this._computeTitleHeight();
+ const {legendHitBoxes: hitboxes, options: {align, labels: {padding}, rtl}} = this;
+ const rtlHelper = getRtlAdapter(rtl, this.left, this.width);
if (this.isHorizontal()) {
let row = 0;
- let left = _alignStartEnd(align, me.left + padding, me.right - me.lineWidths[row]);
+ let left = _alignStartEnd(align, this.left + padding, this.right - this.lineWidths[row]);
for (const hitbox of hitboxes) {
if (row !== hitbox.row) {
row = hitbox.row;
- left = _alignStartEnd(align, me.left + padding, me.right - me.lineWidths[row]);
+ left = _alignStartEnd(align, this.left + padding, this.right - this.lineWidths[row]);
}
- hitbox.top += me.top + titleHeight + padding;
+ hitbox.top += this.top + titleHeight + padding;
hitbox.left = rtlHelper.leftForLtr(rtlHelper.x(left), hitbox.width);
left += hitbox.width + padding;
}
} else {
let col = 0;
- let top = _alignStartEnd(align, me.top + titleHeight + padding, me.bottom - me.columnSizes[col].height);
+ let top = _alignStartEnd(align, this.top + titleHeight + padding, this.bottom - this.columnSizes[col].height);
for (const hitbox of hitboxes) {
if (hitbox.col !== col) {
col = hitbox.col;
- top = _alignStartEnd(align, me.top + titleHeight + padding, me.bottom - me.columnSizes[col].height);
+ top = _alignStartEnd(align, this.top + titleHeight + padding, this.bottom - this.columnSizes[col].height);
}
hitbox.top = top;
- hitbox.left += me.left + padding;
+ hitbox.left += this.left + padding;
hitbox.left = rtlHelper.leftForLtr(rtlHelper.x(hitbox.left), hitbox.width);
top += hitbox.height + padding;
}
}
draw() {
- const me = this;
- if (me.options.display) {
- const ctx = me.ctx;
- clipArea(ctx, me);
+ if (this.options.display) {
+ const ctx = this.ctx;
+ clipArea(ctx, this);
- me._draw();
+ this._draw();
unclipArea(ctx);
}
* @private
*/
_draw() {
- const me = this;
- const {options: opts, columnSizes, lineWidths, ctx} = me;
+ const {options: opts, columnSizes, lineWidths, ctx} = this;
const {align, labels: labelOpts} = opts;
const defaultColor = defaults.color;
- const rtlHelper = getRtlAdapter(opts.rtl, me.left, me.width);
+ const rtlHelper = getRtlAdapter(opts.rtl, this.left, this.width);
const labelFont = toFont(labelOpts.font);
const {color: fontColor, padding} = labelOpts;
const fontSize = labelFont.size;
const halfFontSize = fontSize / 2;
let cursor;
- me.drawTitle();
+ this.drawTitle();
// Canvas setup
ctx.textAlign = rtlHelper.textAlign('left');
};
// Horizontal
- const isHorizontal = me.isHorizontal();
+ const isHorizontal = this.isHorizontal();
const titleHeight = this._computeTitleHeight();
if (isHorizontal) {
cursor = {
- x: _alignStartEnd(align, me.left + padding, me.right - lineWidths[0]),
- y: me.top + padding + titleHeight,
+ x: _alignStartEnd(align, this.left + padding, this.right - lineWidths[0]),
+ y: this.top + padding + titleHeight,
line: 0
};
} else {
cursor = {
- x: me.left + padding,
- y: _alignStartEnd(align, me.top + titleHeight + padding, me.bottom - columnSizes[0].height),
+ x: this.left + padding,
+ y: _alignStartEnd(align, this.top + titleHeight + padding, this.bottom - columnSizes[0].height),
line: 0
};
}
- overrideTextDirection(me.ctx, opts.textDirection);
+ overrideTextDirection(this.ctx, opts.textDirection);
const lineHeight = itemHeight + padding;
- me.legendItems.forEach((legendItem, i) => {
+ this.legendItems.forEach((legendItem, i) => {
// TODO: Remove fallbacks at v4
ctx.strokeStyle = legendItem.fontColor || fontColor; // for strikethrough effect
ctx.fillStyle = legendItem.fontColor || fontColor; // render in correct colour
let x = cursor.x;
let y = cursor.y;
- rtlHelper.setWidth(me.width);
+ rtlHelper.setWidth(this.width);
if (isHorizontal) {
- if (i > 0 && x + width + padding > me.right) {
+ if (i > 0 && x + width + padding > this.right) {
y = cursor.y += lineHeight;
cursor.line++;
- x = cursor.x = _alignStartEnd(align, me.left + padding, me.right - lineWidths[cursor.line]);
+ x = cursor.x = _alignStartEnd(align, this.left + padding, this.right - lineWidths[cursor.line]);
}
- } else if (i > 0 && y + lineHeight > me.bottom) {
+ } else if (i > 0 && y + lineHeight > this.bottom) {
x = cursor.x = x + columnSizes[cursor.line].width + padding;
cursor.line++;
- y = cursor.y = _alignStartEnd(align, me.top + titleHeight + padding, me.bottom - columnSizes[cursor.line].height);
+ y = cursor.y = _alignStartEnd(align, this.top + titleHeight + padding, this.bottom - columnSizes[cursor.line].height);
}
const realX = rtlHelper.x(x);
drawLegendBox(realX, y, legendItem);
- x = _textX(textAlign, x + boxWidth + halfFontSize, isHorizontal ? x + width : me.right, opts.rtl);
+ x = _textX(textAlign, x + boxWidth + halfFontSize, isHorizontal ? x + width : this.right, opts.rtl);
// Fill the actual label
fillText(rtlHelper.x(x), y, legendItem);
}
});
- restoreTextDirection(me.ctx, opts.textDirection);
+ restoreTextDirection(this.ctx, opts.textDirection);
}
/**
* @protected
*/
drawTitle() {
- const me = this;
- const opts = me.options;
+ const opts = this.options;
const titleOpts = opts.title;
const titleFont = toFont(titleOpts.font);
const titlePadding = toPadding(titleOpts.padding);
return;
}
- const rtlHelper = getRtlAdapter(opts.rtl, me.left, me.width);
- const ctx = me.ctx;
+ const rtlHelper = getRtlAdapter(opts.rtl, this.left, this.width);
+ const ctx = this.ctx;
const position = titleOpts.position;
const halfFontSize = titleFont.size / 2;
const topPaddingPlusHalfFontSize = titlePadding.top + halfFontSize;
// These defaults are used when the legend is vertical.
// When horizontal, they are computed below.
- let left = me.left;
- let maxWidth = me.width;
+ let left = this.left;
+ let maxWidth = this.width;
if (this.isHorizontal()) {
// Move left / right so that the title is above the legend lines
- maxWidth = Math.max(...me.lineWidths);
- y = me.top + topPaddingPlusHalfFontSize;
- left = _alignStartEnd(opts.align, left, me.right - maxWidth);
+ maxWidth = Math.max(...this.lineWidths);
+ y = this.top + topPaddingPlusHalfFontSize;
+ left = _alignStartEnd(opts.align, left, this.right - maxWidth);
} else {
// Move down so that the title is above the legend stack in every alignment
- const maxHeight = me.columnSizes.reduce((acc, size) => Math.max(acc, size.height), 0);
- y = topPaddingPlusHalfFontSize + _alignStartEnd(opts.align, me.top, me.bottom - maxHeight - opts.labels.padding - me._computeTitleHeight());
+ const maxHeight = this.columnSizes.reduce((acc, size) => Math.max(acc, size.height), 0);
+ y = topPaddingPlusHalfFontSize + _alignStartEnd(opts.align, this.top, this.bottom - maxHeight - opts.labels.padding - this._computeTitleHeight());
}
// Now that we know the left edge of the inner legend box, compute the correct
* @private
*/
_getLegendItemAt(x, y) {
- const me = this;
let i, hitBox, lh;
- if (x >= me.left && x <= me.right && y >= me.top && y <= me.bottom) {
+ if (x >= this.left && x <= this.right && y >= this.top && y <= this.bottom) {
// See if we are touching one of the dataset boxes
- lh = me.legendHitBoxes;
+ lh = this.legendHitBoxes;
for (i = 0; i < lh.length; ++i) {
hitBox = lh[i];
if (x >= hitBox.left && x <= hitBox.left + hitBox.width && y >= hitBox.top && y <= hitBox.top + hitBox.height) {
// Touching an element
- return me.legendItems[i];
+ return this.legendItems[i];
}
}
}
* @param {ChartEvent} e - The event to handle
*/
handleEvent(e) {
- const me = this;
- const opts = me.options;
+ const opts = this.options;
if (!isListened(e.type, opts)) {
return;
}
// Chart event already has relative position in it
- const hoveredItem = me._getLegendItemAt(e.x, e.y);
+ const hoveredItem = this._getLegendItemAt(e.x, e.y);
if (e.type === 'mousemove') {
- const previous = me._hoveredItem;
+ const previous = this._hoveredItem;
const sameItem = itemsEqual(previous, hoveredItem);
if (previous && !sameItem) {
- call(opts.onLeave, [e, previous, me], me);
+ call(opts.onLeave, [e, previous, this], this);
}
- me._hoveredItem = hoveredItem;
+ this._hoveredItem = hoveredItem;
if (hoveredItem && !sameItem) {
- call(opts.onHover, [e, hoveredItem, me], me);
+ call(opts.onHover, [e, hoveredItem, this], this);
}
} else if (hoveredItem) {
- call(opts.onClick, [e, hoveredItem, me], me);
+ call(opts.onClick, [e, hoveredItem, this], this);
}
}
}
}
update(maxWidth, maxHeight) {
- const me = this;
- const opts = me.options;
+ const opts = this.options;
- me.left = 0;
- me.top = 0;
+ this.left = 0;
+ this.top = 0;
if (!opts.display) {
- me.width = me.height = me.right = me.bottom = 0;
+ this.width = this.height = this.right = this.bottom = 0;
return;
}
- me.width = me.right = maxWidth;
- me.height = me.bottom = maxHeight;
+ this.width = this.right = maxWidth;
+ this.height = this.bottom = maxHeight;
const lineCount = isArray(opts.text) ? opts.text.length : 1;
- me._padding = toPadding(opts.padding);
- const textSize = lineCount * toFont(opts.font).lineHeight + me._padding.height;
+ this._padding = toPadding(opts.padding);
+ const textSize = lineCount * toFont(opts.font).lineHeight + this._padding.height;
- if (me.isHorizontal()) {
- me.height = textSize;
+ if (this.isHorizontal()) {
+ this.height = textSize;
} else {
- me.width = textSize;
+ this.width = textSize;
}
}
}
draw() {
- const me = this;
- const ctx = me.ctx;
- const opts = me.options;
+ const ctx = this.ctx;
+ const opts = this.options;
if (!opts.display) {
return;
const fontOpts = toFont(opts.font);
const lineHeight = fontOpts.lineHeight;
- const offset = lineHeight / 2 + me._padding.top;
- const {titleX, titleY, maxWidth, rotation} = me._drawArgs(offset);
+ const offset = lineHeight / 2 + this._padding.top;
+ const {titleX, titleY, maxWidth, rotation} = this._drawArgs(offset);
renderText(ctx, opts.text, 0, 0, fontOpts, {
color: opts.color,
* @private
*/
_resolveAnimations() {
- const me = this;
- const cached = me._cachedAnimations;
+ const cached = this._cachedAnimations;
if (cached) {
return cached;
}
- const chart = me._chart;
- const options = me.options.setContext(me.getContext());
+ const chart = this._chart;
+ const options = this.options.setContext(this.getContext());
const opts = options.enabled && chart.options.animation && options.animations;
- const animations = new Animations(me._chart, opts);
+ const animations = new Animations(this._chart, opts);
if (opts._cacheable) {
- me._cachedAnimations = Object.freeze(animations);
+ this._cachedAnimations = Object.freeze(animations);
}
return animations;
* @protected
*/
getContext() {
- const me = this;
- return me.$context ||
- (me.$context = createTooltipContext(me._chart.getContext(), me, me._tooltipItems));
+ return this.$context ||
+ (this.$context = createTooltipContext(this._chart.getContext(), this, this._tooltipItems));
}
getTitle(context, options) {
- const me = this;
const {callbacks} = options;
- const beforeTitle = callbacks.beforeTitle.apply(me, [context]);
- const title = callbacks.title.apply(me, [context]);
- const afterTitle = callbacks.afterTitle.apply(me, [context]);
+ const beforeTitle = callbacks.beforeTitle.apply(this, [context]);
+ const title = callbacks.title.apply(this, [context]);
+ const afterTitle = callbacks.afterTitle.apply(this, [context]);
let lines = [];
lines = pushOrConcat(lines, splitNewlines(beforeTitle));
}
getBody(tooltipItems, options) {
- const me = this;
const {callbacks} = options;
const bodyItems = [];
after: []
};
const scoped = overrideCallbacks(callbacks, context);
- pushOrConcat(bodyItem.before, splitNewlines(scoped.beforeLabel.call(me, context)));
- pushOrConcat(bodyItem.lines, scoped.label.call(me, context));
- pushOrConcat(bodyItem.after, splitNewlines(scoped.afterLabel.call(me, context)));
+ pushOrConcat(bodyItem.before, splitNewlines(scoped.beforeLabel.call(this, context)));
+ pushOrConcat(bodyItem.lines, scoped.label.call(this, context));
+ pushOrConcat(bodyItem.after, splitNewlines(scoped.afterLabel.call(this, context)));
bodyItems.push(bodyItem);
});
// Get the footer and beforeFooter and afterFooter lines
getFooter(tooltipItems, options) {
- const me = this;
const {callbacks} = options;
- const beforeFooter = callbacks.beforeFooter.apply(me, [tooltipItems]);
- const footer = callbacks.footer.apply(me, [tooltipItems]);
- const afterFooter = callbacks.afterFooter.apply(me, [tooltipItems]);
+ const beforeFooter = callbacks.beforeFooter.apply(this, [tooltipItems]);
+ const footer = callbacks.footer.apply(this, [tooltipItems]);
+ const afterFooter = callbacks.afterFooter.apply(this, [tooltipItems]);
let lines = [];
lines = pushOrConcat(lines, splitNewlines(beforeFooter));
* @private
*/
_createItems(options) {
- const me = this;
- const active = me._active;
- const data = me._chart.data;
+ const active = this._active;
+ const data = this._chart.data;
const labelColors = [];
const labelPointStyles = [];
const labelTextColors = [];
let i, len;
for (i = 0, len = active.length; i < len; ++i) {
- tooltipItems.push(createTooltipItem(me._chart, active[i]));
+ tooltipItems.push(createTooltipItem(this._chart, active[i]));
}
// If the user provided a filter function, use it to modify the tooltip items
// Determine colors for boxes
each(tooltipItems, (context) => {
const scoped = overrideCallbacks(options.callbacks, context);
- labelColors.push(scoped.labelColor.call(me, context));
- labelPointStyles.push(scoped.labelPointStyle.call(me, context));
- labelTextColors.push(scoped.labelTextColor.call(me, context));
+ labelColors.push(scoped.labelColor.call(this, context));
+ labelPointStyles.push(scoped.labelPointStyle.call(this, context));
+ labelTextColors.push(scoped.labelTextColor.call(this, context));
});
- me.labelColors = labelColors;
- me.labelPointStyles = labelPointStyles;
- me.labelTextColors = labelTextColors;
- me.dataPoints = tooltipItems;
+ this.labelColors = labelColors;
+ this.labelPointStyles = labelPointStyles;
+ this.labelTextColors = labelTextColors;
+ this.dataPoints = tooltipItems;
return tooltipItems;
}
update(changed, replay) {
- const me = this;
- const options = me.options.setContext(me.getContext());
- const active = me._active;
+ const options = this.options.setContext(this.getContext());
+ const active = this._active;
let properties;
let tooltipItems = [];
if (!active.length) {
- if (me.opacity !== 0) {
+ if (this.opacity !== 0) {
properties = {
opacity: 0
};
}
} else {
- const position = positioners[options.position].call(me, active, me._eventPosition);
- tooltipItems = me._createItems(options);
+ const position = positioners[options.position].call(this, active, this._eventPosition);
+ tooltipItems = this._createItems(options);
- me.title = me.getTitle(tooltipItems, options);
- me.beforeBody = me.getBeforeBody(tooltipItems, options);
- me.body = me.getBody(tooltipItems, options);
- me.afterBody = me.getAfterBody(tooltipItems, options);
- me.footer = me.getFooter(tooltipItems, options);
+ this.title = this.getTitle(tooltipItems, options);
+ this.beforeBody = this.getBeforeBody(tooltipItems, options);
+ this.body = this.getBody(tooltipItems, options);
+ this.afterBody = this.getAfterBody(tooltipItems, options);
+ this.footer = this.getFooter(tooltipItems, options);
- const size = me._size = getTooltipSize(me, options);
+ const size = this._size = getTooltipSize(this, options);
const positionAndSize = Object.assign({}, position, size);
- const alignment = determineAlignment(me._chart, options, positionAndSize);
- const backgroundPoint = getBackgroundPoint(options, positionAndSize, alignment, me._chart);
+ const alignment = determineAlignment(this._chart, options, positionAndSize);
+ const backgroundPoint = getBackgroundPoint(options, positionAndSize, alignment, this._chart);
- me.xAlign = alignment.xAlign;
- me.yAlign = alignment.yAlign;
+ this.xAlign = alignment.xAlign;
+ this.yAlign = alignment.yAlign;
properties = {
opacity: 1,
};
}
- me._tooltipItems = tooltipItems;
- me.$context = undefined;
+ this._tooltipItems = tooltipItems;
+ this.$context = undefined;
if (properties) {
- me._resolveAnimations().update(me, properties);
+ this._resolveAnimations().update(this, properties);
}
if (changed && options.external) {
- options.external.call(me, {chart: me._chart, tooltip: me, replay});
+ options.external.call(this, {chart: this._chart, tooltip: this, replay});
}
}
}
drawTitle(pt, ctx, options) {
- const me = this;
- const title = me.title;
+ const title = this.title;
const length = title.length;
let titleFont, titleSpacing, i;
if (length) {
- const rtlHelper = getRtlAdapter(options.rtl, me.x, me.width);
+ const rtlHelper = getRtlAdapter(options.rtl, this.x, this.width);
- pt.x = getAlignedX(me, options.titleAlign, options);
+ pt.x = getAlignedX(this, options.titleAlign, options);
ctx.textAlign = rtlHelper.textAlign(options.titleAlign);
ctx.textBaseline = 'middle';
* @private
*/
_drawColorBox(ctx, pt, i, rtlHelper, options) {
- const me = this;
- const labelColors = me.labelColors[i];
- const labelPointStyle = me.labelPointStyles[i];
+ const labelColors = this.labelColors[i];
+ const labelPointStyle = this.labelPointStyles[i];
const {boxHeight, boxWidth, boxPadding} = options;
const bodyFont = toFont(options.bodyFont);
- const colorX = getAlignedX(me, 'left', options);
+ const colorX = getAlignedX(this, 'left', options);
const rtlColorX = rtlHelper.x(colorX);
const yOffSet = boxHeight < bodyFont.lineHeight ? (bodyFont.lineHeight - boxHeight) / 2 : 0;
const colorY = pt.y + yOffSet;
}
// restore fillStyle
- ctx.fillStyle = me.labelTextColors[i];
+ ctx.fillStyle = this.labelTextColors[i];
}
drawBody(pt, ctx, options) {
- const me = this;
- const {body} = me;
+ const {body} = this;
const {bodySpacing, bodyAlign, displayColors, boxHeight, boxWidth, boxPadding} = options;
const bodyFont = toFont(options.bodyFont);
let bodyLineHeight = bodyFont.lineHeight;
let xLinePadding = 0;
- const rtlHelper = getRtlAdapter(options.rtl, me.x, me.width);
+ const rtlHelper = getRtlAdapter(options.rtl, this.x, this.width);
const fillLineOfText = function(line) {
ctx.fillText(line, rtlHelper.x(pt.x + xLinePadding), pt.y + bodyLineHeight / 2);
ctx.textBaseline = 'middle';
ctx.font = bodyFont.string;
- pt.x = getAlignedX(me, bodyAlignForCalculation, options);
+ pt.x = getAlignedX(this, bodyAlignForCalculation, options);
// Before body lines
ctx.fillStyle = options.bodyColor;
- each(me.beforeBody, fillLineOfText);
+ each(this.beforeBody, fillLineOfText);
xLinePadding = displayColors && bodyAlignForCalculation !== 'right'
? bodyAlign === 'center' ? (boxWidth / 2 + boxPadding) : (boxWidth + 2 + boxPadding)
// Draw body lines now
for (i = 0, ilen = body.length; i < ilen; ++i) {
bodyItem = body[i];
- textColor = me.labelTextColors[i];
+ textColor = this.labelTextColors[i];
ctx.fillStyle = textColor;
each(bodyItem.before, fillLineOfText);
lines = bodyItem.lines;
// Draw Legend-like boxes if needed
if (displayColors && lines.length) {
- me._drawColorBox(ctx, pt, i, rtlHelper, options);
+ this._drawColorBox(ctx, pt, i, rtlHelper, options);
bodyLineHeight = Math.max(bodyFont.lineHeight, boxHeight);
}
bodyLineHeight = bodyFont.lineHeight;
// After body lines
- each(me.afterBody, fillLineOfText);
+ each(this.afterBody, fillLineOfText);
pt.y -= bodySpacing; // Remove last body spacing
}
drawFooter(pt, ctx, options) {
- const me = this;
- const footer = me.footer;
+ const footer = this.footer;
const length = footer.length;
let footerFont, i;
if (length) {
- const rtlHelper = getRtlAdapter(options.rtl, me.x, me.width);
+ const rtlHelper = getRtlAdapter(options.rtl, this.x, this.width);
- pt.x = getAlignedX(me, options.footerAlign, options);
+ pt.x = getAlignedX(this, options.footerAlign, options);
pt.y += options.footerMarginTop;
ctx.textAlign = rtlHelper.textAlign(options.footerAlign);
* @private
*/
_updateAnimationTarget(options) {
- const me = this;
- const chart = me._chart;
- const anims = me.$animations;
+ const chart = this._chart;
+ const anims = this.$animations;
const animX = anims && anims.x;
const animY = anims && anims.y;
if (animX || animY) {
- const position = positioners[options.position].call(me, me._active, me._eventPosition);
+ const position = positioners[options.position].call(this, this._active, this._eventPosition);
if (!position) {
return;
}
- const size = me._size = getTooltipSize(me, options);
- const positionAndSize = Object.assign({}, position, me._size);
+ const size = this._size = getTooltipSize(this, options);
+ const positionAndSize = Object.assign({}, position, this._size);
const alignment = determineAlignment(chart, options, positionAndSize);
const point = getBackgroundPoint(options, positionAndSize, alignment, chart);
if (animX._to !== point.x || animY._to !== point.y) {
- me.xAlign = alignment.xAlign;
- me.yAlign = alignment.yAlign;
- me.width = size.width;
- me.height = size.height;
- me.caretX = position.x;
- me.caretY = position.y;
- me._resolveAnimations().update(me, point);
+ this.xAlign = alignment.xAlign;
+ this.yAlign = alignment.yAlign;
+ this.width = size.width;
+ this.height = size.height;
+ this.caretX = position.x;
+ this.caretY = position.y;
+ this._resolveAnimations().update(this, point);
}
}
}
draw(ctx) {
- const me = this;
- const options = me.options.setContext(me.getContext());
- let opacity = me.opacity;
+ const options = this.options.setContext(this.getContext());
+ let opacity = this.opacity;
if (!opacity) {
return;
}
- me._updateAnimationTarget(options);
+ this._updateAnimationTarget(options);
const tooltipSize = {
- width: me.width,
- height: me.height
+ width: this.width,
+ height: this.height
};
const pt = {
- x: me.x,
- y: me.y
+ x: this.x,
+ y: this.y
};
// IE11/Edge does not like very small opacities, so snap to 0
const padding = toPadding(options.padding);
// Truthy/falsey value for empty tooltip
- const hasTooltipContent = me.title.length || me.beforeBody.length || me.body.length || me.afterBody.length || me.footer.length;
+ const hasTooltipContent = this.title.length || this.beforeBody.length || this.body.length || this.afterBody.length || this.footer.length;
if (options.enabled && hasTooltipContent) {
ctx.save();
ctx.globalAlpha = opacity;
// Draw Background
- me.drawBackground(pt, ctx, tooltipSize, options);
+ this.drawBackground(pt, ctx, tooltipSize, options);
overrideTextDirection(ctx, options.textDirection);
pt.y += padding.top;
// Titles
- me.drawTitle(pt, ctx, options);
+ this.drawTitle(pt, ctx, options);
// Body
- me.drawBody(pt, ctx, options);
+ this.drawBody(pt, ctx, options);
// Footer
- me.drawFooter(pt, ctx, options);
+ this.drawFooter(pt, ctx, options);
restoreTextDirection(ctx, options.textDirection);
* @param {object} eventPosition Synthetic event position used in positioning
*/
setActiveElements(activeElements, eventPosition) {
- const me = this;
- const lastActive = me._active;
+ const lastActive = this._active;
const active = activeElements.map(({datasetIndex, index}) => {
- const meta = me._chart.getDatasetMeta(datasetIndex);
+ const meta = this._chart.getDatasetMeta(datasetIndex);
if (!meta) {
throw new Error('Cannot find a dataset at index ' + datasetIndex);
};
});
const changed = !_elementsEqual(lastActive, active);
- const positionChanged = me._positionChanged(active, eventPosition);
+ const positionChanged = this._positionChanged(active, eventPosition);
if (changed || positionChanged) {
- me._active = active;
- me._eventPosition = eventPosition;
- me.update(true);
+ this._active = active;
+ this._eventPosition = eventPosition;
+ this.update(true);
}
}
* @returns {boolean} true if the tooltip changed
*/
handleEvent(e, replay) {
- const me = this;
- const options = me.options;
- const lastActive = me._active || [];
+ const options = this.options;
+ const lastActive = this._active || [];
let changed = false;
let active = [];
// Find Active Elements for tooltips
if (e.type !== 'mouseout') {
- active = me._chart.getElementsAtEventForMode(e, options.mode, options, replay);
+ active = this._chart.getElementsAtEventForMode(e, options.mode, options, replay);
if (options.reverse) {
active.reverse();
}
// When there are multiple items shown, but the tooltip position is nearest mode
// an update may need to be made because our position may have changed even though
// the items are the same as before.
- const positionChanged = me._positionChanged(active, e);
+ const positionChanged = this._positionChanged(active, e);
// Remember Last Actives
changed = replay || !_elementsEqual(active, lastActive) || positionChanged;
// Only handle target event on tooltip change
if (changed) {
- me._active = active;
+ this._active = active;
if (options.enabled || options.external) {
- me._eventPosition = {
+ this._eventPosition = {
x: e.x,
y: e.y
};
- me.update(true, replay);
+ this.update(true, replay);
}
}
}
determineDataLimits() {
- const me = this;
- const {minDefined, maxDefined} = me.getUserBounds();
- let {min, max} = me.getMinMax(true);
+ const {minDefined, maxDefined} = this.getUserBounds();
+ let {min, max} = this.getMinMax(true);
- if (me.options.bounds === 'ticks') {
+ if (this.options.bounds === 'ticks') {
if (!minDefined) {
min = 0;
}
if (!maxDefined) {
- max = me.getLabels().length - 1;
+ max = this.getLabels().length - 1;
}
}
- me.min = min;
- me.max = max;
+ this.min = min;
+ this.max = max;
}
buildTicks() {
- const me = this;
- const min = me.min;
- const max = me.max;
- const offset = me.options.offset;
+ const min = this.min;
+ const max = this.max;
+ const offset = this.options.offset;
const ticks = [];
- let labels = me.getLabels();
+ let labels = this.getLabels();
// If we are viewing some subset of labels, slice the original array
labels = (min === 0 && max === labels.length - 1) ? labels : labels.slice(min, max + 1);
- me._valueRange = Math.max(labels.length - (offset ? 0 : 1), 1);
- me._startValue = me.min - (offset ? 0.5 : 0);
+ this._valueRange = Math.max(labels.length - (offset ? 0 : 1), 1);
+ this._startValue = this.min - (offset ? 0.5 : 0);
for (let value = min; value <= max; value++) {
ticks.push({value});
}
getLabelForValue(value) {
- const me = this;
- const labels = me.getLabels();
+ const labels = this.getLabels();
if (value >= 0 && value < labels.length) {
return labels[value];
* @protected
*/
configure() {
- const me = this;
-
super.configure();
- if (!me.isHorizontal()) {
+ if (!this.isHorizontal()) {
// For backward compatibility, vertical category scale reverse is inverted.
- me._reversePixels = !me._reversePixels;
+ this._reversePixels = !this._reversePixels;
}
}
// Used to get data value locations. Value can either be an index or a numerical value
getPixelForValue(value) {
- const me = this;
-
if (typeof value !== 'number') {
- value = me.parse(value);
+ value = this.parse(value);
}
- return value === null ? NaN : me.getPixelForDecimal((value - me._startValue) / me._valueRange);
+ return value === null ? NaN : this.getPixelForDecimal((value - this._startValue) / this._valueRange);
}
// Must override base implementation because it calls getPixelForValue
// and category scale can have duplicate values
getPixelForTick(index) {
- const me = this;
- const ticks = me.ticks;
+ const ticks = this.ticks;
if (index < 0 || index > ticks.length - 1) {
return null;
}
- return me.getPixelForValue(ticks[index].value);
+ return this.getPixelForValue(ticks[index].value);
}
getValueForPixel(pixel) {
- const me = this;
- return Math.round(me._startValue + me.getDecimalForPixel(pixel) * me._valueRange);
+ return Math.round(this._startValue + this.getDecimalForPixel(pixel) * this._valueRange);
}
getBasePixel() {
export default class LinearScale extends LinearScaleBase {
determineDataLimits() {
- const me = this;
- const {min, max} = me.getMinMax(true);
+ const {min, max} = this.getMinMax(true);
- me.min = isFinite(min) ? min : 0;
- me.max = isFinite(max) ? max : 1;
+ this.min = isFinite(min) ? min : 0;
+ this.max = isFinite(max) ? max : 1;
// Common base implementation to handle min, max, beginAtZero
- me.handleTickRangeOptions();
+ this.handleTickRangeOptions();
}
/**
* @protected
*/
computeTickLimit() {
- const me = this;
- const horizontal = me.isHorizontal();
- const length = horizontal ? me.width : me.height;
- const minRotation = toRadians(me.options.ticks.minRotation);
+ const horizontal = this.isHorizontal();
+ const length = horizontal ? this.width : this.height;
+ const minRotation = toRadians(this.options.ticks.minRotation);
const ratio = (horizontal ? Math.sin(minRotation) : Math.cos(minRotation)) || 0.001;
- const tickFont = me._resolveTickFontOptions(0);
+ const tickFont = this._resolveTickFontOptions(0);
return Math.ceil(length / Math.min(40, tickFont.lineHeight / ratio));
}
}
handleTickRangeOptions() {
- const me = this;
- const {beginAtZero} = me.options;
- const {minDefined, maxDefined} = me.getUserBounds();
- let {min, max} = me;
+ const {beginAtZero} = this.options;
+ const {minDefined, maxDefined} = this.getUserBounds();
+ let {min, max} = this;
const setMin = v => (min = minDefined ? min : v);
const setMax = v => (max = maxDefined ? max : v);
setMin(min - offset);
}
}
- me.min = min;
- me.max = max;
+ this.min = min;
+ this.max = max;
}
getTickLimit() {
- const me = this;
- const tickOpts = me.options.ticks;
+ const tickOpts = this.options.ticks;
// eslint-disable-next-line prefer-const
let {maxTicksLimit, stepSize} = tickOpts;
let maxTicks;
if (stepSize) {
- maxTicks = Math.ceil(me.max / stepSize) - Math.floor(me.min / stepSize) + 1;
+ maxTicks = Math.ceil(this.max / stepSize) - Math.floor(this.min / stepSize) + 1;
} else {
- maxTicks = me.computeTickLimit();
+ maxTicks = this.computeTickLimit();
maxTicksLimit = maxTicksLimit || 11;
}
}
buildTicks() {
- const me = this;
- const opts = me.options;
+ const opts = this.options;
const tickOpts = opts.ticks;
// Figure out what the max number of ticks we can support it is based on the size of
// the axis area. For now, we say that the minimum tick spacing in pixels must be 40
// We also limit the maximum number of ticks to 11 which gives a nice 10 squares on
// the graph. Make sure we always have at least 2 ticks
- let maxTicks = me.getTickLimit();
+ let maxTicks = this.getTickLimit();
maxTicks = Math.max(2, maxTicks);
const numericGeneratorOptions = {
precision: tickOpts.precision,
step: tickOpts.stepSize,
count: tickOpts.count,
- maxDigits: me._maxDigits(),
- horizontal: me.isHorizontal(),
+ maxDigits: this._maxDigits(),
+ horizontal: this.isHorizontal(),
minRotation: tickOpts.minRotation || 0,
includeBounds: tickOpts.includeBounds !== false
};
- const dataRange = me._range || me;
+ const dataRange = this._range || this;
const ticks = generateTicks(numericGeneratorOptions, dataRange);
// At this point, we need to update our max and min given the tick values,
// since we probably have expanded the range of the scale
if (opts.bounds === 'ticks') {
- _setMinAndMaxByKey(ticks, me, 'value');
+ _setMinAndMaxByKey(ticks, this, 'value');
}
if (opts.reverse) {
ticks.reverse();
- me.start = me.max;
- me.end = me.min;
+ this.start = this.max;
+ this.end = this.min;
} else {
- me.start = me.min;
- me.end = me.max;
+ this.start = this.min;
+ this.end = this.max;
}
return ticks;
* @protected
*/
configure() {
- const me = this;
- const ticks = me.ticks;
- let start = me.min;
- let end = me.max;
+ const ticks = this.ticks;
+ let start = this.min;
+ let end = this.max;
super.configure();
- if (me.options.offset && ticks.length) {
+ if (this.options.offset && ticks.length) {
const offset = (end - start) / Math.max(ticks.length - 1, 1) / 2;
start -= offset;
end += offset;
}
- me._startValue = start;
- me._endValue = end;
- me._valueRange = end - start;
+ this._startValue = start;
+ this._endValue = end;
+ this._valueRange = end - start;
}
getLabelForValue(value) {
}
determineDataLimits() {
- const me = this;
- const {min, max} = me.getMinMax(true);
+ const {min, max} = this.getMinMax(true);
- me.min = isFinite(min) ? Math.max(0, min) : null;
- me.max = isFinite(max) ? Math.max(0, max) : null;
+ this.min = isFinite(min) ? Math.max(0, min) : null;
+ this.max = isFinite(max) ? Math.max(0, max) : null;
- if (me.options.beginAtZero) {
- me._zero = true;
+ if (this.options.beginAtZero) {
+ this._zero = true;
}
- me.handleTickRangeOptions();
+ this.handleTickRangeOptions();
}
handleTickRangeOptions() {
- const me = this;
- const {minDefined, maxDefined} = me.getUserBounds();
- let min = me.min;
- let max = me.max;
+ const {minDefined, maxDefined} = this.getUserBounds();
+ let min = this.min;
+ let max = this.max;
const setMin = v => (min = minDefined ? min : v);
const setMax = v => (max = maxDefined ? max : v);
}
// if data has `0` in it or `beginAtZero` is true, min (non zero) value is at bottom
// of scale, and it does not equal suggestedMin, lower the min bound by one exp.
- if (me._zero && me.min !== me._suggestedMin && min === exp(me.min, 0)) {
+ if (this._zero && this.min !== this._suggestedMin && min === exp(this.min, 0)) {
setMin(exp(min, -1));
}
- me.min = min;
- me.max = max;
+ this.min = min;
+ this.max = max;
}
buildTicks() {
- const me = this;
- const opts = me.options;
+ const opts = this.options;
const generationOptions = {
- min: me._userMin,
- max: me._userMax
+ min: this._userMin,
+ max: this._userMax
};
- const ticks = generateTicks(generationOptions, me);
+ const ticks = generateTicks(generationOptions, this);
// At this point, we need to update our max and min given the tick values,
// since we probably have expanded the range of the scale
if (opts.bounds === 'ticks') {
- _setMinAndMaxByKey(ticks, me, 'value');
+ _setMinAndMaxByKey(ticks, this, 'value');
}
if (opts.reverse) {
ticks.reverse();
- me.start = me.max;
- me.end = me.min;
+ this.start = this.max;
+ this.end = this.min;
} else {
- me.start = me.min;
- me.end = me.max;
+ this.start = this.min;
+ this.end = this.max;
}
return ticks;
* @protected
*/
configure() {
- const me = this;
- const start = me.min;
+ const start = this.min;
super.configure();
- me._startValue = log10(start);
- me._valueRange = log10(me.max) - log10(start);
+ this._startValue = log10(start);
+ this._valueRange = log10(this.max) - log10(start);
}
getPixelForValue(value) {
- const me = this;
if (value === undefined || value === 0) {
- value = me.min;
+ value = this.min;
}
if (value === null || isNaN(value)) {
return NaN;
}
- return me.getPixelForDecimal(value === me.min
+ return this.getPixelForDecimal(value === this.min
? 0
- : (log10(value) - me._startValue) / me._valueRange);
+ : (log10(value) - this._startValue) / this._valueRange);
}
getValueForPixel(pixel) {
- const me = this;
- const decimal = me.getDecimalForPixel(pixel);
- return Math.pow(10, me._startValue + decimal * me._valueRange);
+ const decimal = this.getDecimalForPixel(pixel);
+ return Math.pow(10, this._startValue + decimal * this._valueRange);
}
}
}
setDimensions() {
- const me = this;
-
// Set the unconstrained dimension before label rotation
- me.width = me.maxWidth;
- me.height = me.maxHeight;
- me.paddingTop = getTickBackdropHeight(me.options) / 2;
- me.xCenter = Math.floor(me.width / 2);
- me.yCenter = Math.floor((me.height - me.paddingTop) / 2);
- me.drawingArea = Math.min(me.height - me.paddingTop, me.width) / 2;
+ this.width = this.maxWidth;
+ this.height = this.maxHeight;
+ this.paddingTop = getTickBackdropHeight(this.options) / 2;
+ this.xCenter = Math.floor(this.width / 2);
+ this.yCenter = Math.floor((this.height - this.paddingTop) / 2);
+ this.drawingArea = Math.min(this.height - this.paddingTop, this.width) / 2;
}
determineDataLimits() {
- const me = this;
- const {min, max} = me.getMinMax(false);
+ const {min, max} = this.getMinMax(false);
- me.min = isFinite(min) && !isNaN(min) ? min : 0;
- me.max = isFinite(max) && !isNaN(max) ? max : 0;
+ this.min = isFinite(min) && !isNaN(min) ? min : 0;
+ this.max = isFinite(max) && !isNaN(max) ? max : 0;
// Common base implementation to handle min, max, beginAtZero
- me.handleTickRangeOptions();
+ this.handleTickRangeOptions();
}
/**
}
generateTickLabels(ticks) {
- const me = this;
-
- LinearScaleBase.prototype.generateTickLabels.call(me, ticks);
+ LinearScaleBase.prototype.generateTickLabels.call(this, ticks);
// Point labels
- me._pointLabels = me.getLabels().map((value, index) => {
- const label = callCallback(me.options.pointLabels.callback, [value, index], me);
+ this._pointLabels = this.getLabels().map((value, index) => {
+ const label = callCallback(this.options.pointLabels.callback, [value, index], this);
return label || label === 0 ? label : '';
});
}
fit() {
- const me = this;
- const opts = me.options;
+ const opts = this.options;
if (opts.display && opts.pointLabels.display) {
- fitWithPointLabels(me);
+ fitWithPointLabels(this);
} else {
- me.setCenterPoint(0, 0, 0, 0);
+ this.setCenterPoint(0, 0, 0, 0);
}
}
* @private
*/
_setReductions(largestPossibleRadius, furthestLimits, furthestAngles) {
- const me = this;
let radiusReductionLeft = furthestLimits.l / Math.sin(furthestAngles.l);
- let radiusReductionRight = Math.max(furthestLimits.r - me.width, 0) / Math.sin(furthestAngles.r);
+ let radiusReductionRight = Math.max(furthestLimits.r - this.width, 0) / Math.sin(furthestAngles.r);
let radiusReductionTop = -furthestLimits.t / Math.cos(furthestAngles.t);
- let radiusReductionBottom = -Math.max(furthestLimits.b - (me.height - me.paddingTop), 0) / Math.cos(furthestAngles.b);
+ let radiusReductionBottom = -Math.max(furthestLimits.b - (this.height - this.paddingTop), 0) / Math.cos(furthestAngles.b);
radiusReductionLeft = numberOrZero(radiusReductionLeft);
radiusReductionRight = numberOrZero(radiusReductionRight);
radiusReductionTop = numberOrZero(radiusReductionTop);
radiusReductionBottom = numberOrZero(radiusReductionBottom);
- me.drawingArea = Math.max(largestPossibleRadius / 2, Math.min(
+ this.drawingArea = Math.max(largestPossibleRadius / 2, Math.min(
Math.floor(largestPossibleRadius - (radiusReductionLeft + radiusReductionRight) / 2),
Math.floor(largestPossibleRadius - (radiusReductionTop + radiusReductionBottom) / 2)));
- me.setCenterPoint(radiusReductionLeft, radiusReductionRight, radiusReductionTop, radiusReductionBottom);
+ this.setCenterPoint(radiusReductionLeft, radiusReductionRight, radiusReductionTop, radiusReductionBottom);
}
setCenterPoint(leftMovement, rightMovement, topMovement, bottomMovement) {
- const me = this;
- const maxRight = me.width - rightMovement - me.drawingArea;
- const maxLeft = leftMovement + me.drawingArea;
- const maxTop = topMovement + me.drawingArea;
- const maxBottom = (me.height - me.paddingTop) - bottomMovement - me.drawingArea;
-
- me.xCenter = Math.floor(((maxLeft + maxRight) / 2) + me.left);
- me.yCenter = Math.floor(((maxTop + maxBottom) / 2) + me.top + me.paddingTop);
+ const maxRight = this.width - rightMovement - this.drawingArea;
+ const maxLeft = leftMovement + this.drawingArea;
+ const maxTop = topMovement + this.drawingArea;
+ const maxBottom = (this.height - this.paddingTop) - bottomMovement - this.drawingArea;
+
+ this.xCenter = Math.floor(((maxLeft + maxRight) / 2) + this.left);
+ this.yCenter = Math.floor(((maxTop + maxBottom) / 2) + this.top + this.paddingTop);
}
getIndexAngle(index) {
}
getDistanceFromCenterForValue(value) {
- const me = this;
-
if (isNullOrUndef(value)) {
return NaN;
}
// Take into account half font size + the yPadding of the top value
- const scalingFactor = me.drawingArea / (me.max - me.min);
- if (me.options.reverse) {
- return (me.max - value) * scalingFactor;
+ const scalingFactor = this.drawingArea / (this.max - this.min);
+ if (this.options.reverse) {
+ return (this.max - value) * scalingFactor;
}
- return (value - me.min) * scalingFactor;
+ return (value - this.min) * scalingFactor;
}
getValueForDistanceFromCenter(distance) {
return NaN;
}
- const me = this;
- const scaledDistance = distance / (me.drawingArea / (me.max - me.min));
- return me.options.reverse ? me.max - scaledDistance : me.min + scaledDistance;
+ const scaledDistance = distance / (this.drawingArea / (this.max - this.min));
+ return this.options.reverse ? this.max - scaledDistance : this.min + scaledDistance;
}
getPointLabelContext(index) {
- const me = this;
- const pointLabels = me._pointLabels || [];
+ const pointLabels = this._pointLabels || [];
if (index >= 0 && index < pointLabels.length) {
const pointLabel = pointLabels[index];
- return createPointLabelContext(me.getContext(), index, pointLabel);
+ return createPointLabelContext(this.getContext(), index, pointLabel);
}
}
getPointPosition(index, distanceFromCenter) {
- const me = this;
- const angle = me.getIndexAngle(index) - HALF_PI;
+ const angle = this.getIndexAngle(index) - HALF_PI;
return {
- x: Math.cos(angle) * distanceFromCenter + me.xCenter,
- y: Math.sin(angle) * distanceFromCenter + me.yCenter,
+ x: Math.cos(angle) * distanceFromCenter + this.xCenter,
+ y: Math.sin(angle) * distanceFromCenter + this.yCenter,
angle
};
}
* @protected
*/
drawBackground() {
- const me = this;
- const {backgroundColor, grid: {circular}} = me.options;
+ const {backgroundColor, grid: {circular}} = this.options;
if (backgroundColor) {
- const ctx = me.ctx;
+ const ctx = this.ctx;
ctx.save();
ctx.beginPath();
- pathRadiusLine(me, me.getDistanceFromCenterForValue(me._endValue), circular, me.getLabels().length);
+ pathRadiusLine(this, this.getDistanceFromCenterForValue(this._endValue), circular, this.getLabels().length);
ctx.closePath();
ctx.fillStyle = backgroundColor;
ctx.fill();
* @protected
*/
drawGrid() {
- const me = this;
- const ctx = me.ctx;
- const opts = me.options;
+ const ctx = this.ctx;
+ const opts = this.options;
const {angleLines, grid} = opts;
- const labelCount = me.getLabels().length;
+ const labelCount = this.getLabels().length;
let i, offset, position;
if (opts.pointLabels.display) {
- drawPointLabels(me, labelCount);
+ drawPointLabels(this, labelCount);
}
if (grid.display) {
- me.ticks.forEach((tick, index) => {
+ this.ticks.forEach((tick, index) => {
if (index !== 0) {
- offset = me.getDistanceFromCenterForValue(tick.value);
- const optsAtIndex = grid.setContext(me.getContext(index - 1));
- drawRadiusLine(me, optsAtIndex, offset, labelCount);
+ offset = this.getDistanceFromCenterForValue(tick.value);
+ const optsAtIndex = grid.setContext(this.getContext(index - 1));
+ drawRadiusLine(this, optsAtIndex, offset, labelCount);
}
});
}
if (angleLines.display) {
ctx.save();
- for (i = me.getLabels().length - 1; i >= 0; i--) {
- const optsAtIndex = angleLines.setContext(me.getPointLabelContext(i));
+ for (i = this.getLabels().length - 1; i >= 0; i--) {
+ const optsAtIndex = angleLines.setContext(this.getPointLabelContext(i));
const {color, lineWidth} = optsAtIndex;
if (!lineWidth || !color) {
ctx.setLineDash(optsAtIndex.borderDash);
ctx.lineDashOffset = optsAtIndex.borderDashOffset;
- offset = me.getDistanceFromCenterForValue(opts.ticks.reverse ? me.min : me.max);
- position = me.getPointPosition(i, offset);
+ offset = this.getDistanceFromCenterForValue(opts.ticks.reverse ? this.min : this.max);
+ position = this.getPointPosition(i, offset);
ctx.beginPath();
- ctx.moveTo(me.xCenter, me.yCenter);
+ ctx.moveTo(this.xCenter, this.yCenter);
ctx.lineTo(position.x, position.y);
ctx.stroke();
}
* @protected
*/
drawLabels() {
- const me = this;
- const ctx = me.ctx;
- const opts = me.options;
+ const ctx = this.ctx;
+ const opts = this.options;
const tickOpts = opts.ticks;
if (!tickOpts.display) {
return;
}
- const startAngle = me.getIndexAngle(0);
+ const startAngle = this.getIndexAngle(0);
let offset, width;
ctx.save();
- ctx.translate(me.xCenter, me.yCenter);
+ ctx.translate(this.xCenter, this.yCenter);
ctx.rotate(startAngle);
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
- me.ticks.forEach((tick, index) => {
+ this.ticks.forEach((tick, index) => {
if (index === 0 && !opts.reverse) {
return;
}
- const optsAtIndex = tickOpts.setContext(me.getContext(index));
+ const optsAtIndex = tickOpts.setContext(this.getContext(index));
const tickFont = toFont(optsAtIndex.font);
- offset = me.getDistanceFromCenterForValue(me.ticks[index].value);
+ offset = this.getDistanceFromCenterForValue(this.ticks[index].value);
if (optsAtIndex.showLabelBackdrop) {
ctx.font = tickFont.string;
}
determineDataLimits() {
- const me = this;
- const options = me.options;
- const adapter = me._adapter;
+ const options = this.options;
+ const adapter = this._adapter;
const unit = options.time.unit || 'day';
// eslint-disable-next-line prefer-const
- let {min, max, minDefined, maxDefined} = me.getUserBounds();
+ let {min, max, minDefined, maxDefined} = this.getUserBounds();
/**
* @param {object} bounds
// If we have user provided `min` and `max` labels / data bounds can be ignored
if (!minDefined || !maxDefined) {
// Labels are always considered, when user did not force bounds
- _applyBounds(me._getLabelBounds());
+ _applyBounds(this._getLabelBounds());
// If `bounds` is `'ticks'` and `ticks.source` is `'labels'`,
// data bounds are ignored (and don't need to be determined)
if (options.bounds !== 'ticks' || options.ticks.source !== 'labels') {
- _applyBounds(me.getMinMax(false));
+ _applyBounds(this.getMinMax(false));
}
}
max = isFinite(max) && !isNaN(max) ? max : +adapter.endOf(Date.now(), unit) + 1;
// Make sure that max is strictly higher than min (required by the timeseries lookup table)
- me.min = Math.min(min, max - 1);
- me.max = Math.max(min + 1, max);
+ this.min = Math.min(min, max - 1);
+ this.max = Math.max(min + 1, max);
}
/**
* @return {object[]}
*/
buildTicks() {
- const me = this;
- const options = me.options;
+ const options = this.options;
const timeOpts = options.time;
const tickOpts = options.ticks;
- const timestamps = tickOpts.source === 'labels' ? me.getLabelTimestamps() : me._generate();
+ const timestamps = tickOpts.source === 'labels' ? this.getLabelTimestamps() : this._generate();
if (options.bounds === 'ticks' && timestamps.length) {
- me.min = me._userMin || timestamps[0];
- me.max = me._userMax || timestamps[timestamps.length - 1];
+ this.min = this._userMin || timestamps[0];
+ this.max = this._userMax || timestamps[timestamps.length - 1];
}
- const min = me.min;
- const max = me.max;
+ const min = this.min;
+ const max = this.max;
const ticks = _filterBetween(timestamps, min, max);
// PRIVATE
// determineUnitForFormatting relies on the number of ticks so we don't use it when
// autoSkip is enabled because we don't yet know what the final number of ticks will be
- me._unit = timeOpts.unit || (tickOpts.autoSkip
- ? determineUnitForAutoTicks(timeOpts.minUnit, me.min, me.max, me._getLabelCapacity(min))
- : determineUnitForFormatting(me, ticks.length, timeOpts.minUnit, me.min, me.max));
- me._majorUnit = !tickOpts.major.enabled || me._unit === 'year' ? undefined
- : determineMajorUnit(me._unit);
- me.initOffsets(timestamps);
+ this._unit = timeOpts.unit || (tickOpts.autoSkip
+ ? determineUnitForAutoTicks(timeOpts.minUnit, this.min, this.max, this._getLabelCapacity(min))
+ : determineUnitForFormatting(this, ticks.length, timeOpts.minUnit, this.min, this.max));
+ this._majorUnit = !tickOpts.major.enabled || this._unit === 'year' ? undefined
+ : determineMajorUnit(this._unit);
+ this.initOffsets(timestamps);
if (options.reverse) {
ticks.reverse();
}
- return ticksFromTimestamps(me, ticks, me._majorUnit);
+ return ticksFromTimestamps(this, ticks, this._majorUnit);
}
/**
* @protected
*/
initOffsets(timestamps) {
- const me = this;
let start = 0;
let end = 0;
let first, last;
- if (me.options.offset && timestamps.length) {
- first = me.getDecimalForValue(timestamps[0]);
+ if (this.options.offset && timestamps.length) {
+ first = this.getDecimalForValue(timestamps[0]);
if (timestamps.length === 1) {
start = 1 - first;
} else {
- start = (me.getDecimalForValue(timestamps[1]) - first) / 2;
+ start = (this.getDecimalForValue(timestamps[1]) - first) / 2;
}
- last = me.getDecimalForValue(timestamps[timestamps.length - 1]);
+ last = this.getDecimalForValue(timestamps[timestamps.length - 1]);
if (timestamps.length === 1) {
end = last;
} else {
- end = (last - me.getDecimalForValue(timestamps[timestamps.length - 2])) / 2;
+ end = (last - this.getDecimalForValue(timestamps[timestamps.length - 2])) / 2;
}
}
const limit = timestamps.length < 3 ? 0.5 : 0.25;
start = _limitValue(start, 0, limit);
end = _limitValue(end, 0, limit);
- me._offsets = {start, end, factor: 1 / (start + 1 + end)};
+ this._offsets = {start, end, factor: 1 / (start + 1 + end)};
}
/**
* @private
*/
_generate() {
- const me = this;
- const adapter = me._adapter;
- const min = me.min;
- const max = me.max;
- const options = me.options;
+ const adapter = this._adapter;
+ const min = this.min;
+ const max = this.max;
+ const options = this.options;
const timeOpts = options.time;
// @ts-ignore
- const minor = timeOpts.unit || determineUnitForAutoTicks(timeOpts.minUnit, min, max, me._getLabelCapacity(min));
+ const minor = timeOpts.unit || determineUnitForAutoTicks(timeOpts.minUnit, min, max, this._getLabelCapacity(min));
const stepSize = valueOrDefault(timeOpts.stepSize, 1);
const weekday = minor === 'week' ? timeOpts.isoWeekday : false;
const hasWeekday = isNumber(weekday) || weekday === true;
throw new Error(min + ' and ' + max + ' are too far apart with stepSize of ' + stepSize + ' ' + minor);
}
- const timestamps = options.ticks.source === 'data' && me.getDataTimestamps();
+ const timestamps = options.ticks.source === 'data' && this.getDataTimestamps();
for (time = first, count = 0; time < max; time = +adapter.add(time, stepSize, minor), count++) {
addTick(ticks, time, timestamps);
}
* @return {string}
*/
getLabelForValue(value) {
- const me = this;
- const adapter = me._adapter;
- const timeOpts = me.options.time;
+ const adapter = this._adapter;
+ const timeOpts = this.options.time;
if (timeOpts.tooltipFormat) {
return adapter.format(value, timeOpts.tooltipFormat);
* @private
*/
_tickFormatFunction(time, index, ticks, format) {
- const me = this;
- const options = me.options;
+ const options = this.options;
const formats = options.time.displayFormats;
- const unit = me._unit;
- const majorUnit = me._majorUnit;
+ const unit = this._unit;
+ const majorUnit = this._majorUnit;
const minorFormat = unit && formats[unit];
const majorFormat = majorUnit && formats[majorUnit];
const tick = ticks[index];
const major = majorUnit && majorFormat && tick && tick.major;
- const label = me._adapter.format(time, format || (major ? majorFormat : minorFormat));
+ const label = this._adapter.format(time, format || (major ? majorFormat : minorFormat));
const formatter = options.ticks.callback;
- return formatter ? call(formatter, [label, index, ticks], me) : label;
+ return formatter ? call(formatter, [label, index, ticks], this) : label;
}
/**
* @return {number}
*/
getDecimalForValue(value) {
- const me = this;
- return value === null ? NaN : (value - me.min) / (me.max - me.min);
+ return value === null ? NaN : (value - this.min) / (this.max - this.min);
}
/**
* @return {number}
*/
getPixelForValue(value) {
- const me = this;
- const offsets = me._offsets;
- const pos = me.getDecimalForValue(value);
- return me.getPixelForDecimal((offsets.start + pos) * offsets.factor);
+ const offsets = this._offsets;
+ const pos = this.getDecimalForValue(value);
+ return this.getPixelForDecimal((offsets.start + pos) * offsets.factor);
}
/**
* @return {number}
*/
getValueForPixel(pixel) {
- const me = this;
- const offsets = me._offsets;
- const pos = me.getDecimalForPixel(pixel) / offsets.factor - offsets.end;
- return me.min + pos * (me.max - me.min);
+ const offsets = this._offsets;
+ const pos = this.getDecimalForPixel(pixel) / offsets.factor - offsets.end;
+ return this.min + pos * (this.max - this.min);
}
/**
* @private
*/
_getLabelSize(label) {
- const me = this;
- const ticksOpts = me.options.ticks;
- const tickLabelWidth = me.ctx.measureText(label).width;
- const angle = toRadians(me.isHorizontal() ? ticksOpts.maxRotation : ticksOpts.minRotation);
+ const ticksOpts = this.options.ticks;
+ const tickLabelWidth = this.ctx.measureText(label).width;
+ const angle = toRadians(this.isHorizontal() ? ticksOpts.maxRotation : ticksOpts.minRotation);
const cosRotation = Math.cos(angle);
const sinRotation = Math.sin(angle);
- const tickFontSize = me._resolveTickFontOptions(0).size;
+ const tickFontSize = this._resolveTickFontOptions(0).size;
return {
w: (tickLabelWidth * cosRotation) + (tickFontSize * sinRotation),
* @private
*/
_getLabelCapacity(exampleTime) {
- const me = this;
- const timeOpts = me.options.time;
+ const timeOpts = this.options.time;
const displayFormats = timeOpts.displayFormats;
// pick the longest format (milliseconds) for guestimation
const format = displayFormats[timeOpts.unit] || displayFormats.millisecond;
- const exampleLabel = me._tickFormatFunction(exampleTime, 0, ticksFromTimestamps(me, [exampleTime], me._majorUnit), format);
- const size = me._getLabelSize(exampleLabel);
+ const exampleLabel = this._tickFormatFunction(exampleTime, 0, ticksFromTimestamps(this, [exampleTime], this._majorUnit), format);
+ const size = this._getLabelSize(exampleLabel);
// subtract 1 - if offset then there's one less label than tick
// if not offset then one half label padding is added to each end leaving room for one less label
- const capacity = Math.floor(me.isHorizontal() ? me.width / size.w : me.height / size.h) - 1;
+ const capacity = Math.floor(this.isHorizontal() ? this.width / size.w : this.height / size.h) - 1;
return capacity > 0 ? capacity : 1;
}
* @protected
*/
getDataTimestamps() {
- const me = this;
- let timestamps = me._cache.data || [];
+ let timestamps = this._cache.data || [];
let i, ilen;
if (timestamps.length) {
return timestamps;
}
- const metas = me.getMatchingVisibleMetas();
+ const metas = this.getMatchingVisibleMetas();
- if (me._normalized && metas.length) {
- return (me._cache.data = metas[0].controller.getAllParsedValues(me));
+ if (this._normalized && metas.length) {
+ return (this._cache.data = metas[0].controller.getAllParsedValues(this));
}
for (i = 0, ilen = metas.length; i < ilen; ++i) {
- timestamps = timestamps.concat(metas[i].controller.getAllParsedValues(me));
+ timestamps = timestamps.concat(metas[i].controller.getAllParsedValues(this));
}
- return (me._cache.data = me.normalize(timestamps));
+ return (this._cache.data = this.normalize(timestamps));
}
/**
* @protected
*/
getLabelTimestamps() {
- const me = this;
- const timestamps = me._cache.labels || [];
+ const timestamps = this._cache.labels || [];
let i, ilen;
if (timestamps.length) {
return timestamps;
}
- const labels = me.getLabels();
+ const labels = this.getLabels();
for (i = 0, ilen = labels.length; i < ilen; ++i) {
- timestamps.push(parse(me, labels[i]));
+ timestamps.push(parse(this, labels[i]));
}
- return (me._cache.labels = me._normalized ? timestamps : me.normalize(timestamps));
+ return (this._cache.labels = this._normalized ? timestamps : this.normalize(timestamps));
}
/**
* @protected
*/
initOffsets() {
- const me = this;
- const timestamps = me._getTimestampsForTable();
- const table = me._table = me.buildLookupTable(timestamps);
- me._minPos = interpolate(table, me.min);
- me._tableRange = interpolate(table, me.max) - me._minPos;
+ const timestamps = this._getTimestampsForTable();
+ const table = this._table = this.buildLookupTable(timestamps);
+ this._minPos = interpolate(table, this.min);
+ this._tableRange = interpolate(table, this.max) - this._minPos;
super.initOffsets(timestamps);
}
* @private
*/
_getTimestampsForTable() {
- const me = this;
- let timestamps = me._cache.all || [];
+ let timestamps = this._cache.all || [];
if (timestamps.length) {
return timestamps;
}
- const data = me.getDataTimestamps();
- const label = me.getLabelTimestamps();
+ const data = this.getDataTimestamps();
+ const label = this.getLabelTimestamps();
if (data.length && label.length) {
// If combining labels and data (data might not contain all labels),
// we need to recheck uniqueness and sort
- timestamps = me.normalize(data.concat(label));
+ timestamps = this.normalize(data.concat(label));
} else {
timestamps = data.length ? data : label;
}
- timestamps = me._cache.all = timestamps;
+ timestamps = this._cache.all = timestamps;
return timestamps;
}
* @return {number}
*/
getValueForPixel(pixel) {
- const me = this;
- const offsets = me._offsets;
- const decimal = me.getDecimalForPixel(pixel) / offsets.factor - offsets.end;
- return interpolate(me._table, decimal * me._tableRange + me._minPos, true);
+ const offsets = this._offsets;
+ const decimal = this.getDecimalForPixel(pixel) / offsets.factor - offsets.end;
+ return interpolate(this._table, decimal * this._tableRange + this._minPos, true);
}
}