diff --git a/src/js/common/Utilities.js b/src/js/common/Utilities.js index c6bbbafc2d..31f46e6638 100644 --- a/src/js/common/Utilities.js +++ b/src/js/common/Utilities.js @@ -106,43 +106,53 @@ define([], () => { return names; }, - // Format the number into a string with better readability. - formatNumber(value, min, max) { - if (!value && value !== 0) { + /** + * Format the number into a string with better readability, based on the manitude of a + * range this number falls in. + * @param {number} value The number value to be formatted. + * @param {number} range The range of numerics this value can fall in. + * @returns {string} A formatted number based on the magnitude of `range`. + */ + formatNumber(value, range) { + if (typeof value !== "number") { return ""; } + if (typeof range !== "number") { + return value.toString(); + } - const roundingConstant = Utilities.getRoundingConstant(max - min); - if (roundingConstant) { - return ( - Math.round(value * roundingConstant) / roundingConstant - ).toString(); + const numDecimalPlaces = Utilities.getNumDecimalPlaces(range); + if (numDecimalPlaces !== null) { + return value.toFixed(numDecimalPlaces); } return value.toExponential(2).toString(); }, - // Calculate the rounding precision we should use based on the - // range of the data. - getRoundingConstant(range) { + /** + * Calculate the number of decimal places we should use based on the range of the data. + * @param {number} range The range of data values. + * @returns {number} The number of decimal places we should use. + */ + getNumDecimalPlaces(range) { if (range < 0.0001 || range > 100000) { return null; // Will use scientific notation } if (range < 0.001) { - return 100000; // Allow 5 decimal places + return 5; // Allow 5 decimal places } if (range < 0.01) { - return 10000; // Allow 4 decimal places + return 4; // Allow 4 decimal places } if (range < 0.1) { - return 1000; // Allow 3 decimal places + return 3; // Allow 3 decimal places } if (range < 1) { - return 100; // Allow 2 decimal places + return 2; // Allow 2 decimal places } - if (range > 100) { - return 1; // No decimal places + if (range <= 100) { + return 1; // Allow 1 decimal places } - return 10; // Allow 1 decimal place by default + return 0; // No decimal places }, }; diff --git a/src/js/views/maps/LegendView.js b/src/js/views/maps/LegendView.js index 7e32c20e5b..24a8f117e3 100644 --- a/src/js/views/maps/LegendView.js +++ b/src/js/views/maps/LegendView.js @@ -356,7 +356,7 @@ define([ const min = data[0].value; const max = data[data.length - 1].value; const range = max - min; - const roundingConstant = Utilities.getRoundingConstant(range); + const numDecimalPlaces = Utilities.getNumDecimalPlaces(range); // SVG element const svg = this.createSVG({ @@ -429,10 +429,8 @@ define([ // Show tooltip with the value if (value || value === 0) { // Round or show in scientific notation - if (roundingConstant) { - value = ( - Math.round(value * roundingConstant) / roundingConstant - ).toString(); + if (numDecimalPlaces !== null) { + value = value.toFixed(numDecimalPlaces); } else { value = value.toExponential(2).toString(); } diff --git a/src/js/views/maps/legend/ContinuousSwatchView.js b/src/js/views/maps/legend/ContinuousSwatchView.js index fa93a15d4c..57ac4954fc 100644 --- a/src/js/views/maps/legend/ContinuousSwatchView.js +++ b/src/js/views/maps/legend/ContinuousSwatchView.js @@ -45,12 +45,13 @@ define([ const min = this.collection.first().get("value"); const max = this.collection.last().get("value"); const mid = (min + max) / 2; + const range = max - min; this.$el.html( this.template({ classNames: CLASS_NAMES, - min: Utilities.formatNumber(min, min, max), - mid: Utilities.formatNumber(mid, min, max), - max: Utilities.formatNumber(max, min, max), + min: Utilities.formatNumber(min, range), + mid: Utilities.formatNumber(mid, range), + max: Utilities.formatNumber(max, range), }), ); diff --git a/test/js/specs/unit/common/Utilities.spec.js b/test/js/specs/unit/common/Utilities.spec.js index 9b4b74edc4..a926652dc7 100644 --- a/test/js/specs/unit/common/Utilities.spec.js +++ b/test/js/specs/unit/common/Utilities.spec.js @@ -29,17 +29,25 @@ define(["../../../../../../src/js/common/Utilities"], function (EntityUtils) { describe("formatNumber", () => { it("rounds number if the range is between 0.0001 and 100000", () => { - expect(EntityUtils.formatNumber(0.000099999, 0, 0.0001)).to.equal( - "0.0001", + expect(EntityUtils.formatNumber(0.000099999, 0.0001)).to.equal( + "0.00010", ); - expect(EntityUtils.formatNumber(1.9, 0, 100000)).to.equal("2"); + expect(EntityUtils.formatNumber(1.9, 100000)).to.equal("2"); }); it("uses scientific notation if the range is outside of 0.0001 and 100000", () => { - expect(EntityUtils.formatNumber(0.000099999, 0, 0.000099999)).to.equal( + expect(EntityUtils.formatNumber(0.000099999, 0.000099999)).to.equal( "1.00e-4", ); - expect(EntityUtils.formatNumber(1.9, 0, 100001)).to.equal("1.90e+0"); + expect(EntityUtils.formatNumber(1.9, 100001)).to.equal("1.90e+0"); + }); + + it("returns empty string if input value isn't a number", () => { + expect(EntityUtils.formatNumber("1.0", 0.000099999)).to.equal(""); + }); + + it("returns value as is if range isn't a number", () => { + expect(EntityUtils.formatNumber(1.9, "invalid range")).to.equal("1.9"); }); }); });