diff --git a/src/controllers/controller.bar.js b/src/controllers/controller.bar.js index a146310672e..c9a8e7ef813 100644 --- a/src/controllers/controller.bar.js +++ b/src/controllers/controller.bar.js @@ -310,10 +310,9 @@ export default class BarController extends DatasetController { * @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 + ']' @@ -326,39 +325,35 @@ export default class BarController extends DatasetController { } 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 = { @@ -372,10 +367,10 @@ export default class BarController extends DatasetController { }; 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); } } @@ -387,10 +382,9 @@ export default class BarController extends DatasetController { * @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 = []; @@ -468,15 +462,14 @@ export default class BarController extends DatasetController { * @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; @@ -487,7 +480,7 @@ export default class BarController extends DatasetController { 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 @@ -500,15 +493,14 @@ export default class BarController extends DatasetController { * @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) { @@ -529,7 +521,7 @@ export default class BarController extends DatasetController { 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 @@ -564,24 +556,23 @@ export default class BarController extends DatasetController { * @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); } @@ -594,16 +585,15 @@ export default class BarController extends DatasetController { } 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); } } } diff --git a/src/controllers/controller.bubble.js b/src/controllers/controller.bubble.js index 55873dafe75..eb770260c3d 100644 --- a/src/controllers/controller.bubble.js +++ b/src/controllers/controller.bubble.js @@ -44,10 +44,9 @@ export default class BubbleController extends DatasetController { * @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; @@ -59,26 +58,24 @@ export default class BubbleController extends DatasetController { } 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]); @@ -86,17 +83,17 @@ export default class BubbleController extends DatasetController { 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); } /** diff --git a/src/controllers/controller.doughnut.js b/src/controllers/controller.doughnut.js index 0581fdad99e..3e0da333598 100644 --- a/src/controllers/controller.doughnut.js +++ b/src/controllers/controller.doughnut.js @@ -94,11 +94,9 @@ export default class DoughnutController extends DatasetController { 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(); @@ -117,80 +115,77 @@ export default class DoughnutController extends DatasetController { * @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, @@ -198,13 +193,13 @@ export default class DoughnutController extends DatasetController { 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() { @@ -232,9 +227,8 @@ export default class DoughnutController extends DatasetController { } 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); @@ -245,9 +239,8 @@ export default class DoughnutController extends DatasetController { } getMaxBorderWidth(arcs) { - const me = this; let max = 0; - const chart = me.chart; + const chart = this.chart; let i, ilen, meta, controller, options; if (!arcs) { @@ -257,7 +250,7 @@ export default class DoughnutController extends DatasetController { meta = chart.getDatasetMeta(i); arcs = meta.data; controller = meta.controller; - if (controller !== me) { + if (controller !== this) { controller.configure(); } break; diff --git a/src/controllers/controller.line.js b/src/controllers/controller.line.js index 9b6a505fe0b..970cc837924 100644 --- a/src/controllers/controller.line.js +++ b/src/controllers/controller.line.js @@ -11,15 +11,14 @@ export default class LineController extends DatasetController { } 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; @@ -27,78 +26,76 @@ export default class LineController extends DatasetController { } // 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; } diff --git a/src/controllers/controller.polarArea.js b/src/controllers/controller.polarArea.js index 8a9a1b91e2d..84a9568a4c1 100644 --- a/src/controllers/controller.polarArea.js +++ b/src/controllers/controller.polarArea.js @@ -12,9 +12,8 @@ export default class PolarAreaController extends DatasetController { } 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); @@ -35,8 +34,7 @@ export default class PolarAreaController extends DatasetController { * @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); @@ -45,33 +43,32 @@ export default class PolarAreaController extends DatasetController { 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; @@ -91,10 +88,10 @@ export default class PolarAreaController extends DatasetController { 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); } } diff --git a/src/controllers/controller.radar.js b/src/controllers/controller.radar.js index e8f037c5184..36d53b03016 100644 --- a/src/controllers/controller.radar.js +++ b/src/controllers/controller.radar.js @@ -6,9 +6,8 @@ export default class RadarController extends DatasetController { * @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], @@ -17,8 +16,7 @@ export default class RadarController extends DatasetController { } 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(); @@ -27,8 +25,8 @@ export default class RadarController extends DatasetController { 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; } @@ -38,22 +36,21 @@ export default class RadarController extends DatasetController { 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; @@ -67,7 +64,7 @@ export default class RadarController extends DatasetController { options }; - me.updateElement(point, i, properties, mode); + this.updateElement(point, i, properties, mode); } } } diff --git a/src/core/core.animation.js b/src/core/core.animation.js index 853ba97c5a8..76f726a8e78 100644 --- a/src/core/core.animation.js +++ b/src/core/core.animation.js @@ -44,60 +44,57 @@ export default class Animation { } 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() { diff --git a/src/core/core.animator.js b/src/core/core.animator.js index aab04e01881..59703669292 100644 --- a/src/core/core.animator.js +++ b/src/core/core.animator.js @@ -36,19 +36,17 @@ export class Animator { * @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(); } }); } @@ -57,10 +55,9 @@ export class Animator { * @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; } @@ -90,22 +87,22 @@ export class Animator { 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; } } diff --git a/src/core/core.controller.js b/src/core/core.controller.js index e019bb7f67f..c5b77a0f989 100644 --- a/src/core/core.controller.js +++ b/src/core/core.controller.js @@ -73,8 +73,6 @@ class Chart { // 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); @@ -85,11 +83,11 @@ class Chart { ); } - 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; @@ -126,7 +124,7 @@ class Chart { 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 @@ -137,12 +135,12 @@ class Chart { 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(); } } @@ -182,23 +180,21 @@ class Chart { * @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() { @@ -225,29 +221,28 @@ class Chart { } _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(); } } } @@ -265,10 +260,9 @@ class Chart { * 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; @@ -310,8 +304,8 @@ class Chart { scale = new scaleClass({ id, type: scaleType, - ctx: me.ctx, - chart: me + ctx: this.ctx, + chart: this }); scales[scale.id] = scale; } @@ -326,8 +320,8 @@ class Chart { }); each(scales, (scale) => { - layouts.configure(me, scale, scale.options); - layouts.addBox(me, scale); + layouts.configure(this, scale, scale.options); + layouts.addBox(this, scale); }); } @@ -335,60 +329,57 @@ class Chart { * @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); @@ -400,12 +391,12 @@ class Chart { 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; } @@ -414,10 +405,9 @@ class Chart { * @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); } /** @@ -429,55 +419,54 @@ class Chart { } 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) { @@ -488,19 +477,19 @@ class Chart { }); } - 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(); } /** @@ -509,19 +498,17 @@ class Chart { * @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; @@ -532,14 +519,14 @@ class Chart { 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'); } /** @@ -548,18 +535,17 @@ class Chart { * @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}); } /** @@ -568,78 +554,74 @@ class Chart { * @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; @@ -667,18 +649,16 @@ class Chart { * @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'); } /** @@ -687,27 +667,26 @@ class Chart { * @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 }); } @@ -718,7 +697,7 @@ class Chart { } args.cancelable = false; - me.notifyPlugins('afterDatasetDraw', args); + this.notifyPlugins('afterDatasetDraw', args); } getElementsAtEventForMode(e, mode, options, useFinalPosition) { @@ -731,9 +710,8 @@ class Chart { } 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) { @@ -795,19 +773,18 @@ class Chart { * @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); } } @@ -823,44 +800,41 @@ class Chart { * @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) { @@ -883,49 +857,47 @@ class Chart { * @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); } }; @@ -933,26 +905,26 @@ class Chart { 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(); @@ -963,17 +935,15 @@ class Chart { * @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) { @@ -1007,10 +977,9 @@ class Chart { * @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); } @@ -1024,8 +993,8 @@ class Chart { const changed = !_elementsEqual(active, lastActive); if (changed) { - me._active = active; - me._updateHoverStyles(active, lastActive); + this._active = active; + this._updateHoverStyles(active, lastActive); } } @@ -1046,18 +1015,17 @@ class Chart { * @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); } } @@ -1065,24 +1033,23 @@ class Chart { * @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; } /** @@ -1093,8 +1060,7 @@ class Chart { * @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. @@ -1118,29 +1084,29 @@ class Chart { // 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; } diff --git a/src/core/core.datasetController.js b/src/core/core.datasetController.js index 05919714bff..584aeda027e 100644 --- a/src/core/core.datasetController.js +++ b/src/core/core.datasetController.js @@ -242,12 +242,11 @@ export default class DatasetController { } 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) { @@ -258,10 +257,9 @@ export default class DatasetController { } 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; @@ -271,11 +269,11 @@ export default class DatasetController { 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() { @@ -325,52 +323,49 @@ export default class DatasetController { * @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; @@ -386,11 +381,11 @@ export default class DatasetController { // 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); } } @@ -399,12 +394,11 @@ export default class DatasetController { * @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; } /** @@ -412,8 +406,7 @@ export default class DatasetController { * @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; @@ -421,17 +414,17 @@ export default class DatasetController { 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]); @@ -448,7 +441,7 @@ export default class DatasetController { } if (_stacked) { - updateStacks(me, parsed); + updateStacks(this, parsed); } } @@ -588,13 +581,12 @@ export default class DatasetController { * @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; @@ -610,7 +602,7 @@ export default class DatasetController { 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; @@ -622,7 +614,7 @@ export default class DatasetController { if (_skip()) { continue; } - me.updateRangeFromParsed(range, scale, parsed, stack); + this.updateRangeFromParsed(range, scale, parsed, stack); break; } } @@ -655,11 +647,10 @@ export default class DatasetController { * @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]) : '' @@ -670,12 +661,11 @@ export default class DatasetController { * @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()))); } /** @@ -684,15 +674,14 @@ export default class DatasetController { 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) { @@ -734,21 +723,20 @@ export default class DatasetController { * @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; @@ -777,23 +765,22 @@ export default class DatasetController { * @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) { @@ -815,9 +802,8 @@ export default class DatasetController { * @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) { @@ -825,10 +811,10 @@ export default class DatasetController { } 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) { @@ -925,15 +911,14 @@ export default class DatasetController { * @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; @@ -944,13 +929,13 @@ export default class DatasetController { // 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); } } @@ -958,8 +943,7 @@ export default class DatasetController { * @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; @@ -973,16 +957,16 @@ export default class DatasetController { 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'); } } @@ -992,9 +976,8 @@ export default class DatasetController { * @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); diff --git a/src/core/core.element.js b/src/core/core.element.js index dc119dfcda3..0a2934fa2a4 100644 --- a/src/core/core.element.js +++ b/src/core/core.element.js @@ -29,15 +29,14 @@ export default class Element { * @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; } diff --git a/src/core/core.plugins.js b/src/core/core.plugins.js index 29f98cf291f..480f4239133 100644 --- a/src/core/core.plugins.js +++ b/src/core/core.plugins.js @@ -33,19 +33,17 @@ export default class PluginService { * @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; } diff --git a/src/core/core.registry.js b/src/core/core.registry.js index b1d8f4d5400..157d3d2aa6a 100644 --- a/src/core/core.registry.js +++ b/src/core/core.registry.js @@ -122,11 +122,10 @@ export class Registry { * @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: @@ -139,8 +138,8 @@ export class Registry { // 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); }); } }); diff --git a/src/core/core.scale.js b/src/core/core.scale.js index dd8e1bfd27b..1858078468c 100644 --- a/src/core/core.scale.js +++ b/src/core/core.scale.js @@ -257,16 +257,15 @@ export default class Scale extends Element { * @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); } /** @@ -305,18 +304,17 @@ export default class Scale extends Element { * @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); } @@ -337,12 +335,11 @@ export default class Scale extends Element { * @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 }; } @@ -386,111 +383,109 @@ export default class Scale extends Element { * - 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() { @@ -503,35 +498,33 @@ export default class Scale extends Element { 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 @@ -565,12 +558,11 @@ export default class Scale extends Element { * @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() { @@ -583,34 +575,33 @@ export default class Scale extends Element { 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)), @@ -619,7 +610,7 @@ export default class Scale extends Element { labelRotation = Math.max(minRotation, Math.min(maxRotation, labelRotation)); } - me.labelRotation = labelRotation; + this.labelRotation = labelRotation; } afterCalculateLabelRotation() { call(this.options.afterCalculateLabelRotation, [this]); @@ -631,70 +622,68 @@ export default class Scale extends Element { 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; @@ -718,8 +707,8 @@ export default class Scale extends Element { } // 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; @@ -732,8 +721,8 @@ export default class Scale extends Element { paddingBottom = 0; } - me.paddingTop = paddingTop + padding; - me.paddingBottom = paddingBottom + padding; + this.paddingTop = paddingTop + padding; + this.paddingBottom = paddingBottom + padding; } } @@ -742,12 +731,11 @@ export default class Scale extends Element { * @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); } } @@ -775,11 +763,9 @@ export default class Scale extends Element { * @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; @@ -791,7 +777,7 @@ export default class Scale extends Element { } } - me.afterTickToLabelConversion(); + this.afterTickToLabelConversion(); } /** @@ -799,17 +785,16 @@ export default class Scale extends Element { * @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; @@ -922,14 +907,12 @@ export default class Scale extends Element { * @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); } /** @@ -965,16 +948,15 @@ export default class Scale extends Element { * @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)); } /** @@ -982,21 +964,20 @@ export default class Scale extends Element { * @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; } @@ -1019,19 +1000,18 @@ export default class Scale extends Element { * @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) { @@ -1041,36 +1021,36 @@ export default class Scale extends Element { 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; @@ -1083,7 +1063,7 @@ export default class Scale extends Element { } 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; @@ -1095,7 +1075,7 @@ export default class Scale extends Element { 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; @@ -1107,7 +1087,7 @@ export default class Scale extends Element { 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) { @@ -1142,8 +1122,8 @@ export default class Scale extends Element { }); } - me._ticksLength = ticksLength; - me._borderValue = borderValue; + this._ticksLength = ticksLength; + this._borderValue = borderValue; return items; } @@ -1152,33 +1132,32 @@ export default class Scale extends Element { * @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') { @@ -1187,18 +1166,18 @@ export default class Scale extends Element { } 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') { @@ -1209,14 +1188,14 @@ export default class Scale extends Element { } } - 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; @@ -1313,9 +1292,8 @@ export default class Scale extends Element { } _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'; @@ -1333,9 +1311,8 @@ export default class Scale extends Element { } _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; @@ -1344,7 +1321,7 @@ export default class Scale extends Element { if (position === 'left') { if (mirror) { - x = me.right + padding; + x = this.right + padding; if (crossAlign === 'near') { textAlign = 'left'; @@ -1356,7 +1333,7 @@ export default class Scale extends Element { x += widest; } } else { - x = me.right - tickAndPadding; + x = this.right - tickAndPadding; if (crossAlign === 'near') { textAlign = 'right'; @@ -1365,12 +1342,12 @@ export default class Scale extends Element { 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'; @@ -1382,7 +1359,7 @@ export default class Scale extends Element { x -= widest; } } else { - x = me.left + tickAndPadding; + x = this.left + tickAndPadding; if (crossAlign === 'near') { textAlign = 'left'; @@ -1391,7 +1368,7 @@ export default class Scale extends Element { x += widest / 2; } else { textAlign = 'right'; - x = me.right; + x = this.right; } } } else { @@ -1405,19 +1382,17 @@ export default class Scale extends Element { * @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}; } } @@ -1435,15 +1410,14 @@ export default class Scale extends Element { } 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; @@ -1453,10 +1427,9 @@ export default class Scale extends Element { * @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) => { @@ -1508,24 +1481,23 @@ export default class Scale extends Element { * @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(); @@ -1544,21 +1516,20 @@ export default class Scale extends Element { * @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) { @@ -1617,17 +1588,15 @@ export default class Scale extends Element { } 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); } /** @@ -1635,37 +1604,36 @@ export default class Scale extends Element { * @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); } }]; } @@ -1676,15 +1644,14 @@ export default class Scale extends Element { * @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); } } @@ -1705,8 +1672,7 @@ export default class Scale extends Element { * @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; } } diff --git a/src/core/core.typedRegistry.js b/src/core/core.typedRegistry.js index 0439faf2d7f..8e6eaa87358 100644 --- a/src/core/core.typedRegistry.js +++ b/src/core/core.typedRegistry.js @@ -22,18 +22,17 @@ export default class TypedRegistry { * @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); @@ -46,7 +45,7 @@ export default class TypedRegistry { items[id] = item; registerDefaults(item, scope, parentScope); - if (me.override) { + if (this.override) { defaults.override(item.id, item.overrides); } diff --git a/src/elements/element.arc.js b/src/elements/element.arc.js index 918128cdffc..5c2182fb88e 100644 --- a/src/elements/element.arc.js +++ b/src/elements/element.arc.js @@ -318,14 +318,13 @@ export default class ArcElement extends Element { } 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; } @@ -334,9 +333,9 @@ export default class ArcElement extends Element { 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; } } @@ -344,8 +343,8 @@ export default class ArcElement extends Element { 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(); } diff --git a/src/elements/element.line.js b/src/elements/element.line.js index 87eb9f583b6..9ad022dcb1f 100644 --- a/src/elements/element.line.js +++ b/src/elements/element.line.js @@ -259,21 +259,19 @@ export default class LineElement extends Element { } 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() { @@ -313,11 +311,10 @@ export default class LineElement extends Element { * @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; @@ -369,16 +366,15 @@ export default class LineElement extends Element { * @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; } @@ -391,22 +387,21 @@ export default class LineElement extends Element { * @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; } } } diff --git a/src/elements/element.point.js b/src/elements/element.point.js index 05b521910f4..26f73623f4a 100644 --- a/src/elements/element.point.js +++ b/src/elements/element.point.js @@ -51,17 +51,16 @@ export default class PointElement extends Element { } 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() { diff --git a/src/plugins/plugin.legend.js b/src/plugins/plugin.legend.js index 87108b8815f..ccd31800a67 100644 --- a/src/plugins/plugin.legend.js +++ b/src/plugins/plugin.legend.js @@ -72,95 +72,88 @@ export class Legend extends Element { } 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; @@ -169,7 +162,7 @@ export class Legend extends Element { 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) { @@ -188,10 +181,9 @@ export class Legend extends Element { } _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; @@ -201,7 +193,7 @@ export class Legend extends Element { 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 @@ -228,35 +220,34 @@ export class Legend extends Element { } 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; } @@ -268,12 +259,11 @@ export class Legend extends Element { } 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); } @@ -283,18 +273,17 @@ export class Legend extends Element { * @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'); @@ -375,26 +364,26 @@ export class Legend extends Element { }; // 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 @@ -405,25 +394,25 @@ export class Legend extends Element { 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); @@ -435,15 +424,14 @@ export class Legend extends Element { } }); - 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); @@ -452,8 +440,8 @@ export class Legend extends Element { 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; @@ -461,18 +449,18 @@ export class Legend extends Element { // 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 @@ -503,18 +491,17 @@ export class Legend extends Element { * @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]; } } } @@ -527,29 +514,28 @@ export class Legend extends Element { * @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); } } } diff --git a/src/plugins/plugin.title.js b/src/plugins/plugin.title.js index f55abdfbe7b..5b5158b66cf 100644 --- a/src/plugins/plugin.title.js +++ b/src/plugins/plugin.title.js @@ -27,28 +27,27 @@ export class Title extends Element { } 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; } } @@ -83,9 +82,8 @@ export class Title extends Element { } draw() { - const me = this; - const ctx = me.ctx; - const opts = me.options; + const ctx = this.ctx; + const opts = this.options; if (!opts.display) { return; @@ -93,8 +91,8 @@ export class Title extends Element { 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, diff --git a/src/plugins/plugin.tooltip.js b/src/plugins/plugin.tooltip.js index f932cb15fbf..cdf4734ec3c 100644 --- a/src/plugins/plugin.tooltip.js +++ b/src/plugins/plugin.tooltip.js @@ -392,19 +392,18 @@ export class Tooltip extends Element { * @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; @@ -414,18 +413,16 @@ export class Tooltip extends Element { * @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)); @@ -440,7 +437,6 @@ export class Tooltip extends Element { } getBody(tooltipItems, options) { - const me = this; const {callbacks} = options; const bodyItems = []; @@ -451,9 +447,9 @@ export class Tooltip extends Element { 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); }); @@ -467,12 +463,11 @@ export class Tooltip extends Element { // 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)); @@ -486,9 +481,8 @@ export class Tooltip extends Element { * @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 = []; @@ -496,7 +490,7 @@ export class Tooltip extends Element { 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 @@ -512,48 +506,47 @@ export class Tooltip extends Element { // 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, @@ -566,15 +559,15 @@ export class Tooltip extends Element { }; } - 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}); } } @@ -644,15 +637,14 @@ export class Tooltip extends Element { } 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'; @@ -678,12 +670,11 @@ export class Tooltip extends Element { * @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; @@ -757,18 +748,17 @@ export class Tooltip extends Element { } // 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); @@ -782,11 +772,11 @@ export class Tooltip extends Element { 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) @@ -795,7 +785,7 @@ export class Tooltip extends Element { // 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); @@ -803,7 +793,7 @@ export class Tooltip extends Element { 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); } @@ -821,20 +811,19 @@ export class Tooltip extends Element { 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); @@ -898,50 +887,48 @@ export class Tooltip extends Element { * @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 @@ -950,27 +937,27 @@ export class Tooltip extends Element { 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); @@ -992,10 +979,9 @@ export class Tooltip extends Element { * @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); @@ -1008,12 +994,12 @@ export class Tooltip extends Element { }; }); 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); } } @@ -1024,15 +1010,14 @@ export class Tooltip extends Element { * @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(); } @@ -1041,22 +1026,22 @@ export class Tooltip extends Element { // 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); } } diff --git a/src/scales/scale.category.js b/src/scales/scale.category.js index 28f57b082c9..681e07e8e72 100644 --- a/src/scales/scale.category.js +++ b/src/scales/scale.category.js @@ -37,36 +37,34 @@ export default class CategoryScale extends Scale { } 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}); @@ -75,8 +73,7 @@ export default class CategoryScale extends Scale { } getLabelForValue(value) { - const me = this; - const labels = me.getLabels(); + const labels = this.getLabels(); if (value >= 0 && value < labels.length) { return labels[value]; @@ -88,41 +85,35 @@ export default class CategoryScale extends Scale { * @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() { diff --git a/src/scales/scale.linear.js b/src/scales/scale.linear.js index d29772772b8..362d088cff1 100644 --- a/src/scales/scale.linear.js +++ b/src/scales/scale.linear.js @@ -6,14 +6,13 @@ import {toRadians} from '../helpers'; 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(); } /** @@ -21,12 +20,11 @@ export default class LinearScale extends LinearScaleBase { * @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)); } diff --git a/src/scales/scale.linearbase.js b/src/scales/scale.linearbase.js index f7a0d02c590..dc00265ee19 100644 --- a/src/scales/scale.linearbase.js +++ b/src/scales/scale.linearbase.js @@ -175,10 +175,9 @@ export default class LinearScaleBase extends Scale { } 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); @@ -211,21 +210,20 @@ export default class LinearScaleBase extends Scale { 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; } @@ -244,15 +242,14 @@ export default class LinearScaleBase extends Scale { } 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 = { @@ -263,28 +260,28 @@ export default class LinearScaleBase extends Scale { 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; @@ -294,21 +291,20 @@ export default class LinearScaleBase extends Scale { * @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) { diff --git a/src/scales/scale.logarithmic.js b/src/scales/scale.logarithmic.js index 99e83241485..ba7f5237f26 100644 --- a/src/scales/scale.logarithmic.js +++ b/src/scales/scale.logarithmic.js @@ -68,24 +68,22 @@ export default class LogarithmicScale extends Scale { } 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); @@ -108,37 +106,36 @@ export default class LogarithmicScale extends Scale { } // 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; @@ -156,32 +153,29 @@ export default class LogarithmicScale extends Scale { * @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); } } diff --git a/src/scales/scale.radialLinear.js b/src/scales/scale.radialLinear.js index 93b5a64bd8a..8ad7e8b23c2 100644 --- a/src/scales/scale.radialLinear.js +++ b/src/scales/scale.radialLinear.js @@ -289,26 +289,23 @@ export default class RadialLinearScale extends LinearScaleBase { } 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(); } /** @@ -320,25 +317,22 @@ export default class RadialLinearScale extends LinearScaleBase { } 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); } } @@ -347,32 +341,30 @@ export default class RadialLinearScale extends LinearScaleBase { * @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) { @@ -382,18 +374,16 @@ export default class RadialLinearScale extends LinearScaleBase { } 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) { @@ -401,27 +391,24 @@ export default class RadialLinearScale extends LinearScaleBase { 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 }; } @@ -448,13 +435,12 @@ export default class RadialLinearScale extends LinearScaleBase { * @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(); @@ -466,24 +452,23 @@ export default class RadialLinearScale extends LinearScaleBase { * @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); } }); } @@ -491,8 +476,8 @@ export default class RadialLinearScale extends LinearScaleBase { 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) { @@ -505,10 +490,10 @@ export default class RadialLinearScale extends LinearScaleBase { 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(); } @@ -526,32 +511,31 @@ export default class RadialLinearScale extends LinearScaleBase { * @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; diff --git a/src/scales/scale.time.js b/src/scales/scale.time.js index 18da79aa459..6397c18efef 100644 --- a/src/scales/scale.time.js +++ b/src/scales/scale.time.js @@ -262,12 +262,11 @@ export default class TimeScale extends Scale { } 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 @@ -284,12 +283,12 @@ export default class TimeScale extends Scale { // 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)); } } @@ -297,8 +296,8 @@ export default class TimeScale extends Scale { 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); } /** @@ -320,37 +319,36 @@ export default class TimeScale extends Scale { * @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); } /** @@ -363,30 +361,29 @@ export default class TimeScale extends Scale { * @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)}; } /** @@ -397,14 +394,13 @@ export default class TimeScale extends Scale { * @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; @@ -425,7 +421,7 @@ export default class TimeScale extends Scale { 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); } @@ -443,9 +439,8 @@ export default class TimeScale extends Scale { * @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); @@ -463,18 +458,17 @@ export default class TimeScale extends Scale { * @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; } /** @@ -494,8 +488,7 @@ export default class TimeScale extends Scale { * @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); } /** @@ -503,10 +496,9 @@ export default class TimeScale extends Scale { * @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); } /** @@ -514,10 +506,9 @@ export default class TimeScale extends Scale { * @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); } /** @@ -526,13 +517,12 @@ export default class TimeScale extends Scale { * @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), @@ -546,17 +536,16 @@ export default class TimeScale extends Scale { * @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; } @@ -564,45 +553,43 @@ export default class TimeScale extends Scale { * @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)); } /** diff --git a/src/scales/scale.timeseries.js b/src/scales/scale.timeseries.js index e42d87817a5..f14d409583b 100644 --- a/src/scales/scale.timeseries.js +++ b/src/scales/scale.timeseries.js @@ -51,11 +51,10 @@ class TimeSeriesScale extends TimeScale { * @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); } @@ -110,23 +109,22 @@ class TimeSeriesScale extends TimeScale { * @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; } @@ -144,10 +142,9 @@ class TimeSeriesScale extends TimeScale { * @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); } }