helpers.toDegrees = function(radians) {
return radians * (180 / Math.PI);
};
+
+ /**
+ * Returns the number of decimal places
+ * i.e. the number of digits after the decimal point, of the value of this Number.
+ * @param {Number} x - A number.
+ * @returns {Number} The number of decimal places.
+ */
+ helpers.decimalPlaces = function(x) {
+ if (!helpers.isFinite(x)) {
+ return;
+ }
+ var e = 1;
+ var p = 0;
+ while (Math.round(x * e) / e !== x) {
+ e *= 10;
+ p++;
+ }
+ return p;
+ };
+
// Gets the angle from vertical upright to the point about a centre.
helpers.getAngleFromPoint = function(centrePoint, anglePoint) {
var distanceFromXCenter = anglePoint.x - centrePoint.x;
// "nice number" algorithm. See http://stackoverflow.com/questions/8506881/nice-label-algorithm-for-charts-with-minimum-ticks
// for details.
- var factor;
- var precision;
- var spacing;
+ var stepSize = generationOptions.stepSize;
+ var min = generationOptions.min;
+ var max = generationOptions.max;
+ var spacing, precision, factor, niceRange, niceMin, niceMax, numSpaces;
- if (generationOptions.stepSize && generationOptions.stepSize > 0) {
- spacing = generationOptions.stepSize;
+ if (stepSize && stepSize > 0) {
+ spacing = stepSize;
} else {
- var niceRange = helpers.niceNum(dataRange.max - dataRange.min, false);
+ niceRange = helpers.niceNum(dataRange.max - dataRange.min, false);
spacing = helpers.niceNum(niceRange / (generationOptions.maxTicks - 1), true);
precision = generationOptions.precision;
- if (precision !== undefined) {
+ if (!helpers.isNullOrUndef(precision)) {
// If the user specified a precision, round to that number of decimal places
factor = Math.pow(10, precision);
spacing = Math.ceil(spacing * factor) / factor;
}
}
- var niceMin = Math.floor(dataRange.min / spacing) * spacing;
- var niceMax = Math.ceil(dataRange.max / spacing) * spacing;
+ // If a precision is not specified, calculate factor based on spacing
+ if (!factor) {
+ factor = Math.pow(10, helpers.decimalPlaces(spacing));
+ }
+ niceMin = Math.floor(dataRange.min / spacing) * spacing;
+ niceMax = Math.ceil(dataRange.max / spacing) * spacing;
// If min, max and stepSize is set and they make an evenly spaced scale use it.
- if (!helpers.isNullOrUndef(generationOptions.min) && !helpers.isNullOrUndef(generationOptions.max) && generationOptions.stepSize) {
+ if (!helpers.isNullOrUndef(min) && !helpers.isNullOrUndef(max) && stepSize) {
// If very close to our whole number, use it.
- if (helpers.almostWhole((generationOptions.max - generationOptions.min) / generationOptions.stepSize, spacing / 1000)) {
- niceMin = generationOptions.min;
- niceMax = generationOptions.max;
+ if (helpers.almostWhole((max - min) / stepSize, spacing / 1000)) {
+ niceMin = min;
+ niceMax = max;
}
}
- var numSpaces = (niceMax - niceMin) / spacing;
+ numSpaces = (niceMax - niceMin) / spacing;
// If very close to our rounded value, use it.
if (helpers.almostEquals(numSpaces, Math.round(numSpaces), spacing / 1000)) {
numSpaces = Math.round(numSpaces);
numSpaces = Math.ceil(numSpaces);
}
- precision = 1;
- if (spacing < 1) {
- precision = Math.pow(10, 1 - Math.floor(helpers.log10(spacing)));
- niceMin = Math.round(niceMin * precision) / precision;
- niceMax = Math.round(niceMax * precision) / precision;
- }
- ticks.push(generationOptions.min !== undefined ? generationOptions.min : niceMin);
+ niceMin = Math.round(niceMin * factor) / factor;
+ niceMax = Math.round(niceMax * factor) / factor;
+ ticks.push(helpers.isNullOrUndef(min) ? niceMin : min);
for (var j = 1; j < numSpaces; ++j) {
- ticks.push(Math.round((niceMin + j * spacing) * precision) / precision);
+ ticks.push(Math.round((niceMin + j * spacing) * factor) / factor);
}
- ticks.push(generationOptions.max !== undefined ? generationOptions.max : niceMax);
+ ticks.push(helpers.isNullOrUndef(max) ? niceMax : max);
return ticks;
}
expect(helpers.toDegrees(Math.PI * 3 / 2)).toBe(270);
});
+ it('should get the correct number of decimal places', function() {
+ expect(helpers.decimalPlaces(100)).toBe(0);
+ expect(helpers.decimalPlaces(1)).toBe(0);
+ expect(helpers.decimalPlaces(0)).toBe(0);
+ expect(helpers.decimalPlaces(0.01)).toBe(2);
+ expect(helpers.decimalPlaces(-0.01)).toBe(2);
+ expect(helpers.decimalPlaces('1')).toBe(undefined);
+ expect(helpers.decimalPlaces('')).toBe(undefined);
+ expect(helpers.decimalPlaces(undefined)).toBe(undefined);
+ });
+
it('should get an angle from a point', function() {
var center = {
x: 0,
expect(chart.scales.yScale0.ticks).toEqual(['11', '9', '7', '5', '3', '1']);
});
+ it('Should create decimal steps if stepSize is a decimal number', function() {
+ var chart = window.acquireChart({
+ type: 'bar',
+ data: {
+ datasets: [{
+ yAxisID: 'yScale0',
+ data: [10, 3, 6, 8, 3, 1]
+ }],
+ labels: ['a', 'b', 'c', 'd', 'e', 'f']
+ },
+ options: {
+ scales: {
+ yAxes: [{
+ id: 'yScale0',
+ type: 'linear',
+ ticks: {
+ stepSize: 2.5
+ }
+ }]
+ }
+ }
+ });
+
+ 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']);
+ });
+
describe('precision', function() {
it('Should create integer steps if precision is 0', function() {
var chart = window.acquireChart({