]> git.ipfire.org Git - thirdparty/Chart.js.git/commitdiff
Handle effective dataset visibility per chart
authorSimon Brunel <simonbrunel@users.noreply.github.com>
Thu, 21 Apr 2016 17:12:12 +0000 (19:12 +0200)
committerSimon Brunel <simonbrunel@users.noreply.github.com>
Tue, 26 Apr 2016 10:46:27 +0000 (12:46 +0200)
Introduced a new meta.hidden 3 states flag (null|true|false) to be able to override dataset.hidden when interacting with the chart (i.e., true or false to ignore the dataset.hidden value). This is required in order to be able to correctly share dataset.hidden between multiple charts.

For example: 2 charts are sharing the same data and dataset.hidden is initially false: the dataset will be displayed on both charts because meta.hidden is null. If the user clicks the legend of the first chart, meta.hidden is changed to true and the dataset is only hidden on the first chart. If dataset.hidden changes, only the second chart will have the dataset visibility updated and that until the user click again on the first chart legend, switching the meta.hidden to null.

src/controllers/controller.bar.js
src/controllers/controller.doughnut.js
src/controllers/controller.line.js
src/controllers/controller.polarArea.js
src/core/core.controller.js
src/core/core.helpers.js
src/core/core.legend.js
src/core/core.tooltip.js
src/scales/scale.linear.js
src/scales/scale.logarithmic.js
src/scales/scale.radialLinear.js

index eb3dd4dc75bb4c84579e79dd91d7f7643698f0b1..a4fca99dc173393a76292339f7ff9fde742514c8 100644 (file)
@@ -40,7 +40,7 @@ module.exports = function(Chart) {
                        var barCount = 0;
                        helpers.each(this.chart.data.datasets, function(dataset, datasetIndex) {
                                var meta = this.chart.getDatasetMeta(datasetIndex);
-                               if (meta.bar && helpers.isDatasetVisible(dataset)) {
+                               if (meta.bar && this.chart.isDatasetVisible(datasetIndex)) {
                                        ++barCount;
                                }
                        }, this);
@@ -141,7 +141,7 @@ module.exports = function(Chart) {
                                        for (var i = 0; i < datasetIndex; i++) {
                                                var negDS = this.chart.data.datasets[i];
                                                var negDSMeta = this.chart.getDatasetMeta(i);
-                                               if (negDSMeta.bar && negDSMeta.yAxisID === yScale.id && helpers.isDatasetVisible(negDS)) {
+                                               if (negDSMeta.bar && negDSMeta.yAxisID === yScale.id && this.chart.isDatasetVisible(i)) {
                                                        base += negDS.data[index] < 0 ? negDS.data[index] : 0;
                                                }
                                        }
@@ -149,7 +149,7 @@ module.exports = function(Chart) {
                                        for (var j = 0; j < datasetIndex; j++) {
                                                var posDS = this.chart.data.datasets[j];
                                                var posDSMeta = this.chart.getDatasetMeta(j);
-                                               if (posDSMeta.bar && posDSMeta.yAxisID === yScale.id && helpers.isDatasetVisible(posDS)) {
+                                               if (posDSMeta.bar && posDSMeta.yAxisID === yScale.id && this.chart.isDatasetVisible(j)) {
                                                        base += posDS.data[index] > 0 ? posDS.data[index] : 0;
                                                }
                                        }
@@ -221,7 +221,7 @@ module.exports = function(Chart) {
 
                        for (j = 0; j < datasetIndex; ++j) {
                                meta = this.chart.getDatasetMeta(j);
-                               if (meta.bar && helpers.isDatasetVisible(this.chart.data.datasets[j])) {
+                               if (meta.bar && this.chart.isDatasetVisible(j)) {
                                        ++barIndex;
                                }
                        }
@@ -266,7 +266,7 @@ module.exports = function(Chart) {
                                for (var i = 0; i < datasetIndex; i++) {
                                        var ds = this.chart.data.datasets[i];
                                        var dsMeta = this.chart.getDatasetMeta(i);
-                                       if (dsMeta.bar && dsMeta.yAxisID === yScale.id && helpers.isDatasetVisible(ds)) {
+                                       if (dsMeta.bar && dsMeta.yAxisID === yScale.id && this.chart.isDatasetVisible(i)) {
                                                if (ds.data[index] < 0) {
                                                        sumNeg += ds.data[index] || 0;
                                                } else {
index e9cd0acab407cb43c0756ec739841c089657fb0f..69a5a130ffcb9cef4483903fb9eb8e54dbba4911 100644 (file)
@@ -61,17 +61,17 @@ module.exports = function(Chart) {
                                }
                        },
                        onClick: function(e, legendItem) {
-                               helpers.each(this.chart.data.datasets, function(dataset) {
-                                       dataset.metaHiddenData = dataset.metaHiddenData || [];
+                               helpers.each(this.chart.data.datasets, function(dataset, datasetIndex) {
+                                       var meta = this.chart.getDatasetMeta(datasetIndex);
                                        var idx = legendItem.index;
 
                                        if (!isNaN(dataset.data[idx])) {
-                                               dataset.metaHiddenData[idx] = dataset.data[idx];
+                                               meta.hiddenData[idx] = dataset.data[idx];
                                                dataset.data[idx] = NaN;
-                                       } else if (!isNaN(dataset.metaHiddenData[idx])) {
-                                               dataset.data[idx] = dataset.metaHiddenData[idx];
+                                       } else if (!isNaN(meta.hiddenData[idx])) {
+                                               dataset.data[idx] = meta.hiddenData[idx];
                                        }
-                               });
+                               }, this);
 
                                this.chart.update();
                        }
@@ -137,18 +137,12 @@ module.exports = function(Chart) {
                        this.updateElement(arc, index, true);
                },
 
-               getVisibleDatasetCount: function getVisibleDatasetCount() {
-                       return helpers.where(this.chart.data.datasets, function(ds) {
-                               return helpers.isDatasetVisible(ds);
-                       }).length;
-               },
-
                // Get index of the dataset in relation to the visible datasets. This allows determining the inner and outer radius correctly
                getRingIndex: function getRingIndex(datasetIndex) {
                        var ringIndex = 0;
 
                        for (var j = 0; j < datasetIndex; ++j) {
-                               if (helpers.isDatasetVisible(this.chart.data.datasets[j])) {
+                               if (this.chart.isDatasetVisible(j)) {
                                        ++ringIndex;
                                }
                        }
@@ -183,7 +177,7 @@ module.exports = function(Chart) {
 
                        this.chart.outerRadius = Math.max(minSize / 2, 0);
                        this.chart.innerRadius = Math.max(this.chart.options.cutoutPercentage ? (this.chart.outerRadius / 100) * (this.chart.options.cutoutPercentage) : 1, 0);
-                       this.chart.radiusLength = (this.chart.outerRadius - this.chart.innerRadius) / this.getVisibleDatasetCount();
+                       this.chart.radiusLength = (this.chart.outerRadius - this.chart.innerRadius) / this.chart.getVisibleDatasetCount();
                        this.chart.offsetX = offset.x * this.chart.outerRadius;
                        this.chart.offsetY = offset.y * this.chart.outerRadius;
 
index 2f8ed795189d075406ba9e5104cd00cb8adef238..ed480f4a06a55b343ab991d5dc098fd986748b2e 100644 (file)
@@ -223,7 +223,7 @@ module.exports = function(Chart) {
                                for (var i = 0; i < datasetIndex; i++) {
                                        var ds = this.chart.data.datasets[i];
                                        var dsMeta = this.chart.getDatasetMeta(i);
-                                       if (dsMeta.type === 'line' && helpers.isDatasetVisible(ds)) {
+                                       if (dsMeta.type === 'line' && this.chart.isDatasetVisible(i)) {
                                                if (ds.data[index] < 0) {
                                                        sumNeg += ds.data[index] || 0;
                                                } else {
index 1f4090047d21b369fe78dfb7a994ff7ec3510836..19e9b4b0d8ea077203bca2e17e14dbba562d9296 100644 (file)
@@ -62,17 +62,17 @@ module.exports = function(Chart) {
                                }
                        },
                        onClick: function(e, legendItem) {
-                               helpers.each(this.chart.data.datasets, function(dataset) {
-                                       dataset.metaHiddenData = dataset.metaHiddenData || [];
+                               helpers.each(this.chart.data.datasets, function(dataset, datasetIndex) {
+                                       var meta = this.chart.getDatasetMeta(datasetIndex);
                                        var idx = legendItem.index;
 
                                        if (!isNaN(dataset.data[idx])) {
-                                               dataset.metaHiddenData[idx] = dataset.data[idx];
+                                               meta.hiddenData[idx] = dataset.data[idx];
                                                dataset.data[idx] = NaN;
-                                       } else if (!isNaN(dataset.metaHiddenData[idx])) {
-                                               dataset.data[idx] = dataset.metaHiddenData[idx];
+                                       } else if (!isNaN(meta.hiddenData[idx])) {
+                                               dataset.data[idx] = meta.hiddenData[idx];
                                        }
-                               });
+                               }, this);
 
                                this.chart.update();
                        }
@@ -118,17 +118,12 @@ module.exports = function(Chart) {
                        this.getMeta().data.splice(index, 0, arc);
                        this.updateElement(arc, index, true);
                },
-               getVisibleDatasetCount: function getVisibleDatasetCount() {
-                       return helpers.where(this.chart.data.datasets, function(ds) {
-                               return helpers.isDatasetVisible(ds);
-                       }).length;
-               },
 
                update: function update(reset) {
                        var minSize = Math.min(this.chart.chartArea.right - this.chart.chartArea.left, this.chart.chartArea.bottom - this.chart.chartArea.top);
                        this.chart.outerRadius = Math.max((minSize - this.chart.options.elements.arc.borderWidth / 2) / 2, 0);
                        this.chart.innerRadius = Math.max(this.chart.options.cutoutPercentage ? (this.chart.outerRadius / 100) * (this.chart.options.cutoutPercentage) : 1, 0);
-                       this.chart.radiusLength = (this.chart.outerRadius - this.chart.innerRadius) / this.getVisibleDatasetCount();
+                       this.chart.radiusLength = (this.chart.outerRadius - this.chart.innerRadius) / this.chart.getVisibleDatasetCount();
 
                        this.getDataset().total = 0;
                        helpers.each(this.getDataset().data, function(value) {
index 3a33a04931d0b5ad6bcd8bfcb824629d9992e938..6ace65e8e85d96b3594119f6a5eb4985e9f35917 100644 (file)
@@ -325,7 +325,7 @@ module.exports = function(Chart) {
 
                        // Draw each dataset via its respective controller (reversed to support proper line stacking)
                        helpers.each(this.data.datasets, function(dataset, datasetIndex) {
-                               if (helpers.isDatasetVisible(dataset)) {
+                               if (this.isDatasetVisible(datasetIndex)) {
                                        this.getDatasetMeta(datasetIndex).controller.draw(ease);
                                }
                        }, this, true);
@@ -346,8 +346,8 @@ module.exports = function(Chart) {
                        var elementsArray = [];
 
                        helpers.each(this.data.datasets, function(dataset, datasetIndex) {
-                               var meta = this.getDatasetMeta(datasetIndex);
-                               if (helpers.isDatasetVisible(dataset)) {
+                               if (this.isDatasetVisible(datasetIndex)) {
+                                       var meta = this.getDatasetMeta(datasetIndex);
                                        helpers.each(meta.data, function(element, index) {
                                                if (element.inRange(eventPosition.x, eventPosition.y)) {
                                                        elementsArray.push(element);
@@ -368,7 +368,7 @@ module.exports = function(Chart) {
                                if (this.data.datasets) {
                                        for (var i = 0; i < this.data.datasets.length; i++) {
                                                var meta = this.getDatasetMeta(i);
-                                               if (helpers.isDatasetVisible(this.data.datasets[i])) {
+                                               if (this.isDatasetVisible(i)) {
                                                        for (var j = 0; j < meta.data.length; j++) {
                                                                if (meta.data[j].inRange(eventPosition.x, eventPosition.y)) {
                                                                        return meta.data[j];
@@ -384,8 +384,8 @@ module.exports = function(Chart) {
                        }
 
                        helpers.each(this.data.datasets, function(dataset, datasetIndex) {
-                               var meta = this.getDatasetMeta(datasetIndex);
-                               if (helpers.isDatasetVisible(dataset)) {
+                               if (this.isDatasetVisible(datasetIndex)) {
+                                       var meta = this.getDatasetMeta(datasetIndex);
                                        elementsArray.push(meta.data[found._index]);
                                }
                        }, this);
@@ -416,6 +416,8 @@ module.exports = function(Chart) {
                                data: [],
                                dataset: null,
                                controller: null,
+                               hiddenData: {},
+                               hidden: null,                   // See isDatasetVisible() comment
                                xAxisID: null,
                                yAxisID: null
                        };
@@ -424,6 +426,24 @@ module.exports = function(Chart) {
                        return meta;
                },
 
+               getVisibleDatasetCount: function() {
+                       var count = 0;
+                       for (var i = 0, ilen = this.data.datasets.length; i<ilen; ++i) {
+                                if (this.isDatasetVisible(i)) {
+                                       count++;
+                               }
+                       }
+                       return count;
+               },
+
+               isDatasetVisible: function(datasetIndex) {
+                       var meta = this.getDatasetMeta(datasetIndex);
+
+                       // meta.hidden is a per chart dataset hidden flag override with 3 states: if true or false,
+                       // the dataset.hidden value is ignored, else if null, the dataset hidden state is returned.
+                       return typeof meta.hidden === 'boolean'? !meta.hidden : !this.data.datasets[datasetIndex].hidden;
+               },
+
                generateLegend: function generateLegend() {
                        return this.options.legendCallback(this);
                },
index eb808258d9a6b7d28500b274954c5aacf8d740f8..7d3983fa8a5acdca8d28aa84fe5bff9033d12b36 100644 (file)
@@ -938,9 +938,6 @@ module.exports = function(Chart) {
                        array.push(element);
                }
        };
-       helpers.isDatasetVisible = function(dataset) {
-               return !dataset.hidden;
-       };
        helpers.callCallback = function(fn, args, _tArg) {
                if (fn && typeof fn.call === 'function') {
                        fn.apply(_tArg, args);
index ca042ccc42dd5a7997e13df7cf2c061829c61d70..62287ab707ffa8805a6aaad811feb86a5994d3b9 100644 (file)
@@ -13,8 +13,11 @@ module.exports = function(Chart) {
 
                // a callback that will handle
                onClick: function(e, legendItem) {
-                       var dataset = this.chart.data.datasets[legendItem.datasetIndex];
-                       dataset.hidden = !dataset.hidden;
+                       var index = legendItem.datasetIndex;
+                       var meta = this.chart.getDatasetMeta(index);
+
+                       // See controller.isDatasetVisible comment
+                       meta.hidden = meta.hidden === null? !this.chart.data.datasets[index].hidden : null;
 
                        // We hid a dataset ... rerender the chart
                        this.chart.update();
@@ -40,7 +43,7 @@ module.exports = function(Chart) {
                                        return {
                                                text: dataset.label,
                                                fillStyle: dataset.backgroundColor,
-                                               hidden: dataset.hidden,
+                                               hidden: !chart.isDatasetVisible(i),
                                                lineCap: dataset.borderCapStyle,
                                                lineDash: dataset.borderDash,
                                                lineDashOffset: dataset.borderDashOffset,
index cb7136402c6d871905d69b5246b118821d91d9e4..be5f1c85b3486d9f749692dfbfa68b2d73ca1e42 100644 (file)
@@ -236,7 +236,7 @@ module.exports = function(Chart) {
                                        tooltipPosition = this.getAveragePosition(this._active);
                                } else {
                                        helpers.each(this._data.datasets, function(dataset, datasetIndex) {
-                                               if (!helpers.isDatasetVisible(dataset)) {
+                                               if (!this._chartInstance.isDatasetVisible(datasetIndex)) {
                                                        return;
                                                }
 
index 80d9f336ac5839c0959ab92034390f26430c5970..c2717f30b17277a5041a1c738bed092d931e8875 100644 (file)
@@ -59,7 +59,7 @@ module.exports = function(Chart) {
                                        var positiveValues = valuesPerType[meta.type].positiveValues;
                                        var negativeValues = valuesPerType[meta.type].negativeValues;
 
-                                       if (helpers.isDatasetVisible(dataset) && (this.isHorizontal() ? meta.xAxisID === this.id : meta.yAxisID === this.id)) {
+                                       if (this.chart.isDatasetVisible(datasetIndex) && (this.isHorizontal() ? meta.xAxisID === this.id : meta.yAxisID === this.id)) {
                                                helpers.each(dataset.data, function(rawValue, index) {
 
                                                        var value = +this.getRightValue(rawValue);
@@ -96,7 +96,7 @@ module.exports = function(Chart) {
                        } else {
                                helpers.each(this.chart.data.datasets, function(dataset, datasetIndex) {
                                        var meta = this.chart.getDatasetMeta(datasetIndex);
-                                       if (helpers.isDatasetVisible(dataset) && (this.isHorizontal() ? meta.xAxisID === this.id : meta.yAxisID === this.id)) {
+                                       if (this.chart.isDatasetVisible(datasetIndex) && (this.isHorizontal() ? meta.xAxisID === this.id : meta.yAxisID === this.id)) {
                                                helpers.each(dataset.data, function(rawValue, index) {
                                                        var value = +this.getRightValue(rawValue);
                                                        if (isNaN(value)) {
index a99df1e7e97f018f10ef719ab96509b09cf6c628..ef9ab1435cec2cef2f1e2144c326564cccad0055 100644 (file)
@@ -32,7 +32,7 @@ module.exports = function(Chart) {
 
                                helpers.each(this.chart.data.datasets, function(dataset, datasetIndex) {
                                        var meta = this.chart.getDatasetMeta(datasetIndex);
-                                       if (helpers.isDatasetVisible(dataset) && (this.isHorizontal() ? meta.xAxisID === this.id : meta.yAxisID === this.id)) {
+                                       if (this.chart.isDatasetVisible(datasetIndex) && (this.isHorizontal() ? meta.xAxisID === this.id : meta.yAxisID === this.id)) {
                                                if (valuesPerType[meta.type] === undefined) {
                                                        valuesPerType[meta.type] = [];
                                                }
@@ -66,7 +66,7 @@ module.exports = function(Chart) {
                        } else {
                                helpers.each(this.chart.data.datasets, function(dataset, datasetIndex) {
                                        var meta = this.chart.getDatasetMeta(datasetIndex);
-                                       if (helpers.isDatasetVisible(dataset) && (this.isHorizontal() ? meta.xAxisID === this.id : meta.yAxisID === this.id)) {
+                                       if (this.chart.isDatasetVisible(dataset, datasetIndex) && (this.isHorizontal() ? meta.xAxisID === this.id : meta.yAxisID === this.id)) {
                                                helpers.each(dataset.data, function(rawValue, index) {
                                                        var value = +this.getRightValue(rawValue);
                                                        if (isNaN(value)) {
index a79a419582d3b97674a0a9fbbf795a4ff84273f7..e381a18e6d117c814ed14f3bac340775b008d57a 100644 (file)
@@ -63,8 +63,8 @@ module.exports = function(Chart) {
                        this.min = null;
                        this.max = null;
 
-                       helpers.each(this.chart.data.datasets, function(dataset) {
-                               if (helpers.isDatasetVisible(dataset)) {
+                       helpers.each(this.chart.data.datasets, function(dataset, datasetIndex) {
+                               if (this.chart.isDatasetVisible(datasetIndex)) {
                                        helpers.each(dataset.data, function(rawValue, index) {
                                                var value = +this.getRightValue(rawValue);
                                                if (isNaN(value)) {
@@ -395,7 +395,7 @@ module.exports = function(Chart) {
                                                }
                                                // Extra 3px out for some label spacing
                                                var pointLabelPosition = this.getPointPosition(i, this.getDistanceFromCenterForValue(this.options.reverse ? this.min : this.max) + 5);
-                                               
+
                                                var pointLabelFontColor = helpers.getValueOrDefault(this.options.pointLabels.fontColor, Chart.defaults.global.defaultFontColor);
                                                var pointLabelFontSize = helpers.getValueOrDefault(this.options.pointLabels.fontSize, Chart.defaults.global.defaultFontSize);
                                                var pointLabeFontStyle = helpers.getValueOrDefault(this.options.pointLabels.fontStyle, Chart.defaults.global.defaultFontStyle);