]> git.ipfire.org Git - thirdparty/Chart.js.git/commitdiff
Correctly determine min/max for Float Bar (#7398)
authorJukka Kurkela <jukka.kurkela@gmail.com>
Tue, 9 Jun 2020 21:15:05 +0000 (00:15 +0300)
committerGitHub <noreply@github.com>
Tue, 9 Jun 2020 21:15:05 +0000 (17:15 -0400)
src/controllers/controller.bar.js
src/core/core.datasetController.js
src/core/core.scale.js
src/scales/scale.linear.js
src/scales/scale.logarithmic.js
src/scales/scale.radialLinear.js
test/specs/controller.bar.tests.js

index 0b21e96b3a43a4ea75d86bb2b3611d87c46ca75a..d7acc836b22dac16de3380ae9616f30326eca177 100644 (file)
@@ -220,6 +220,19 @@ export default class BarController extends DatasetController {
                return parsed;
        }
 
+       /**
+        * @protected
+        */
+       updateRangeFromParsed(range, scale, parsed, stack) {
+               super.updateRangeFromParsed(range, scale, parsed, stack);
+               const custom = parsed._custom;
+               if (custom) {
+                       // float bar: only one end of the bar is considered by `super`
+                       range.min = Math.min(range.min, custom.min);
+                       range.max = Math.max(range.max, custom.max);
+               }
+       }
+
        /**
         * @protected
         */
index 48b2c79684f5ed2abc67fe93c9283ddf8a845d31..1f16ec89be1c614b68f5959683c6903c5b07445f 100644 (file)
@@ -584,35 +584,39 @@ export default class DatasetController {
                return applyStack(stack, value, meta.index);
        }
 
+       /**
+        * @protected
+        */
+       updateRangeFromParsed(range, scale, parsed, stack) {
+               let value = parsed[scale.axis];
+               const values = stack && parsed._stacks[scale.axis];
+               if (stack && values) {
+                       stack.values = values;
+                       // Need to consider individual stack values for data range,
+                       // in addition to the stacked value
+                       range.min = Math.min(range.min, value);
+                       range.max = Math.max(range.max, value);
+                       value = applyStack(stack, value, this._cachedMeta.index, true);
+               }
+               range.min = Math.min(range.min, value);
+               range.max = Math.max(range.max, value);
+       }
+
        /**
         * @protected
         */
        getMinMax(scale, canStack) {
-               const meta = this._cachedMeta;
+               const me = this;
+               const meta = me._cachedMeta;
                const _parsed = meta._parsed;
                const sorted = meta._sorted && scale === meta.iScale;
                const ilen = _parsed.length;
-               const otherScale = this._getOtherScale(scale);
-               const stack = canStack && meta._stacked && {keys: getSortedDatasetIndices(this.chart, true), values: null};
-               let min = Number.POSITIVE_INFINITY;
-               let max = Number.NEGATIVE_INFINITY;
+               const otherScale = me._getOtherScale(scale);
+               const stack = canStack && meta._stacked && {keys: getSortedDatasetIndices(me.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;
 
-               function _compute() {
-                       const values = stack && parsed._stacks[scale.axis];
-                       if (stack && values) {
-                               stack.values = values;
-                               // Need to consider individual stack values for data range,
-                               // in addition to the stacked value
-                               min = Math.min(min, value);
-                               max = Math.max(max, value);
-                               value = applyStack(stack, value, meta.index, true);
-                       }
-                       min = Math.min(min, value);
-                       max = Math.max(max, value);
-               }
-
                function _skip() {
                        parsed = _parsed[i];
                        value = parsed[scale.axis];
@@ -624,21 +628,23 @@ export default class DatasetController {
                        if (_skip()) {
                                continue;
                        }
-                       _compute();
+                       me.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;
                        }
                }
                if (sorted) {
+                       // in the sorted case, find first non-skipped value from other end of array
                        for (i = ilen - 1; i >= 0; --i) {
                                if (_skip()) {
                                        continue;
                                }
-                               _compute();
+                               me.updateRangeFromParsed(range, scale, parsed, stack);
                                break;
                        }
                }
-               return {min, max};
+               return range;
        }
 
        getAllParsedValues(scale) {
index 7f8a0d5aa6d8f8990253848b6a9c30378238e782..5e364085620fb5e2b3ab7167a41638656b88fb7b 100644 (file)
@@ -411,7 +411,7 @@ export default class Scale extends Element {
                const me = this;
                // eslint-disable-next-line prefer-const
                let {min, max, minDefined, maxDefined} = me.getUserBounds();
-               let minmax;
+               let range;
 
                if (minDefined && maxDefined) {
                        return {min, max};
@@ -419,12 +419,12 @@ export default class Scale extends Element {
 
                const metas = me.getMatchingVisibleMetas();
                for (let i = 0, ilen = metas.length; i < ilen; ++i) {
-                       minmax = metas[i].controller.getMinMax(me, canStack);
+                       range = metas[i].controller.getMinMax(me, canStack);
                        if (!minDefined) {
-                               min = Math.min(min, minmax.min);
+                               min = Math.min(min, range.min);
                        }
                        if (!maxDefined) {
-                               max = Math.max(max, minmax.max);
+                               max = Math.max(max, range.max);
                        }
                }
 
index f6392e5e64d3e5956d57eeff5a4691b5afb26f10..de3ec340a1e69a46095d11d95089a7ca7d936ad8 100644 (file)
@@ -13,9 +13,7 @@ class LinearScale extends LinearScaleBase {
        determineDataLimits() {
                const me = this;
                const options = me.options;
-               const minmax = me.getMinMax(true);
-               const min = minmax.min;
-               const max = minmax.max;
+               const {min, max} = me.getMinMax(true);
 
                me.min = isFinite(min) ? min : valueOrDefault(options.suggestedMin, 0);
                me.max = isFinite(max) ? max : valueOrDefault(options.suggestedMax, 1);
index 7efc88ceb530f3d53fd09d793a65b89fcd87183b..e0cce4182a626e7adea49e680ccc684c467605cc 100644 (file)
@@ -81,9 +81,7 @@ class LogarithmicScale extends Scale {
 
        determineDataLimits() {
                const me = this;
-               const minmax = me.getMinMax(true);
-               const min = minmax.min;
-               const max = minmax.max;
+               const {min, max} = me.getMinMax(true);
 
                me.min = isFinite(min) ? Math.max(0, min) : null;
                me.max = isFinite(max) ? Math.max(0, max) : null;
index 0273394f8d1e6d2619414b5ead0d1db6376e1ef9..bb1497295f1ef33417c56519780973ff0037eb93 100644 (file)
@@ -323,9 +323,7 @@ class RadialLinearScale extends LinearScaleBase {
 
        determineDataLimits() {
                const me = this;
-               const minmax = me.getMinMax(false);
-               const min = minmax.min;
-               const max = minmax.max;
+               const {min, max} = me.getMinMax(false);
 
                me.min = isFinite(min) && !isNaN(min) ? min : 0;
                me.max = isFinite(max) && !isNaN(max) ? max : 0;
index 7ea64528fbcf9d50d528805bd6f8b6b19d2c554f..c1a8f9bb8ccdc00c902aee8fed7215cdac93159d 100644 (file)
@@ -1629,4 +1629,20 @@ describe('Chart.controllers.bar', function() {
                expect(data[0].base + minBarLength).toEqual(data[0].x);
                expect(data[1].base - minBarLength).toEqual(data[1].x);
        });
+
+       describe('Float bar', function() {
+               it('Should return correct values from getMinMax', function() {
+                       var chart = window.acquireChart({
+                               type: 'bar',
+                               data: {
+                                       labels: ['a'],
+                                       datasets: [{
+                                               data: [[10, -10]]
+                                       }]
+                               }
+                       });
+
+                       expect(chart.scales.y.getMinMax()).toEqual({min: -10, max: 10});
+               });
+       });
 });