From 99811328dca10cd2ba310fa3877266bddc84da25 Mon Sep 17 00:00:00 2001 From: Ben McCann <322311+benmccann@users.noreply.github.com> Date: Thu, 31 Oct 2019 15:45:13 -0700 Subject: [PATCH] Make all ticks objects (#6645) Make all ticks object --- .eslintrc.yml | 3 + docs/axes/README.md | 2 +- docs/getting-started/v3-migration.md | 12 ++ samples/scales/time/financial.html | 4 +- src/core/core.helpers.js | 26 ++-- src/core/core.scale.js | 91 ++++---------- src/core/core.ticks.js | 4 +- src/scales/scale.category.js | 5 +- src/scales/scale.linear.js | 18 +-- src/scales/scale.linearbase.js | 30 ++--- src/scales/scale.logarithmic.js | 25 ++-- src/scales/scale.radialLinear.js | 16 +-- src/scales/scale.time.js | 10 +- test/specs/core.layouts.tests.js | 6 +- test/specs/core.scale.tests.js | 45 ++----- test/specs/core.ticks.tests.js | 20 +-- test/specs/scale.category.tests.js | 22 ++-- test/specs/scale.linear.tests.js | 41 ++++--- test/specs/scale.logarithmic.tests.js | 50 ++++---- test/specs/scale.radialLinear.tests.js | 26 ++-- test/specs/scale.time.tests.js | 164 +++++++++++++------------ 21 files changed, 300 insertions(+), 320 deletions(-) diff --git a/.eslintrc.yml b/.eslintrc.yml index b0d9d5695..ea06e34fd 100644 --- a/.eslintrc.yml +++ b/.eslintrc.yml @@ -4,4 +4,7 @@ env: browser: true node: true +parserOptions: + ecmaVersion: 6 + plugins: ['html'] diff --git a/docs/axes/README.md b/docs/axes/README.md index 4c79922d7..e400f2a76 100644 --- a/docs/axes/README.md +++ b/docs/axes/README.md @@ -31,7 +31,7 @@ There are a number of config callbacks that can be used to change parameters in | `beforeDataLimits` | `axis` | Callback that runs before data limits are determined. | `afterDataLimits` | `axis` | Callback that runs after data limits are determined. | `beforeBuildTicks` | `axis` | Callback that runs before ticks are created. -| `afterBuildTicks` | `axis`, `ticks` | Callback that runs after ticks are created. Useful for filtering ticks. Should return the filtered ticks. +| `afterBuildTicks` | `axis` | Callback that runs after ticks are created. Useful for filtering ticks. | `beforeTickToLabelConversion` | `axis` | Callback that runs before ticks are converted into strings. | `afterTickToLabelConversion` | `axis` | Callback that runs after ticks are converted into strings. | `beforeCalculateTickRotation` | `axis` | Callback that runs before tick rotation is determined. diff --git a/docs/getting-started/v3-migration.md b/docs/getting-started/v3-migration.md index 4c0b60e09..9b9bf8f55 100644 --- a/docs/getting-started/v3-migration.md +++ b/docs/getting-started/v3-migration.md @@ -43,13 +43,18 @@ Chart.js 3.0 introduces a number of breaking changes. Chart.js 2.0 was released * `helpers.aliasPixel` * `helpers.configMerge` * `helpers.indexOf` +* `helpers.min` +* `helpers.max` * `helpers.numberOfLabelLines` * `helpers.removeEvent` * `helpers.scaleMerge` * `scale.mergeTicksOptions` +* `scale.ticksAsNumbers` * `Chart.Controller` * `Chart.chart.chart` * `Chart.types` +* Made `scale.handleDirectionalChanges` private +* Made `scale.tickValues` private ### Renamed @@ -65,6 +70,13 @@ Chart.js 3.0 introduces a number of breaking changes. Chart.js 2.0 was released ### Changed +#### Ticks + +* `scale.ticks` now contains objects instead of strings +* `buildTicks` is now expected to return tick objects +* `afterBuildTicks` now has no parameters like the other callbacks +* `convertTicksToLabels` was renamed to `generateTickLabels`. It is now expected to set the label property on the ticks given as input + #### Time Scale * `getValueForPixel` now returns milliseconds since the epoch diff --git a/samples/scales/time/financial.html b/samples/scales/time/financial.html index a402b0e95..87ba2b669 100644 --- a/samples/scales/time/financial.html +++ b/samples/scales/time/financial.html @@ -130,8 +130,9 @@ maxRotation: 0, sampleSize: 100 }, - afterBuildTicks: function(scale, ticks) { + afterBuildTicks: function(scale) { var majorUnit = scale._majorUnit; + var ticks = scale.ticks; var firstTick = ticks[0]; var i, ilen, val, tick, currMajor, lastMajor; @@ -154,7 +155,6 @@ tick.major = currMajor !== lastMajor; lastMajor = currMajor; } - return ticks; } }], yAxes: [{ diff --git a/src/core/core.helpers.js b/src/core/core.helpers.js index 39669f090..e5be621fa 100644 --- a/src/core/core.helpers.js +++ b/src/core/core.helpers.js @@ -71,21 +71,27 @@ module.exports = function() { var rounded = Math.round(x); return ((rounded - epsilon) <= x) && ((rounded + epsilon) >= x); }; - helpers.max = function(array) { - return array.reduce(function(max, value) { + helpers._setMinAndMax = function(array, target) { + var i, ilen, value; + + for (i = 0, ilen = array.length; i < ilen; i++) { + value = array[i]; if (!isNaN(value)) { - return Math.max(max, value); + target.min = Math.min(target.min, value); + target.max = Math.max(target.max, value); } - return max; - }, Number.NEGATIVE_INFINITY); + } }; - helpers.min = function(array) { - return array.reduce(function(min, value) { + helpers._setMinAndMaxByKey = function(array, target, property) { + var i, ilen, value; + + for (i = 0, ilen = array.length; i < ilen; i++) { + value = array[i][property]; if (!isNaN(value)) { - return Math.min(min, value); + target.min = Math.min(target.min, value); + target.max = Math.max(target.max, value); } - return min; - }, Number.POSITIVE_INFINITY); + } }; helpers.sign = Math.sign ? function(x) { diff --git a/src/core/core.scale.js b/src/core/core.scale.js index 20e13953f..f3521ee12 100644 --- a/src/core/core.scale.js +++ b/src/core/core.scale.js @@ -81,7 +81,7 @@ function sample(arr, numItems) { } function getPixelForGridLine(scale, index, offsetGridLines) { - var length = scale.getTicks().length; + var length = scale.ticks.length; var validIndex = Math.min(index, length - 1); var lineValue = scale.getPixelForTick(validIndex); var start = scale._startPixel; @@ -348,7 +348,7 @@ var Scale = Element.extend({ * @since 2.7 */ getTicks: function() { - return this._ticks; + return this.ticks; }, /** @@ -379,7 +379,7 @@ var Scale = Element.extend({ var me = this; var tickOpts = me.options.ticks; var sampleSize = tickOpts.sampleSize; - var i, ilen, labels, ticks, samplingEnabled; + var samplingEnabled; // Update Lifecycle - Probably don't want to ever extend or overwrite this function ;) me.beforeUpdate(); @@ -394,7 +394,6 @@ var Scale = Element.extend({ bottom: 0 }, margins); - me._ticks = null; me.ticks = null; me._labelSizes = null; me._maxLabelLines = 0; @@ -413,39 +412,17 @@ var Scale = Element.extend({ me.determineDataLimits(); me.afterDataLimits(); - // Ticks - `this.ticks` is now DEPRECATED! - // Internal ticks are now stored as objects in the PRIVATE `this._ticks` member - // and must not be accessed directly from outside this class. `this.ticks` being - // around for long time and not marked as private, we can't change its structure - // without unexpected breaking changes. If you need to access the scale ticks, - // use scale.getTicks() instead. - me.beforeBuildTicks(); - // New implementations should return an array of objects but for BACKWARD COMPAT, - // we still support no return (`this.ticks` internally set by calling this method). - ticks = me.buildTicks() || []; + me.ticks = me.buildTicks() || []; // Allow modification of ticks in callback. - ticks = me.afterBuildTicks(ticks) || ticks; - - // Ensure ticks contains ticks in new tick format - if ((!ticks || !ticks.length) && me.ticks) { - ticks = []; - for (i = 0, ilen = me.ticks.length; i < ilen; ++i) { - ticks.push({ - value: me.ticks[i], - major: false - }); - } - } - - me._ticks = ticks; + me.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 - samplingEnabled = sampleSize < ticks.length; - labels = me._convertTicksToLabels(samplingEnabled ? sample(ticks, sampleSize) : ticks); + samplingEnabled = sampleSize < me.ticks.length; + me._convertTicksToLabels(samplingEnabled ? sample(me.ticks, sampleSize) : me.ticks); // _configure is called twice, once here, once from core.controller.updateLayout. // Here we haven't been positioned yet, but dimensions are correct. @@ -463,15 +440,13 @@ var Scale = Element.extend({ me.afterFit(); // Auto-skip - me._ticksToDraw = tickOpts.display && (tickOpts.autoSkip || tickOpts.source === 'auto') ? me._autoSkip(ticks) : ticks; + me._ticksToDraw = tickOpts.display && (tickOpts.autoSkip || tickOpts.source === 'auto') ? me._autoSkip(me.ticks) : me.ticks; if (samplingEnabled) { // Generate labels using all non-skipped ticks - labels = me._convertTicksToLabels(me._ticksToDraw); + me._convertTicksToLabels(me._ticksToDraw); } - me.ticks = labels; // BACKWARD COMPATIBILITY - // IMPORTANT: after this point, we consider that `this.ticks` will NEVER change! me.afterUpdate(); @@ -553,25 +528,24 @@ var Scale = Element.extend({ helpers.callback(this.options.beforeBuildTicks, [this]); }, buildTicks: helpers.noop, - afterBuildTicks: function(ticks) { - var me = this; - // ticks is empty for old axis implementations here - if (isArray(ticks) && ticks.length) { - return helpers.callback(me.options.afterBuildTicks, [me, ticks]); - } - // Support old implementations (that modified `this.ticks` directly in buildTicks) - me.ticks = helpers.callback(me.options.afterBuildTicks, [me, me.ticks]) || me.ticks; - return ticks; + afterBuildTicks: function() { + helpers.callback(this.options.afterBuildTicks, [this]); }, beforeTickToLabelConversion: function() { helpers.callback(this.options.beforeTickToLabelConversion, [this]); }, - convertTicksToLabels: function() { + /** + * Convert ticks to label strings + */ + generateTickLabels: function(ticks) { var me = this; - // Convert ticks to strings var tickOpts = me.options.ticks; - me.ticks = me.ticks.map(tickOpts.callback, this); + var i, ilen, tick; + for (i = 0, ilen = ticks.length; i < ilen; i++) { + tick = ticks[i]; + tick.label = helpers.callback(tickOpts.callback, [tick.value, i, ticks], me); + } }, afterTickToLabelConversion: function() { helpers.callback(this.options.afterTickToLabelConversion, [this]); @@ -586,7 +560,7 @@ var Scale = Element.extend({ var me = this; var options = me.options; var tickOpts = options.ticks; - var numTicks = me.getTicks().length; + var numTicks = me.ticks.length; var minRotation = tickOpts.minRotation || 0; var maxRotation = tickOpts.maxRotation; var labelRotation = minRotation; @@ -686,7 +660,7 @@ var Scale = Element.extend({ minSize.height = Math.min(me.maxHeight, minSize.height + labelHeight + tickPadding); var offsetLeft = me.getPixelForTick(0) - me.left; - var offsetRight = me.right - me.getPixelForTick(me.getTicks().length - 1); + var offsetRight = me.right - me.getPixelForTick(me.ticks.length - 1); var paddingLeft, paddingRight; // Ensure that our ticks are always inside the canvas. When rotated, ticks are right aligned @@ -788,27 +762,12 @@ var Scale = Element.extend({ _convertTicksToLabels: function(ticks) { var me = this; - var labels, i, ilen; - - me.ticks = ticks.map(function(tick) { - return tick.value; - }); me.beforeTickToLabelConversion(); - // New implementations should return the formatted tick labels but for BACKWARD - // COMPAT, we still support no return (`this.ticks` internally changed by calling - // this method and supposed to contain only string values). - labels = me.convertTicksToLabels(ticks) || me.ticks; + me.generateTickLabels(ticks); me.afterTickToLabelConversion(); - - // BACKWARD COMPAT: synchronize `_ticks` with labels (so potentially `this.ticks`) - for (i = 0, ilen = ticks.length; i < ilen; ++i) { - ticks[i].label = labels[i]; - } - - return labels; }, /** @@ -819,7 +778,7 @@ var Scale = Element.extend({ var labelSizes = me._labelSizes; if (!labelSizes) { - me._labelSizes = labelSizes = computeLabelSizes(me.ctx, parseTickFontOptions(me.options.ticks), me.getTicks(), me.longestTextCache); + me._labelSizes = labelSizes = computeLabelSizes(me.ctx, parseTickFontOptions(me.options.ticks), me.ticks, me.longestTextCache); me.longestLabelWidth = labelSizes.widest.width; } @@ -895,7 +854,7 @@ var Scale = Element.extend({ getPixelForTick: function(index) { var me = this; var offset = me.options.offset; - var numTicks = me._ticks.length; + var numTicks = me.ticks.length; var tickWidth = 1 / Math.max(numTicks - (offset ? 0 : 1), 1); return index < 0 || index > numTicks - 1 diff --git a/src/core/core.ticks.js b/src/core/core.ticks.js index da1c14fb3..3e7a39702 100644 --- a/src/core/core.ticks.js +++ b/src/core/core.ticks.js @@ -33,7 +33,7 @@ module.exports = { */ linear: function(tickValue, index, ticks) { // If we have lots of ticks, don't use the ones - var delta = ticks.length > 3 ? ticks[2] - ticks[1] : ticks[1] - ticks[0]; + var delta = ticks.length > 3 ? ticks[2].value - ticks[1].value : ticks[1].value - ticks[0].value; // If we have a number like 2.5 as the delta, figure out how many decimal places we need if (Math.abs(delta) > 1) { @@ -47,7 +47,7 @@ module.exports = { var tickString = ''; if (tickValue !== 0) { - var maxTick = Math.max(Math.abs(ticks[0]), Math.abs(ticks[ticks.length - 1])); + var maxTick = Math.max(Math.abs(ticks[0].value), Math.abs(ticks[ticks.length - 1].value)); if (maxTick < 1e-4) { // all ticks are small numbers; use scientific notation var logTick = math.log10(Math.abs(tickValue)); var numExponential = Math.floor(logTick) - Math.floor(logDelta); diff --git a/src/scales/scale.category.js b/src/scales/scale.category.js index 29dbf6493..487f4b554 100644 --- a/src/scales/scale.category.js +++ b/src/scales/scale.category.js @@ -49,7 +49,10 @@ module.exports = Scale.extend({ var maxIndex = me.maxIndex; // If we are viewing some subset of labels, slice the original array - me.ticks = (minIndex === 0 && maxIndex === labels.length - 1) ? labels : labels.slice(minIndex, maxIndex + 1); + labels = (minIndex === 0 && maxIndex === labels.length - 1) ? labels : labels.slice(minIndex, maxIndex + 1); + return labels.map(function(l) { + return {value: l}; + }); }, getLabelForIndex: function(index, datasetIndex) { diff --git a/src/scales/scale.linear.js b/src/scales/scale.linear.js index 995f079ce..21999c2be 100644 --- a/src/scales/scale.linear.js +++ b/src/scales/scale.linear.js @@ -107,8 +107,7 @@ module.exports = LinearScaleBase.extend({ helpers.each(stacks, function(stackValues) { values = stackValues.pos.concat(stackValues.neg); - me.min = Math.min(me.min, helpers.min(values)); - me.max = Math.max(me.max, helpers.max(values)); + helpers._setMinAndMax(values, me); }); me.min = helpers.isFinite(me.min) && !isNaN(me.min) ? me.min : DEFAULT_MIN; @@ -130,12 +129,13 @@ module.exports = LinearScaleBase.extend({ return Math.ceil(me.height / tickFont.lineHeight); }, - // Called after the ticks are built. We need - handleDirectionalChanges: function() { - if (!this.isHorizontal()) { - // We are in a vertical orientation. The top value is the highest. So reverse the array - this.ticks.reverse(); - } + /** + * Called after the ticks are built + * @private + */ + _handleDirectionalChanges: function(ticks) { + // If we are in a vertical orientation the top value is the highest so reverse the array + return this.isHorizontal() ? ticks : ticks.reverse(); }, getLabelForIndex: function(index, datasetIndex) { @@ -153,7 +153,7 @@ module.exports = LinearScaleBase.extend({ }, getPixelForTick: function(index) { - var ticks = this.ticksAsNumbers; + var ticks = this._tickValues; if (index < 0 || index > ticks.length - 1) { return null; } diff --git a/src/scales/scale.linearbase.js b/src/scales/scale.linearbase.js index 95ba9bebe..b20820aaf 100644 --- a/src/scales/scale.linearbase.js +++ b/src/scales/scale.linearbase.js @@ -3,7 +3,6 @@ var helpers = require('../helpers/index'); var Scale = require('../core/core.scale'); -var noop = helpers.noop; var isNullOrUndef = helpers.isNullOrUndef; /** @@ -33,7 +32,7 @@ function generateTicks(generationOptions, dataRange) { // Beyond MIN_SPACING floating point numbers being to lose precision // such that we can't do the math necessary to generate ticks if (spacing < MIN_SPACING && isNullOrUndef(min) && isNullOrUndef(max)) { - return [rmin, rmax]; + return [{value: rmin}, {value: rmax}]; } numSpaces = Math.ceil(rmax / spacing) - Math.floor(rmin / spacing); @@ -75,11 +74,11 @@ function generateTicks(generationOptions, dataRange) { niceMin = Math.round(niceMin * factor) / factor; niceMax = Math.round(niceMax * factor) / factor; - ticks.push(isNullOrUndef(min) ? niceMin : min); + ticks.push({value: isNullOrUndef(min) ? niceMin : min}); for (var j = 1; j < numSpaces; ++j) { - ticks.push(Math.round((niceMin + j * spacing) * factor) / factor); + ticks.push({value: Math.round((niceMin + j * spacing) * factor) / factor}); } - ticks.push(isNullOrUndef(max) ? niceMax : max); + ticks.push({value: isNullOrUndef(max) ? niceMax : max}); return ticks; } @@ -184,7 +183,9 @@ module.exports = Scale.extend({ return Number.POSITIVE_INFINITY; }, - handleDirectionalChanges: noop, + _handleDirectionalChanges: function(ticks) { + return ticks; + }, buildTicks: function() { var me = this; @@ -205,14 +206,13 @@ module.exports = Scale.extend({ precision: tickOpts.precision, stepSize: helpers.valueOrDefault(tickOpts.fixedStepSize, tickOpts.stepSize) }; - var ticks = me.ticks = generateTicks(numericGeneratorOptions, me); + var ticks = generateTicks(numericGeneratorOptions, me); - me.handleDirectionalChanges(); + ticks = me._handleDirectionalChanges(ticks); // At this point, we need to update our max and min given the tick values since we have expanded the // range of the scale - me.max = helpers.max(ticks); - me.min = helpers.min(ticks); + helpers._setMinAndMaxByKey(ticks, me, 'value'); if (tickOpts.reverse) { ticks.reverse(); @@ -223,14 +223,16 @@ module.exports = Scale.extend({ me.start = me.min; me.end = me.max; } + + return ticks; }, - convertTicksToLabels: function() { + generateTickLabels: function(ticks) { var me = this; - me.ticksAsNumbers = me.ticks.slice(); - me.zeroLineIndex = me.ticks.indexOf(0); + me._tickValues = ticks.map(t => t.value); + me.zeroLineIndex = me._tickValues.indexOf(0); - Scale.prototype.convertTicksToLabels.call(me); + Scale.prototype.generateTickLabels.call(me, ticks); }, _configure: function() { diff --git a/src/scales/scale.logarithmic.js b/src/scales/scale.logarithmic.js index 6a6553ab8..43a9d46ab 100644 --- a/src/scales/scale.logarithmic.js +++ b/src/scales/scale.logarithmic.js @@ -27,7 +27,7 @@ function generateTicks(generationOptions, dataRange) { exp = Math.floor(log10(dataRange.minNotZero)); significand = Math.floor(dataRange.minNotZero / Math.pow(10, exp)); - ticks.push(tickVal); + ticks.push({value: tickVal}); tickVal = significand * Math.pow(10, exp); } else { exp = Math.floor(log10(tickVal)); @@ -36,7 +36,7 @@ function generateTicks(generationOptions, dataRange) { var precision = exp < 0 ? Math.pow(10, Math.abs(exp)) : 1; do { - ticks.push(tickVal); + ticks.push({value: tickVal}); ++significand; if (significand === 10) { @@ -49,7 +49,7 @@ function generateTicks(generationOptions, dataRange) { } while (exp < endExp || (exp === endExp && significand < endSignificand)); var lastTick = valueOrDefault(generationOptions.max, tickVal); - ticks.push(lastTick); + ticks.push({value: lastTick}); return ticks; } @@ -130,10 +130,7 @@ module.exports = Scale.extend({ helpers.each(valuesPerStack, function(valuesForType) { if (valuesForType.length > 0) { - var minVal = helpers.min(valuesForType); - var maxVal = helpers.max(valuesForType); - me.min = Math.min(me.min, minVal); - me.max = Math.max(me.max, maxVal); + helpers._setMinAndMax(valuesForType, me); } }); @@ -214,12 +211,11 @@ module.exports = Scale.extend({ min: nonNegativeOrDefault(tickOpts.min), max: nonNegativeOrDefault(tickOpts.max) }; - var ticks = me.ticks = generateTicks(generationOptions, me); + var ticks = generateTicks(generationOptions, me); // At this point, we need to update our max and min given the tick values since we have expanded the // range of the scale - me.max = helpers.max(ticks); - me.min = helpers.min(ticks); + helpers._setMinAndMaxByKey(ticks, me, 'value'); if (tickOpts.reverse) { reverse = !reverse; @@ -232,12 +228,13 @@ module.exports = Scale.extend({ if (reverse) { ticks.reverse(); } + return ticks; }, - convertTicksToLabels: function() { - this.tickValues = this.ticks.slice(); + generateTickLabels: function(ticks) { + this._tickValues = ticks.map(t => t.value); - Scale.prototype.convertTicksToLabels.call(this); + return Scale.prototype.generateTickLabels.call(this, ticks); }, // Get the correct tooltip label @@ -246,7 +243,7 @@ module.exports = Scale.extend({ }, getPixelForTick: function(index) { - var ticks = this.tickValues; + var ticks = this._tickValues; if (index < 0 || index > ticks.length - 1) { return null; } diff --git a/src/scales/scale.radialLinear.js b/src/scales/scale.radialLinear.js index ea77ae022..18216168d 100644 --- a/src/scales/scale.radialLinear.js +++ b/src/scales/scale.radialLinear.js @@ -337,10 +337,10 @@ module.exports = LinearScaleBase.extend({ return Math.ceil(this.drawingArea / getTickBackdropHeight(this.options)); }, - convertTicksToLabels: function() { + generateTickLabels: function(ticks) { var me = this; - LinearScaleBase.prototype.convertTicksToLabels.call(me); + LinearScaleBase.prototype.generateTickLabels.call(me, ticks); // Point labels me.pointLabels = me.chart.data.labels.map(function() { @@ -467,9 +467,9 @@ module.exports = LinearScaleBase.extend({ } if (gridLineOpts.display) { - helpers.each(me.ticks, function(label, index) { + helpers.each(me.ticks, function(tick, index) { if (index !== 0) { - offset = me.getDistanceFromCenterForValue(me.ticksAsNumbers[index]); + offset = me.getDistanceFromCenterForValue(me._tickValues[index]); drawRadiusLine(me, gridLineOpts, offset, index); } }); @@ -522,15 +522,15 @@ module.exports = LinearScaleBase.extend({ ctx.textAlign = 'center'; ctx.textBaseline = 'middle'; - helpers.each(me.ticks, function(label, index) { + helpers.each(me.ticks, function(tick, index) { if (index === 0 && !tickOpts.reverse) { return; } - offset = me.getDistanceFromCenterForValue(me.ticksAsNumbers[index]); + offset = me.getDistanceFromCenterForValue(me._tickValues[index]); if (tickOpts.showLabelBackdrop) { - width = ctx.measureText(label).width; + width = ctx.measureText(tick.label).width; ctx.fillStyle = tickOpts.backdropColor; ctx.fillRect( @@ -542,7 +542,7 @@ module.exports = LinearScaleBase.extend({ } ctx.fillStyle = tickFontColor; - ctx.fillText(label, 0, -offset); + ctx.fillText(tick.label, 0, -offset); }); ctx.restore(); diff --git a/src/scales/scale.time.js b/src/scales/scale.time.js index cb3aac10a..453d18023 100644 --- a/src/scales/scale.time.js +++ b/src/scales/scale.time.js @@ -621,15 +621,13 @@ module.exports = Scale.extend({ return formatter ? formatter(label, index, ticks) : label; }, - convertTicksToLabels: function(ticks) { - var labels = []; - var i, ilen; + generateTickLabels: function(ticks) { + var i, ilen, tick; for (i = 0, ilen = ticks.length; i < ilen; ++i) { - labels.push(this.tickFormatFunction(ticks[i].value, i, ticks)); + tick = ticks[i]; + tick.label = this.tickFormatFunction(tick.value, i, ticks); } - - return labels; }, /** diff --git a/test/specs/core.layouts.tests.js b/test/specs/core.layouts.tests.js index 21a31c897..3c2b8e5b3 100644 --- a/test/specs/core.layouts.tests.js +++ b/test/specs/core.layouts.tests.js @@ -1,3 +1,7 @@ +function getLabels(scale) { + return scale.ticks.map(t => t.label); +} + describe('Chart.layouts', function() { it('should be exposed through Chart.layouts', function() { expect(Chart.layouts).toBeDefined(); @@ -651,7 +655,7 @@ describe('Chart.layouts', function() { // issue #4441: y-axis labels partially hidden. // minimum horizontal space required to fit labels expect(yAxis.width).toBeCloseToPixel(33); - expect(yAxis.ticks).toEqual(['2.5', '2.0', '1.5', '1.0', '0.5', '0']); + expect(getLabels(yAxis)).toEqual(['2.5', '2.0', '1.5', '1.0', '0.5', '0']); }); }); }); diff --git a/test/specs/core.scale.tests.js b/test/specs/core.scale.tests.js index a4f374602..d92ea6988 100644 --- a/test/specs/core.scale.tests.js +++ b/test/specs/core.scale.tests.js @@ -1,3 +1,7 @@ +function getLabels(scale) { + return scale.ticks.map(t => t.label); +} + describe('Core.scale', function() { describe('auto', jasmine.fixture.specs('core.scale')); @@ -390,37 +394,8 @@ describe('Core.scale', function() { id: 'x', type: 'category', labels: labels, - afterBuildTicks: function(axis, ticks) { - return ticks.slice(1); - } - }] - } - } - }); - - var scale = chart.scales.x; - expect(scale.ticks).toEqual(labels.slice(1)); - }); - - it('should allow filtering of ticks (for new implementation of buildTicks)', function() { - var chart = window.acquireChart({ - type: 'line', - data: { - labels: ['2016', '2017', '2018'] - }, - options: { - scales: { - xAxes: [{ - id: 'x', - type: 'time', - time: { - parser: 'YYYY' - }, - ticks: { - source: 'labels' - }, - afterBuildTicks: function(axis, ticks) { - return ticks.slice(1); + afterBuildTicks: function(scale) { + scale.ticks = scale.ticks.slice(1); } }] } @@ -428,7 +403,7 @@ describe('Core.scale', function() { }); var scale = chart.scales.x; - expect(scale.ticks.length).toEqual(2); + expect(getLabels(scale)).toEqual(labels.slice(1)); }); it('should allow no return value from callback', function() { @@ -448,7 +423,7 @@ describe('Core.scale', function() { }); var scale = chart.scales.x; - expect(scale.ticks).toEqual(labels); + expect(getLabels(scale)).toEqual(labels); }); it('should allow empty ticks', function() { @@ -461,8 +436,8 @@ describe('Core.scale', function() { id: 'x', type: 'category', labels: labels, - afterBuildTicks: function() { - return []; + afterBuildTicks: function(scale) { + scale.ticks = []; } }] } diff --git a/test/specs/core.ticks.tests.js b/test/specs/core.ticks.tests.js index afc2afda2..2dedaac11 100644 --- a/test/specs/core.ticks.tests.js +++ b/test/specs/core.ticks.tests.js @@ -1,3 +1,7 @@ +function getLabels(scale) { + return scale.ticks.map(t => t.label); +} + describe('Test tick generators', function() { // formatters are used as default config values so users want to be able to reference them it('Should expose formatters api', function() { @@ -42,11 +46,11 @@ describe('Test tick generators', function() { } }); - var xAxis = chart.scales['x-axis-0']; - var yAxis = chart.scales['y-axis-0']; + var xLabels = getLabels(chart.scales['x-axis-0']); + var yLabels = getLabels(chart.scales['y-axis-0']); - expect(xAxis.ticks).toEqual(['0', '0.1', '0.2', '0.3', '0.4', '0.5', '0.6', '0.7', '0.8', '0.9', '1']); - expect(yAxis.ticks).toEqual(['1', '0.9', '0.8', '0.7', '0.6', '0.5', '0.4', '0.3', '0.2', '0.1', '0']); + expect(xLabels).toEqual(['0', '0.1', '0.2', '0.3', '0.4', '0.5', '0.6', '0.7', '0.8', '0.9', '1']); + expect(yLabels).toEqual(['1', '0.9', '0.8', '0.7', '0.6', '0.5', '0.4', '0.3', '0.2', '0.1', '0']); }); it('Should generate logarithmic spaced ticks with correct precision', function() { @@ -87,10 +91,10 @@ describe('Test tick generators', function() { } }); - var xAxis = chart.scales['x-axis-0']; - var yAxis = chart.scales['y-axis-0']; + var xLabels = getLabels(chart.scales['x-axis-0']); + var yLabels = getLabels(chart.scales['y-axis-0']); - expect(xAxis.ticks).toEqual(['0.1', '0.2', '0.3', '0.4', '0.5', '0.6', '0.7', '0.8', '0.9', '1']); - expect(yAxis.ticks).toEqual(['1', '0.9', '0.8', '0.7', '0.6', '0.5', '0.4', '0.3', '0.2', '0.1']); + expect(xLabels).toEqual(['0.1', '0.2', '0.3', '0.4', '0.5', '0.6', '0.7', '0.8', '0.9', '1']); + expect(yLabels).toEqual(['1', '0.9', '0.8', '0.7', '0.6', '0.5', '0.4', '0.3', '0.2', '0.1']); }); }); diff --git a/test/specs/scale.category.tests.js b/test/specs/scale.category.tests.js index e49fff65a..337279608 100644 --- a/test/specs/scale.category.tests.js +++ b/test/specs/scale.category.tests.js @@ -1,5 +1,13 @@ // Test the category scale +function getLabels(scale) { + return scale.ticks.map(t => t.label); +} + +function getValues(scale) { + return scale.ticks.map(t => t.value); +} + describe('Category scale tests', function() { it('Should register the constructor with the scale service', function() { var Constructor = Chart.scaleService.getScaleConstructor('category'); @@ -75,8 +83,8 @@ describe('Category scale tests', function() { }); scale.determineDataLimits(); - scale.buildTicks(); - expect(scale.ticks).toEqual(mockData.labels); + scale.ticks = scale.buildTicks(); + expect(getValues(scale)).toEqual(mockData.labels); }); it('Should generate ticks from the data xLabels', function() { @@ -102,8 +110,8 @@ describe('Category scale tests', function() { }); scale.determineDataLimits(); - scale.buildTicks(); - expect(scale.ticks).toEqual(mockData.xLabels); + scale.ticks = scale.buildTicks(); + expect(getValues(scale)).toEqual(mockData.xLabels); }); it('Should generate ticks from the data yLabels', function() { @@ -130,8 +138,8 @@ describe('Category scale tests', function() { }); scale.determineDataLimits(); - scale.buildTicks(); - expect(scale.ticks).toEqual(mockData.yLabels); + scale.ticks = scale.buildTicks(); + expect(getValues(scale)).toEqual(mockData.yLabels); }); it('Should generate ticks from the axis labels', function() { @@ -153,7 +161,7 @@ describe('Category scale tests', function() { }); var scale = chart.scales.x; - expect(scale.ticks).toEqual(labels); + expect(getLabels(scale)).toEqual(labels); }); it('should get the correct label for the index', function() { diff --git a/test/specs/scale.linear.tests.js b/test/specs/scale.linear.tests.js index e99d101d7..79d7fcd7f 100644 --- a/test/specs/scale.linear.tests.js +++ b/test/specs/scale.linear.tests.js @@ -1,3 +1,7 @@ +function getLabels(scale) { + return scale.ticks.map(t => t.label); +} + describe('Linear Scale', function() { it('Should register the constructor with the scale service', function() { var Constructor = Chart.scaleService.getScaleConstructor('linear'); @@ -538,8 +542,9 @@ describe('Linear Scale', function() { expect(chart.scales.yScale0).not.toEqual(undefined); // must construct expect(chart.scales.yScale0.min).toBe(-1010); expect(chart.scales.yScale0.max).toBe(1010); - expect(chart.scales.yScale0.ticks[0]).toBe('1010'); - expect(chart.scales.yScale0.ticks[chart.scales.yScale0.ticks.length - 1]).toBe('-1010'); + var labels = getLabels(chart.scales.yScale0); + expect(labels[0]).toBe('1010'); + expect(labels[labels.length - 1]).toBe('-1010'); }); it('Should use min, max and stepSize to create fixed spaced ticks', function() { @@ -570,7 +575,7 @@ describe('Linear Scale', function() { expect(chart.scales.yScale0).not.toEqual(undefined); // must construct expect(chart.scales.yScale0.min).toBe(1); expect(chart.scales.yScale0.max).toBe(11); - expect(chart.scales.yScale0.ticks).toEqual(['11', '10', '8', '6', '4', '2', '1']); + expect(getLabels(chart.scales.yScale0)).toEqual(['11', '10', '8', '6', '4', '2', '1']); }); it('Should create decimal steps if stepSize is a decimal number', function() { @@ -599,7 +604,7 @@ describe('Linear Scale', function() { expect(chart.scales.yScale0).not.toEqual(undefined); // must construct expect(chart.scales.yScale0.min).toBe(0); expect(chart.scales.yScale0.max).toBe(10); - expect(chart.scales.yScale0.ticks).toEqual(['10', '7.5', '5', '2.5', '0']); + expect(getLabels(chart.scales.yScale0)).toEqual(['10', '7.5', '5', '2.5', '0']); }); describe('precision', function() { @@ -629,7 +634,7 @@ describe('Linear Scale', function() { expect(chart.scales.yScale0).not.toEqual(undefined); // must construct expect(chart.scales.yScale0.min).toBe(0); expect(chart.scales.yScale0.max).toBe(2); - expect(chart.scales.yScale0.ticks).toEqual(['2', '1', '0']); + expect(getLabels(chart.scales.yScale0)).toEqual(['2', '1', '0']); }); it('Should round the step size to the given number of decimal places', function() { @@ -658,7 +663,7 @@ describe('Linear Scale', function() { expect(chart.scales.yScale0).not.toEqual(undefined); // must construct expect(chart.scales.yScale0.min).toBe(0); expect(chart.scales.yScale0.max).toBe(0.01); - expect(chart.scales.yScale0.ticks).toEqual(['0.01', '0']); + expect(getLabels(chart.scales.yScale0)).toEqual(['0.01', '0']); }); }); @@ -684,19 +689,19 @@ describe('Linear Scale', function() { }); expect(chart.scales.yScale0).not.toEqual(undefined); // must construct - expect(chart.scales.yScale0.ticks).toEqual(['50', '45', '40', '35', '30', '25', '20']); + expect(getLabels(chart.scales.yScale0)).toEqual(['50', '45', '40', '35', '30', '25', '20']); chart.scales.yScale0.options.ticks.beginAtZero = true; chart.update(); - expect(chart.scales.yScale0.ticks).toEqual(['50', '45', '40', '35', '30', '25', '20', '15', '10', '5', '0']); + expect(getLabels(chart.scales.yScale0)).toEqual(['50', '45', '40', '35', '30', '25', '20', '15', '10', '5', '0']); chart.data.datasets[0].data = [-20, -30, -40, -50]; chart.update(); - expect(chart.scales.yScale0.ticks).toEqual(['0', '-5', '-10', '-15', '-20', '-25', '-30', '-35', '-40', '-45', '-50']); + expect(getLabels(chart.scales.yScale0)).toEqual(['0', '-5', '-10', '-15', '-20', '-25', '-30', '-35', '-40', '-45', '-50']); chart.scales.yScale0.options.ticks.beginAtZero = false; chart.update(); - expect(chart.scales.yScale0.ticks).toEqual(['-20', '-25', '-30', '-35', '-40', '-45', '-50']); + expect(getLabels(chart.scales.yScale0)).toEqual(['-20', '-25', '-30', '-35', '-40', '-45', '-50']); }); it('Should generate tick marks in the correct order in reversed mode', function() { @@ -722,7 +727,7 @@ describe('Linear Scale', function() { } }); - expect(chart.scales.yScale0.ticks).toEqual(['0', '10', '20', '30', '40', '50', '60', '70', '80']); + expect(getLabels(chart.scales.yScale0)).toEqual(['0', '10', '20', '30', '40', '50', '60', '70', '80']); expect(chart.scales.yScale0.start).toBe(80); expect(chart.scales.yScale0.end).toBe(0); }); @@ -746,7 +751,7 @@ describe('Linear Scale', function() { } } }); - expect(chart.scales.yScale0.ticks).toEqual(['0.06', '0.05', '0.04', '0.03', '0.02', '0.01', '0']); + expect(getLabels(chart.scales.yScale0)).toEqual(['0.06', '0.05', '0.04', '0.03', '0.02', '0.01', '0']); }); it('Should correctly limit the maximum number of ticks', function() { @@ -767,17 +772,17 @@ describe('Linear Scale', function() { } }); - expect(chart.scales.yScale.ticks).toEqual(['2.5', '2.0', '1.5', '1.0', '0.5']); + expect(getLabels(chart.scales.yScale)).toEqual(['2.5', '2.0', '1.5', '1.0', '0.5']); chart.options.scales.yAxes[0].ticks.maxTicksLimit = 11; chart.update(); - expect(chart.scales.yScale.ticks).toEqual(['2.5', '2.0', '1.5', '1.0', '0.5']); + expect(getLabels(chart.scales.yScale)).toEqual(['2.5', '2.0', '1.5', '1.0', '0.5']); chart.options.scales.yAxes[0].ticks.maxTicksLimit = 21; chart.update(); - expect(chart.scales.yScale.ticks).toEqual([ + expect(getLabels(chart.scales.yScale)).toEqual([ '2.5', '2.4', '2.3', '2.2', '2.1', '2.0', '1.9', '1.8', '1.7', '1.6', '1.5', '1.4', '1.3', '1.2', '1.1', '1.0', '0.9', '0.8', '0.7', '0.6', '0.5' @@ -787,13 +792,13 @@ describe('Linear Scale', function() { chart.options.scales.yAxes[0].ticks.stepSize = 0.01; chart.update(); - expect(chart.scales.yScale.ticks).toEqual(['2.5', '2.0', '1.5', '1.0', '0.5']); + expect(getLabels(chart.scales.yScale)).toEqual(['2.5', '2.0', '1.5', '1.0', '0.5']); chart.options.scales.yAxes[0].ticks.min = 0.3; chart.options.scales.yAxes[0].ticks.max = 2.8; chart.update(); - expect(chart.scales.yScale.ticks).toEqual(['2.8', '2.5', '2.0', '1.5', '1.0', '0.5', '0.3']); + expect(getLabels(chart.scales.yScale)).toEqual(['2.8', '2.5', '2.0', '1.5', '1.0', '0.5', '0.3']); }); it('Should build labels using the user supplied callback', function() { @@ -822,7 +827,7 @@ describe('Linear Scale', function() { }); // Just the index - expect(chart.scales.yScale0.ticks).toEqual(['0', '1', '2', '3', '4', '5', '6', '7', '8']); + expect(getLabels(chart.scales.yScale0)).toEqual(['0', '1', '2', '3', '4', '5', '6', '7', '8']); }); it('Should get the correct pixel value for a point', function() { diff --git a/test/specs/scale.logarithmic.tests.js b/test/specs/scale.logarithmic.tests.js index ba5102a66..f8f1d9cea 100644 --- a/test/specs/scale.logarithmic.tests.js +++ b/test/specs/scale.logarithmic.tests.js @@ -1,3 +1,7 @@ +function getLabels(scale) { + return scale.ticks.map(t => t.label); +} + describe('Logarithmic Scale tests', function() { it('should register the constructor with the scale service', function() { var Constructor = Chart.scaleService.getScaleConstructor('logarithmic'); @@ -473,8 +477,8 @@ describe('Logarithmic Scale tests', function() { var tickCount = yScale.ticks.length; expect(yScale.min).toBe(10); expect(yScale.max).toBe(1010); - expect(yScale.ticks[0]).toBe(1010); - expect(yScale.ticks[tickCount - 1]).toBe(10); + expect(yScale.ticks[0].value).toBe(1010); + expect(yScale.ticks[tickCount - 1].value).toBe(10); }); it('should ignore negative min and max options', function() { @@ -564,11 +568,10 @@ describe('Logarithmic Scale tests', function() { }); // Counts down because the lines are drawn top to bottom - expect(chart.scales.yScale).toEqual(jasmine.objectContaining({ - ticks: [80, 70, 60, 50, 40, 30, 20, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1], - start: 1, - end: 80 - })); + var scale = chart.scales.yScale; + expect(getLabels(scale)).toEqual([80, 70, 60, 50, 40, 30, 20, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1]); + expect(scale.start).toEqual(1); + expect(scale.end).toEqual(80); }); it('should generate tick marks when 0 values are present', function() { @@ -595,12 +598,11 @@ describe('Logarithmic Scale tests', function() { } }); + var scale = chart.scales.yScale; // Counts down because the lines are drawn top to bottom - expect(chart.scales.yScale).toEqual(jasmine.objectContaining({ - ticks: [30, 20, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0.9, 0.8, 0], - start: 0, - end: 30 - })); + expect(getLabels(scale)).toEqual([30, 20, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0.9, 0.8, 0]); + expect(scale.start).toEqual(0); + expect(scale.end).toEqual(30); }); @@ -629,12 +631,10 @@ describe('Logarithmic Scale tests', function() { } }); - // Counts down because the lines are drawn top to bottom - expect(chart.scales.yScale).toEqual(jasmine.objectContaining({ - ticks: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 20, 30, 40, 50, 60, 70, 80], - start: 80, - end: 1 - })); + var scale = chart.scales.yScale; + expect(getLabels(scale)).toEqual([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 20, 30, 40, 50, 60, 70, 80]); + expect(scale.start).toEqual(80); + expect(scale.end).toEqual(1); }); it('should generate tick marks in the correct order in reversed mode when 0 values are present', function() { @@ -662,12 +662,10 @@ describe('Logarithmic Scale tests', function() { } }); - // Counts down because the lines are drawn top to bottom - expect(chart.scales.yScale).toEqual(jasmine.objectContaining({ - ticks: [0, 9, 10, 20, 30], - start: 30, - end: 0 - })); + var scale = chart.scales.yScale; + expect(getLabels(scale)).toEqual([0, 9, 10, 20, 30]); + expect(scale.start).toEqual(30); + expect(scale.end).toEqual(0); }); it('should build labels using the default template', function() { @@ -689,7 +687,7 @@ describe('Logarithmic Scale tests', function() { } }); - expect(chart.scales.yScale.ticks).toEqual(['8e+1', '', '', '5e+1', '', '', '2e+1', '1e+1', '', '', '', '', '5e+0', '', '', '2e+0', '1e+0', '0']); + expect(getLabels(chart.scales.yScale)).toEqual(['8e+1', '', '', '5e+1', '', '', '2e+1', '1e+1', '', '', '', '', '5e+0', '', '', '2e+0', '1e+0', '0']); }); it('should build labels using the user supplied callback', function() { @@ -717,7 +715,7 @@ describe('Logarithmic Scale tests', function() { }); // Just the index - expect(chart.scales.yScale.ticks).toEqual(['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16']); + expect(getLabels(chart.scales.yScale)).toEqual(['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16']); }); it('should correctly get the correct label for a data item', function() { diff --git a/test/specs/scale.radialLinear.tests.js b/test/specs/scale.radialLinear.tests.js index 20349b351..ee83eb96c 100644 --- a/test/specs/scale.radialLinear.tests.js +++ b/test/specs/scale.radialLinear.tests.js @@ -1,3 +1,7 @@ +function getLabels(scale) { + return scale.ticks.map(t => t.label); +} + // Tests for the radial linear scale used by the polar area and radar charts describe('Test the radial linear scale', function() { describe('auto', jasmine.fixture.specs('scale.radialLinear')); @@ -220,7 +224,7 @@ describe('Test the radial linear scale', function() { expect(chart.scale.min).toBe(-1010); expect(chart.scale.max).toBe(1010); - expect(chart.scale.ticks).toEqual(['-1010', '-1000', '-500', '0', '500', '1000', '1010']); + expect(getLabels(chart.scale)).toEqual(['-1010', '-1000', '-500', '0', '500', '1000', '1010']); }); it('should forcibly include 0 in the range if the beginAtZero option is used', function() { @@ -241,22 +245,22 @@ describe('Test the radial linear scale', function() { } }); - expect(chart.scale.ticks).toEqual(['20', '25', '30', '35', '40', '45', '50']); + expect(getLabels(chart.scale)).toEqual(['20', '25', '30', '35', '40', '45', '50']); chart.scale.options.ticks.beginAtZero = true; chart.update(); - expect(chart.scale.ticks).toEqual(['0', '5', '10', '15', '20', '25', '30', '35', '40', '45', '50']); + expect(getLabels(chart.scale)).toEqual(['0', '5', '10', '15', '20', '25', '30', '35', '40', '45', '50']); chart.data.datasets[0].data = [-20, -30, -40, -50]; chart.update(); - expect(chart.scale.ticks).toEqual(['-50', '-45', '-40', '-35', '-30', '-25', '-20', '-15', '-10', '-5', '0']); + expect(getLabels(chart.scale)).toEqual(['-50', '-45', '-40', '-35', '-30', '-25', '-20', '-15', '-10', '-5', '0']); chart.scale.options.ticks.beginAtZero = false; chart.update(); - expect(chart.scale.ticks).toEqual(['-50', '-45', '-40', '-35', '-30', '-25', '-20']); + expect(getLabels(chart.scale)).toEqual(['-50', '-45', '-40', '-35', '-30', '-25', '-20']); }); it('Should generate tick marks in the correct order in reversed mode', function() { @@ -277,7 +281,7 @@ describe('Test the radial linear scale', function() { } }); - expect(chart.scale.ticks).toEqual(['80', '70', '60', '50', '40', '30', '20', '10', '0']); + expect(getLabels(chart.scale)).toEqual(['80', '70', '60', '50', '40', '30', '20', '10', '0']); expect(chart.scale.start).toBe(80); expect(chart.scale.end).toBe(0); }); @@ -300,23 +304,23 @@ describe('Test the radial linear scale', function() { } }); - expect(chart.scale.ticks).toEqual(['0.5', '1.0', '1.5', '2.0', '2.5']); + expect(getLabels(chart.scale)).toEqual(['0.5', '1.0', '1.5', '2.0', '2.5']); chart.options.scale.ticks.maxTicksLimit = 11; chart.update(); - expect(chart.scale.ticks).toEqual(['0.5', '1.0', '1.5', '2.0', '2.5']); + expect(getLabels(chart.scale)).toEqual(['0.5', '1.0', '1.5', '2.0', '2.5']); chart.options.scale.ticks.stepSize = 0.01; chart.update(); - expect(chart.scale.ticks).toEqual(['0.5', '1.0', '1.5', '2.0', '2.5']); + expect(getLabels(chart.scale)).toEqual(['0.5', '1.0', '1.5', '2.0', '2.5']); chart.options.scale.ticks.min = 0.3; chart.options.scale.ticks.max = 2.8; chart.update(); - expect(chart.scale.ticks).toEqual(['0.3', '0.5', '1.0', '1.5', '2.0', '2.5', '2.8']); + expect(getLabels(chart.scale)).toEqual(['0.3', '0.5', '1.0', '1.5', '2.0', '2.5', '2.8']); }); it('Should build labels using the user supplied callback', function() { @@ -339,7 +343,7 @@ describe('Test the radial linear scale', function() { } }); - expect(chart.scale.ticks).toEqual(['0', '1', '2', '3', '4', '5', '6', '7', '8']); + expect(getLabels(chart.scale)).toEqual(['0', '1', '2', '3', '4', '5', '6', '7', '8']); expect(chart.scale.pointLabels).toEqual(['label1', 'label2', 'label3', 'label4', 'label5']); }); diff --git a/test/specs/scale.time.tests.js b/test/specs/scale.time.tests.js index 1696a2aef..604bc9307 100755 --- a/test/specs/scale.time.tests.js +++ b/test/specs/scale.time.tests.js @@ -4,23 +4,25 @@ describe('Time scale tests', function() { var scaleID = 'myScale'; var mockContext = window.createMockContext(); var Constructor = Chart.scaleService.getScaleConstructor('time'); + var width = (dimensions && dimensions.width) || 400; + var height = (dimensions && dimensions.height) || 50; var scale = new Constructor({ ctx: mockContext, options: options, chart: { - data: data + data: data, + width: width, + height: height }, id: scaleID }); - var width = (dimensions && dimensions.width) || 400; - var height = (dimensions && dimensions.height) || 50; scale.update(width, height); return scale; } - function getTicksLabels(scale) { - return scale.ticks; + function getLabels(scale) { + return scale.ticks.map(t => t.label); } beforeEach(function() { @@ -124,7 +126,7 @@ describe('Time scale tests', function() { var scaleOptions = Chart.scaleService.getScaleDefaults('time'); var scale = createScale(mockData, scaleOptions, {width: 1000, height: 200}); - var ticks = getTicksLabels(scale); + var ticks = getLabels(scale); // `bounds === 'data'`: first and last ticks removed since outside the data range expect(ticks.length).toEqual(217); @@ -135,7 +137,7 @@ describe('Time scale tests', function() { labels: [newDateFromRef(0), newDateFromRef(1), newDateFromRef(2), newDateFromRef(4), newDateFromRef(6), newDateFromRef(7), newDateFromRef(9)], // days }; var scale = createScale(mockData, Chart.scaleService.getScaleDefaults('time'), {width: 1000, height: 200}); - var ticks = getTicksLabels(scale); + var ticks = getLabels(scale); // `bounds === 'data'`: first and last ticks removed since outside the data range expect(ticks.length).toEqual(217); @@ -183,7 +185,7 @@ describe('Time scale tests', function() { }, {canvas: {width: 800, height: 200}}); var xScale = chart.scales.xScale0; - var ticks = getTicksLabels(xScale); + var ticks = getLabels(xScale); // `bounds === 'data'`: first and last ticks removed since outside the data range expect(ticks.length).toEqual(217); @@ -231,7 +233,7 @@ describe('Time scale tests', function() { }, {canvas: {width: 800, height: 200}}); var tScale = chart.scales.tScale0; - var ticks = getTicksLabels(tScale); + var ticks = getLabels(tScale); // `bounds === 'data'`: first and last ticks removed since outside the data range expect(ticks.length).toEqual(217); @@ -272,11 +274,11 @@ describe('Time scale tests', function() { }); // Counts down because the lines are drawn top to bottom - var xScale = chart.scales.xScale0; + var labels = getLabels(chart.scales.xScale0); // Counts down because the lines are drawn top to bottom - expect(xScale.ticks[0]).toBe('Jan 2'); - expect(xScale.ticks[1]).toBe('May 8'); + expect(labels[0]).toBe('Jan 2'); + expect(labels[1]).toBe('May 8'); }); it('should build ticks using the config unit', function() { @@ -288,7 +290,7 @@ describe('Time scale tests', function() { config.time.unit = 'hour'; var scale = createScale(mockData, config, {width: 2500, height: 200}); - var ticks = getTicksLabels(scale); + var ticks = getLabels(scale); expect(ticks).toEqual(['8PM', '9PM', '10PM', '11PM', '12AM', '1AM', '2AM', '3AM', '4AM', '5AM', '6AM', '7AM', '8AM', '9AM', '10AM', '11AM', '12PM', '1PM', '2PM', '3PM', '4PM', '5PM', '6PM', '7PM', '8PM', '9PM']); }); @@ -306,7 +308,7 @@ describe('Time scale tests', function() { }, Chart.scaleService.getScaleDefaults('time')); var scale = createScale(mockData, config); - var ticks = getTicksLabels(scale); + var ticks = getLabels(scale); expect(ticks).toEqual(['Jan 1', 'Jan 2', 'Jan 3']); }); @@ -361,7 +363,7 @@ describe('Time scale tests', function() { }, Chart.scaleService.getScaleDefaults('time')); var scale = createScale(mockData, config); - var ticks = getTicksLabels(scale); + var ticks = getLabels(scale); expect(ticks).toEqual(['2012', '2013', '2014', '2015', '2016', '2017', '2018', '2019']); }); @@ -380,7 +382,7 @@ describe('Time scale tests', function() { }, Chart.scaleService.getScaleDefaults('time')); var scale = createScale(mockData, config, {width: 800, height: 200}); - var ticks = getTicksLabels(scale); + var ticks = getLabels(scale); // last date is feb 15 because we round to start of week expect(ticks).toEqual(['Dec 28, 2014', 'Jan 4, 2015', 'Jan 11, 2015', 'Jan 18, 2015', 'Jan 25, 2015', 'Feb 1, 2015', 'Feb 8, 2015', 'Feb 15, 2015']); @@ -401,7 +403,7 @@ describe('Time scale tests', function() { }, Chart.scaleService.getScaleDefaults('time')); var scale = createScale(mockData, config, {width: 2500, height: 200}); - var ticks = getTicksLabels(scale); + var ticks = getLabels(scale); expect(ticks).toEqual(['8PM', '10PM']); }); @@ -422,29 +424,29 @@ describe('Time scale tests', function() { it('should use the min option when less than first label for building ticks', function() { config.ticks.min = '2014-12-29T04:00:00'; - var scale = createScale(mockData, config); - expect(scale.ticks[0]).toEqual('Jan 1'); + var labels = getLabels(createScale(mockData, config)); + expect(labels[0]).toEqual('Jan 1'); }); it('should use the min option when greater than first label for building ticks', function() { config.ticks.min = '2015-01-02T04:00:00'; - var scale = createScale(mockData, config); - expect(scale.ticks[0]).toEqual('Jan 2'); + var labels = getLabels(createScale(mockData, config)); + expect(labels[0]).toEqual('Jan 2'); }); it('should use the max option when greater than last label for building ticks', function() { config.ticks.max = '2015-01-05T06:00:00'; - var scale = createScale(mockData, config); - expect(scale.ticks[scale.ticks.length - 1]).toEqual('Jan 3'); + var labels = getLabels(createScale(mockData, config)); + expect(labels[labels.length - 1]).toEqual('Jan 3'); }); it('should use the max option when less than last label for building ticks', function() { config.ticks.max = '2015-01-02T23:00:00'; - var scale = createScale(mockData, config); - expect(scale.ticks[scale.ticks.length - 1]).toEqual('Jan 2'); + var labels = getLabels(createScale(mockData, config)); + expect(labels[labels.length - 1]).toEqual('Jan 2'); }); }); @@ -463,29 +465,29 @@ describe('Time scale tests', function() { it('should use the min option when less than first label for building ticks', function() { config.ticks.min = '2014-12-29T04:00:00'; - var scale = createScale(mockData, config); - expect(scale.ticks[0]).toEqual('Jan 1'); + var labels = getLabels(createScale(mockData, config)); + expect(labels[0]).toEqual('Jan 1'); }); it('should use the min option when greater than first label for building ticks', function() { config.ticks.min = '2015-01-02T04:00:00'; - var scale = createScale(mockData, config); - expect(scale.ticks[0]).toEqual('Jan 2'); + var labels = getLabels(createScale(mockData, config)); + expect(labels[0]).toEqual('Jan 2'); }); it('should use the max option when greater than last label for building ticks', function() { config.ticks.max = '2015-01-05T06:00:00'; - var scale = createScale(mockData, config); - expect(scale.ticks[scale.ticks.length - 1]).toEqual('Jan 3'); + var labels = getLabels(createScale(mockData, config)); + expect(labels[labels.length - 1]).toEqual('Jan 3'); }); it('should use the max option when less than last label for building ticks', function() { config.ticks.max = '2015-01-02T23:00:00'; - var scale = createScale(mockData, config); - expect(scale.ticks[scale.ticks.length - 1]).toEqual('Jan 2'); + var labels = getLabels(createScale(mockData, config)); + expect(labels[labels.length - 1]).toEqual('Jan 2'); }); }); @@ -507,7 +509,7 @@ describe('Time scale tests', function() { }, Chart.scaleService.getScaleDefaults('time')); var scale = createScale(mockData, config); - var ticks = getTicksLabels(scale); + var ticks = getLabels(scale); expect(ticks).toEqual(['Dec 31, 2014', 'Jan 7, 2015']); }); @@ -616,7 +618,7 @@ describe('Time scale tests', function() { }); it('should build the correct ticks', function() { - expect(getTicksLabels(this.scale)).toEqual(['2005', '2006', '2007', '2008', '2009', '2010', '2011', '2012', '2013', '2014', '2015', '2016', '2017', '2018']); + expect(getLabels(this.scale)).toEqual(['2005', '2006', '2007', '2008', '2009', '2010', '2011', '2012', '2013', '2014', '2015', '2016', '2017', '2018']); }); it('should have ticks with accurate labels', function() { @@ -698,24 +700,24 @@ describe('Time scale tests', function() { }); it('should get the correct labels for ticks', function() { - var scale = this.scale; + var labels = getLabels(this.scale); - expect(scale.ticks.length).toEqual(61); - expect(scale.ticks[0]).toEqual('<8:00:00>'); - expect(scale.ticks[scale.ticks.length - 1]).toEqual('<8:01:00>'); + expect(labels.length).toEqual(61); + expect(labels[0]).toEqual('<8:00:00>'); + expect(labels[labels.length - 1]).toEqual('<8:01:00>'); }); it('should update ticks.callback correctly', function() { var chart = this.chart; - var scale = this.scale; - chart.options.scales.xAxes[0].ticks.callback = function(value) { return '{' + value + '}'; }; chart.update(); - expect(scale.ticks.length).toEqual(61); - expect(scale.ticks[0]).toEqual('{8:00:00}'); - expect(scale.ticks[scale.ticks.length - 1]).toEqual('{8:01:00}'); + + var labels = getLabels(this.scale); + expect(labels.length).toEqual(61); + expect(labels[0]).toEqual('{8:00:00}'); + expect(labels[labels.length - 1]).toEqual('{8:01:00}'); }); }); @@ -759,46 +761,46 @@ describe('Time scale tests', function() { }); it('should get the correct labels for major and minor ticks', function() { - var scale = this.scale; + var labels = getLabels(this.scale); - expect(scale.ticks.length).toEqual(61); - expect(scale.ticks[0]).toEqual('[[8:00 pm]]'); - expect(scale.ticks[Math.floor(scale.ticks.length / 2)]).toEqual('(8:00:30 pm)'); - expect(scale.ticks[scale.ticks.length - 1]).toEqual('[[8:01 pm]]'); + expect(labels.length).toEqual(61); + expect(labels[0]).toEqual('[[8:00 pm]]'); + expect(labels[Math.floor(labels.length / 2)]).toEqual('(8:00:30 pm)'); + expect(labels[labels.length - 1]).toEqual('[[8:01 pm]]'); }); it('should only use ticks.minor callback if ticks.major.enabled is false', function() { var chart = this.chart; - var scale = this.scale; - chart.options.scales.xAxes[0].ticks.major.enabled = false; chart.update(); - expect(scale.ticks.length).toEqual(61); - expect(scale.ticks[0]).toEqual('(8:00:00 pm)'); - expect(scale.ticks[scale.ticks.length - 1]).toEqual('(8:01:00 pm)'); + + var labels = getLabels(this.scale); + expect(labels.length).toEqual(61); + expect(labels[0]).toEqual('(8:00:00 pm)'); + expect(labels[labels.length - 1]).toEqual('(8:01:00 pm)'); }); it('should use ticks.callback if ticks.major.callback is omitted', function() { var chart = this.chart; - var scale = this.scale; - chart.options.scales.xAxes[0].ticks.major.callback = undefined; chart.update(); - expect(scale.ticks.length).toEqual(61); - expect(scale.ticks[0]).toEqual('<8:00 pm>'); - expect(scale.ticks[scale.ticks.length - 1]).toEqual('<8:01 pm>'); + + var labels = getLabels(this.scale); + expect(labels.length).toEqual(61); + expect(labels[0]).toEqual('<8:00 pm>'); + expect(labels[labels.length - 1]).toEqual('<8:01 pm>'); }); it('should use ticks.callback if ticks.minor.callback is omitted', function() { var chart = this.chart; - var scale = this.scale; - chart.options.scales.xAxes[0].ticks.minor.callback = undefined; chart.update(); - expect(scale.ticks.length).toEqual(61); - expect(scale.ticks[0]).toEqual('[[8:00 pm]]'); - expect(scale.ticks[Math.floor(scale.ticks.length / 2)]).toEqual('<8:00:30 pm>'); - expect(scale.ticks[scale.ticks.length - 1]).toEqual('[[8:01 pm]]'); + + var labels = getLabels(this.scale); + expect(labels.length).toEqual(61); + expect(labels[0]).toEqual('[[8:00 pm]]'); + expect(labels[Math.floor(labels.length / 2)]).toEqual('<8:00:30 pm>'); + expect(labels[labels.length - 1]).toEqual('[[8:01 pm]]'); }); }); @@ -943,7 +945,7 @@ describe('Time scale tests', function() { expect(scale.min).toEqual(+moment('2017', 'YYYY')); expect(scale.max).toEqual(+moment('2042', 'YYYY')); - expect(getTicksLabels(scale)).toEqual([ + expect(getLabels(scale)).toEqual([ '2017', '2019', '2020', '2025', '2042']); }); it ('should not add ticks for min and max if they extend the labels range', function() { @@ -957,7 +959,7 @@ describe('Time scale tests', function() { expect(scale.min).toEqual(+moment('2012', 'YYYY')); expect(scale.max).toEqual(+moment('2051', 'YYYY')); - expect(getTicksLabels(scale)).toEqual([ + expect(getLabels(scale)).toEqual([ '2017', '2019', '2020', '2025', '2042']); }); it ('should not duplicate ticks if min and max are the labels limits', function() { @@ -971,7 +973,7 @@ describe('Time scale tests', function() { expect(scale.min).toEqual(+moment('2017', 'YYYY')); expect(scale.max).toEqual(+moment('2042', 'YYYY')); - expect(getTicksLabels(scale)).toEqual([ + expect(getLabels(scale)).toEqual([ '2017', '2019', '2020', '2025', '2042']); }); it ('should correctly handle empty `data.labels` using "day" if `time.unit` is undefined`', function() { @@ -983,7 +985,7 @@ describe('Time scale tests', function() { expect(scale.min).toEqual(+moment().startOf('day')); expect(scale.max).toEqual(+moment().endOf('day') + 1); - expect(getTicksLabels(scale)).toEqual([]); + expect(getLabels(scale)).toEqual([]); }); it ('should correctly handle empty `data.labels` using `time.unit`', function() { var chart = this.chart; @@ -996,7 +998,7 @@ describe('Time scale tests', function() { expect(scale.min).toEqual(+moment().startOf('year')); expect(scale.max).toEqual(+moment().endOf('year') + 1); - expect(getTicksLabels(scale)).toEqual([]); + expect(getLabels(scale)).toEqual([]); }); }); @@ -1037,7 +1039,7 @@ describe('Time scale tests', function() { expect(scale.min).toEqual(+moment('2017', 'YYYY')); expect(scale.max).toEqual(+moment('2043', 'YYYY')); - expect(getTicksLabels(scale)).toEqual([ + expect(getLabels(scale)).toEqual([ '2017', '2018', '2019', '2020', '2025', '2042', '2043']); }); it ('should not add ticks for min and max if they extend the labels range', function() { @@ -1051,7 +1053,7 @@ describe('Time scale tests', function() { expect(scale.min).toEqual(+moment('2012', 'YYYY')); expect(scale.max).toEqual(+moment('2051', 'YYYY')); - expect(getTicksLabels(scale)).toEqual([ + expect(getLabels(scale)).toEqual([ '2017', '2018', '2019', '2020', '2025', '2042', '2043']); }); it ('should not duplicate ticks if min and max are the labels limits', function() { @@ -1065,7 +1067,7 @@ describe('Time scale tests', function() { expect(scale.min).toEqual(+moment('2017', 'YYYY')); expect(scale.max).toEqual(+moment('2043', 'YYYY')); - expect(getTicksLabels(scale)).toEqual([ + expect(getLabels(scale)).toEqual([ '2017', '2018', '2019', '2020', '2025', '2042', '2043']); }); it ('should correctly handle empty `data.labels` using "day" if `time.unit` is undefined`', function() { @@ -1077,7 +1079,7 @@ describe('Time scale tests', function() { expect(scale.min).toEqual(+moment('2018', 'YYYY')); expect(scale.max).toEqual(+moment('2043', 'YYYY')); - expect(getTicksLabels(scale)).toEqual([ + expect(getLabels(scale)).toEqual([ '2018', '2020', '2043']); }); it ('should correctly handle empty `data.labels` and hidden datasets using `time.unit`', function() { @@ -1093,7 +1095,7 @@ describe('Time scale tests', function() { expect(scale.min).toEqual(+moment().startOf('year')); expect(scale.max).toEqual(+moment().endOf('year') + 1); - expect(getTicksLabels(scale)).toEqual([]); + expect(getLabels(scale)).toEqual([]); }); }); }); @@ -1277,7 +1279,7 @@ describe('Time scale tests', function() { expect(scale.max).toEqual(+moment('02/23 11:00', 'MM/DD HH:mm')); expect(scale.getPixelForValue('02/20 08:00')).toBeCloseToPixel(scale.left); expect(scale.getPixelForValue('02/23 11:00')).toBeCloseToPixel(scale.left + scale.width); - expect(getTicksLabels(scale)).toEqual([ + expect(getLabels(scale)).toEqual([ 'Feb 21', 'Feb 22', 'Feb 23']); }); }); @@ -1315,7 +1317,7 @@ describe('Time scale tests', function() { expect(scale.max).toEqual(ticks[ticks.length - 1].value); expect(scale.getPixelForValue('02/20 08:00')).toBeCloseToPixel(60); expect(scale.getPixelForValue('02/23 11:00')).toBeCloseToPixel(426); - expect(getTicksLabels(scale)).toEqual([ + expect(getLabels(scale)).toEqual([ 'Feb 20', 'Feb 21', 'Feb 22', 'Feb 23', 'Feb 24']); }); }); @@ -1767,10 +1769,10 @@ describe('Time scale tests', function() { } }); - expect(getTicksLabels(chart.scales.x)).toEqual(['2015', '2016', '2017']); - expect(getTicksLabels(chart.scales.x2)).toEqual(['1985', '1986', '1987']); - expect(getTicksLabels(chart.scales.y)).toEqual(['1995', '1996', '1997']); - expect(getTicksLabels(chart.scales.y2)).toEqual(['2005', '2006', '2007']); + expect(getLabels(chart.scales.x)).toEqual(['2015', '2016', '2017']); + expect(getLabels(chart.scales.x2)).toEqual(['1985', '1986', '1987']); + expect(getLabels(chart.scales.y)).toEqual(['1995', '1996', '1997']); + expect(getLabels(chart.scales.y2)).toEqual(['2005', '2006', '2007']); }); }); -- 2.47.2