From 82b1e5cd99d77744aac3c1a3c532bbf99b2578cf Mon Sep 17 00:00:00 2001 From: Simon Brunel Date: Thu, 21 Apr 2016 19:12:12 +0200 Subject: [PATCH] Handle effective dataset visibility per chart 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 | 10 ++++---- src/controllers/controller.doughnut.js | 22 +++++++---------- src/controllers/controller.line.js | 2 +- src/controllers/controller.polarArea.js | 19 ++++++--------- src/core/core.controller.js | 32 ++++++++++++++++++++----- src/core/core.helpers.js | 3 --- src/core/core.legend.js | 9 ++++--- src/core/core.tooltip.js | 2 +- src/scales/scale.linear.js | 4 ++-- src/scales/scale.logarithmic.js | 4 ++-- src/scales/scale.radialLinear.js | 6 ++--- 11 files changed, 61 insertions(+), 52 deletions(-) diff --git a/src/controllers/controller.bar.js b/src/controllers/controller.bar.js index eb3dd4dc7..a4fca99dc 100644 --- a/src/controllers/controller.bar.js +++ b/src/controllers/controller.bar.js @@ -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 { diff --git a/src/controllers/controller.doughnut.js b/src/controllers/controller.doughnut.js index e9cd0acab..69a5a130f 100644 --- a/src/controllers/controller.doughnut.js +++ b/src/controllers/controller.doughnut.js @@ -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; diff --git a/src/controllers/controller.line.js b/src/controllers/controller.line.js index 2f8ed7951..ed480f4a0 100644 --- a/src/controllers/controller.line.js +++ b/src/controllers/controller.line.js @@ -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 { diff --git a/src/controllers/controller.polarArea.js b/src/controllers/controller.polarArea.js index 1f4090047..19e9b4b0d 100644 --- a/src/controllers/controller.polarArea.js +++ b/src/controllers/controller.polarArea.js @@ -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) { diff --git a/src/core/core.controller.js b/src/core/core.controller.js index 3a33a0493..6ace65e8e 100644 --- a/src/core/core.controller.js +++ b/src/core/core.controller.js @@ -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