]> git.ipfire.org Git - thirdparty/Chart.js.git/commitdiff
formatters.numeric: verify ticks length (#8705) v3.0.0-rc.3
authorJukka Kurkela <jukka.kurkela@gmail.com>
Tue, 23 Mar 2021 20:14:22 +0000 (22:14 +0200)
committerGitHub <noreply@github.com>
Tue, 23 Mar 2021 20:14:22 +0000 (16:14 -0400)
* formatters.numeric: verify ticks length
* use tickValue as fallback delta, add tests
* cc, chore

src/core/core.ticks.js
test/specs/core.ticks.tests.js

index 59ad7a835d00b5c98a475b2b0ac954963b1f8413..186be7c0f07e84b8f9137563e65bcd0e0ec9a34f 100644 (file)
@@ -8,45 +8,40 @@ import {log10} from '../helpers/helpers.math';
  */
 const formatters = {
   /**
-        * Formatter for value labels
-        * @method Chart.Ticks.formatters.values
-        * @param value the value to display
-        * @return {string|string[]} the label to display
-        */
+   * Formatter for value labels
+   * @method Chart.Ticks.formatters.values
+   * @param value the value to display
+   * @return {string|string[]} the label to display
+   */
   values(value) {
     return isArray(value) ? value : '' + value;
   },
 
   /**
-        * Formatter for numeric ticks
-        * @method Chart.Ticks.formatters.numeric
-        * @param tickValue {number} the value to be formatted
-        * @param index {number} the position of the tickValue parameter in the ticks array
-        * @param ticks {object[]} the list of ticks being converted
-        * @return {string} string representation of the tickValue parameter
-        */
+   * Formatter for numeric ticks
+   * @method Chart.Ticks.formatters.numeric
+   * @param tickValue {number} the value to be formatted
+   * @param index {number} the position of the tickValue parameter in the ticks array
+   * @param ticks {object[]} the list of ticks being converted
+   * @return {string} string representation of the tickValue parameter
+   */
   numeric(tickValue, index, ticks) {
     if (tickValue === 0) {
       return '0'; // never show decimal places for 0
     }
 
     const locale = this.chart.options.locale;
-
-    // all ticks are small or there huge numbers; use scientific notation
-    const maxTick = Math.max(Math.abs(ticks[0].value), Math.abs(ticks[ticks.length - 1].value));
     let notation;
-    if (maxTick < 1e-4 || maxTick > 1e+15) {
-      notation = 'scientific';
-    }
+    let delta = tickValue; // This is used when there are less than 2 ticks as the tick interval.
 
-    // Figure out how many digits to show
-    // The space between the first two ticks might be smaller than normal spacing
-    let delta = ticks.length > 3 ? ticks[2].value - ticks[1].value : ticks[1].value - ticks[0].value;
+    if (ticks.length > 1) {
+      // all ticks are small or there huge numbers; use scientific notation
+      const maxTick = Math.max(Math.abs(ticks[0].value), Math.abs(ticks[ticks.length - 1].value));
+      if (maxTick < 1e-4 || maxTick > 1e+15) {
+        notation = 'scientific';
+      }
 
-    // If we have a number like 2.5 as the delta, figure out how many decimal places we need
-    if (Math.abs(delta) > 1 && tickValue !== Math.floor(tickValue)) {
-      // not an integer
-      delta = tickValue - Math.floor(tickValue);
+      delta = calculateDelta(tickValue, ticks);
     }
 
     const logDelta = log10(Math.abs(delta));
@@ -56,27 +51,43 @@ const formatters = {
     Object.assign(options, this.options.ticks.format);
 
     return formatNumber(tickValue, locale, options);
+  },
+
+
+  /**
+   * Formatter for logarithmic ticks
+   * @method Chart.Ticks.formatters.logarithmic
+   * @param tickValue {number} the value to be formatted
+   * @param index {number} the position of the tickValue parameter in the ticks array
+   * @param ticks {object[]} the list of ticks being converted
+   * @return {string} string representation of the tickValue parameter
+   */
+  logarithmic(tickValue, index, ticks) {
+    if (tickValue === 0) {
+      return '0';
+    }
+    const remain = tickValue / (Math.pow(10, Math.floor(log10(tickValue))));
+    if (remain === 1 || remain === 2 || remain === 5) {
+      return formatters.numeric.call(this, tickValue, index, ticks);
+    }
+    return '';
   }
+
 };
 
-/**
- * Formatter for logarithmic ticks
- * @method Chart.Ticks.formatters.logarithmic
- * @param tickValue {number} the value to be formatted
- * @param index {number} the position of the tickValue parameter in the ticks array
- * @param ticks {object[]} the list of ticks being converted
- * @return {string} string representation of the tickValue parameter
- */
-formatters.logarithmic = function(tickValue, index, ticks) {
-  if (tickValue === 0) {
-    return '0';
-  }
-  const remain = tickValue / (Math.pow(10, Math.floor(log10(tickValue))));
-  if (remain === 1 || remain === 2 || remain === 5) {
-    return formatters.numeric.call(this, tickValue, index, ticks);
+
+function calculateDelta(tickValue, ticks) {
+  // Figure out how many digits to show
+  // The space between the first two ticks might be smaller than normal spacing
+  let 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 && tickValue !== Math.floor(tickValue)) {
+    // not an integer
+    delta = tickValue - Math.floor(tickValue);
   }
-  return '';
-};
+  return delta;
+}
 
 /**
  * Namespace to hold static tick generation functions
index 149d19e72e62e40c05acb4eff20b2e28f1ad5b6f..52857b649aa8bb59c1818cd2b19d3a42440c822d 100644 (file)
@@ -96,4 +96,13 @@ describe('Test tick generators', function() {
     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(['0.1', '0.2', '0.3', '0.4', '0.5', '0.6', '0.7', '0.8', '0.9', '1']);
   });
+
+  describe('formatters.numeric', function() {
+    it('should not fail on empty or 1 item array', function() {
+      const scale = {chart: {options: {locale: 'en'}}, options: {ticks: {format: {}}}};
+      expect(Chart.Ticks.formatters.numeric.apply(scale, [1, 0, []])).toEqual('1');
+      expect(Chart.Ticks.formatters.numeric.apply(scale, [1, 0, [{value: 1}]])).toEqual('1');
+      expect(Chart.Ticks.formatters.numeric.apply(scale, [1, 0, [{value: 1}, {value: 1.01}]])).toEqual('1.00');
+    });
+  });
 });