Skip to content

Commit 9064ecc

Browse files
committed
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.
1 parent 409bb20 commit 9064ecc

File tree

11 files changed

+61
-52
lines changed

11 files changed

+61
-52
lines changed

src/controllers/controller.bar.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ module.exports = function(Chart) {
4040
var barCount = 0;
4141
helpers.each(this.chart.data.datasets, function(dataset, datasetIndex) {
4242
var meta = this.chart.getDatasetMeta(datasetIndex);
43-
if (meta.bar && helpers.isDatasetVisible(dataset)) {
43+
if (meta.bar && this.chart.isDatasetVisible(datasetIndex)) {
4444
++barCount;
4545
}
4646
}, this);
@@ -141,15 +141,15 @@ module.exports = function(Chart) {
141141
for (var i = 0; i < datasetIndex; i++) {
142142
var negDS = this.chart.data.datasets[i];
143143
var negDSMeta = this.chart.getDatasetMeta(i);
144-
if (negDSMeta.bar && negDSMeta.yAxisID === yScale.id && helpers.isDatasetVisible(negDS)) {
144+
if (negDSMeta.bar && negDSMeta.yAxisID === yScale.id && this.chart.isDatasetVisible(i)) {
145145
base += negDS.data[index] < 0 ? negDS.data[index] : 0;
146146
}
147147
}
148148
} else {
149149
for (var j = 0; j < datasetIndex; j++) {
150150
var posDS = this.chart.data.datasets[j];
151151
var posDSMeta = this.chart.getDatasetMeta(j);
152-
if (posDSMeta.bar && posDSMeta.yAxisID === yScale.id && helpers.isDatasetVisible(posDS)) {
152+
if (posDSMeta.bar && posDSMeta.yAxisID === yScale.id && this.chart.isDatasetVisible(j)) {
153153
base += posDS.data[index] > 0 ? posDS.data[index] : 0;
154154
}
155155
}
@@ -221,7 +221,7 @@ module.exports = function(Chart) {
221221

222222
for (j = 0; j < datasetIndex; ++j) {
223223
meta = this.chart.getDatasetMeta(j);
224-
if (meta.bar && helpers.isDatasetVisible(this.chart.data.datasets[j])) {
224+
if (meta.bar && this.chart.isDatasetVisible(j)) {
225225
++barIndex;
226226
}
227227
}
@@ -266,7 +266,7 @@ module.exports = function(Chart) {
266266
for (var i = 0; i < datasetIndex; i++) {
267267
var ds = this.chart.data.datasets[i];
268268
var dsMeta = this.chart.getDatasetMeta(i);
269-
if (dsMeta.bar && dsMeta.yAxisID === yScale.id && helpers.isDatasetVisible(ds)) {
269+
if (dsMeta.bar && dsMeta.yAxisID === yScale.id && this.chart.isDatasetVisible(i)) {
270270
if (ds.data[index] < 0) {
271271
sumNeg += ds.data[index] || 0;
272272
} else {

src/controllers/controller.doughnut.js

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -61,17 +61,17 @@ module.exports = function(Chart) {
6161
}
6262
},
6363
onClick: function(e, legendItem) {
64-
helpers.each(this.chart.data.datasets, function(dataset) {
65-
dataset.metaHiddenData = dataset.metaHiddenData || [];
64+
helpers.each(this.chart.data.datasets, function(dataset, datasetIndex) {
65+
var meta = this.chart.getDatasetMeta(datasetIndex);
6666
var idx = legendItem.index;
6767

6868
if (!isNaN(dataset.data[idx])) {
69-
dataset.metaHiddenData[idx] = dataset.data[idx];
69+
meta.hiddenData[idx] = dataset.data[idx];
7070
dataset.data[idx] = NaN;
71-
} else if (!isNaN(dataset.metaHiddenData[idx])) {
72-
dataset.data[idx] = dataset.metaHiddenData[idx];
71+
} else if (!isNaN(meta.hiddenData[idx])) {
72+
dataset.data[idx] = meta.hiddenData[idx];
7373
}
74-
});
74+
}, this);
7575

7676
this.chart.update();
7777
}
@@ -137,18 +137,12 @@ module.exports = function(Chart) {
137137
this.updateElement(arc, index, true);
138138
},
139139

140-
getVisibleDatasetCount: function getVisibleDatasetCount() {
141-
return helpers.where(this.chart.data.datasets, function(ds) {
142-
return helpers.isDatasetVisible(ds);
143-
}).length;
144-
},
145-
146140
// Get index of the dataset in relation to the visible datasets. This allows determining the inner and outer radius correctly
147141
getRingIndex: function getRingIndex(datasetIndex) {
148142
var ringIndex = 0;
149143

150144
for (var j = 0; j < datasetIndex; ++j) {
151-
if (helpers.isDatasetVisible(this.chart.data.datasets[j])) {
145+
if (this.chart.isDatasetVisible(j)) {
152146
++ringIndex;
153147
}
154148
}
@@ -183,7 +177,7 @@ module.exports = function(Chart) {
183177

184178
this.chart.outerRadius = Math.max(minSize / 2, 0);
185179
this.chart.innerRadius = Math.max(this.chart.options.cutoutPercentage ? (this.chart.outerRadius / 100) * (this.chart.options.cutoutPercentage) : 1, 0);
186-
this.chart.radiusLength = (this.chart.outerRadius - this.chart.innerRadius) / this.getVisibleDatasetCount();
180+
this.chart.radiusLength = (this.chart.outerRadius - this.chart.innerRadius) / this.chart.getVisibleDatasetCount();
187181
this.chart.offsetX = offset.x * this.chart.outerRadius;
188182
this.chart.offsetY = offset.y * this.chart.outerRadius;
189183

src/controllers/controller.line.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,7 @@ module.exports = function(Chart) {
223223
for (var i = 0; i < datasetIndex; i++) {
224224
var ds = this.chart.data.datasets[i];
225225
var dsMeta = this.chart.getDatasetMeta(i);
226-
if (dsMeta.type === 'line' && helpers.isDatasetVisible(ds)) {
226+
if (dsMeta.type === 'line' && this.chart.isDatasetVisible(i)) {
227227
if (ds.data[index] < 0) {
228228
sumNeg += ds.data[index] || 0;
229229
} else {

src/controllers/controller.polarArea.js

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -62,17 +62,17 @@ module.exports = function(Chart) {
6262
}
6363
},
6464
onClick: function(e, legendItem) {
65-
helpers.each(this.chart.data.datasets, function(dataset) {
66-
dataset.metaHiddenData = dataset.metaHiddenData || [];
65+
helpers.each(this.chart.data.datasets, function(dataset, datasetIndex) {
66+
var meta = this.chart.getDatasetMeta(datasetIndex);
6767
var idx = legendItem.index;
6868

6969
if (!isNaN(dataset.data[idx])) {
70-
dataset.metaHiddenData[idx] = dataset.data[idx];
70+
meta.hiddenData[idx] = dataset.data[idx];
7171
dataset.data[idx] = NaN;
72-
} else if (!isNaN(dataset.metaHiddenData[idx])) {
73-
dataset.data[idx] = dataset.metaHiddenData[idx];
72+
} else if (!isNaN(meta.hiddenData[idx])) {
73+
dataset.data[idx] = meta.hiddenData[idx];
7474
}
75-
});
75+
}, this);
7676

7777
this.chart.update();
7878
}
@@ -118,17 +118,12 @@ module.exports = function(Chart) {
118118
this.getMeta().data.splice(index, 0, arc);
119119
this.updateElement(arc, index, true);
120120
},
121-
getVisibleDatasetCount: function getVisibleDatasetCount() {
122-
return helpers.where(this.chart.data.datasets, function(ds) {
123-
return helpers.isDatasetVisible(ds);
124-
}).length;
125-
},
126121

127122
update: function update(reset) {
128123
var minSize = Math.min(this.chart.chartArea.right - this.chart.chartArea.left, this.chart.chartArea.bottom - this.chart.chartArea.top);
129124
this.chart.outerRadius = Math.max((minSize - this.chart.options.elements.arc.borderWidth / 2) / 2, 0);
130125
this.chart.innerRadius = Math.max(this.chart.options.cutoutPercentage ? (this.chart.outerRadius / 100) * (this.chart.options.cutoutPercentage) : 1, 0);
131-
this.chart.radiusLength = (this.chart.outerRadius - this.chart.innerRadius) / this.getVisibleDatasetCount();
126+
this.chart.radiusLength = (this.chart.outerRadius - this.chart.innerRadius) / this.chart.getVisibleDatasetCount();
132127

133128
this.getDataset().total = 0;
134129
helpers.each(this.getDataset().data, function(value) {

src/core/core.controller.js

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -325,7 +325,7 @@ module.exports = function(Chart) {
325325

326326
// Draw each dataset via its respective controller (reversed to support proper line stacking)
327327
helpers.each(this.data.datasets, function(dataset, datasetIndex) {
328-
if (helpers.isDatasetVisible(dataset)) {
328+
if (this.isDatasetVisible(datasetIndex)) {
329329
this.getDatasetMeta(datasetIndex).controller.draw(ease);
330330
}
331331
}, this, true);
@@ -346,8 +346,8 @@ module.exports = function(Chart) {
346346
var elementsArray = [];
347347

348348
helpers.each(this.data.datasets, function(dataset, datasetIndex) {
349-
var meta = this.getDatasetMeta(datasetIndex);
350-
if (helpers.isDatasetVisible(dataset)) {
349+
if (this.isDatasetVisible(datasetIndex)) {
350+
var meta = this.getDatasetMeta(datasetIndex);
351351
helpers.each(meta.data, function(element, index) {
352352
if (element.inRange(eventPosition.x, eventPosition.y)) {
353353
elementsArray.push(element);
@@ -368,7 +368,7 @@ module.exports = function(Chart) {
368368
if (this.data.datasets) {
369369
for (var i = 0; i < this.data.datasets.length; i++) {
370370
var meta = this.getDatasetMeta(i);
371-
if (helpers.isDatasetVisible(this.data.datasets[i])) {
371+
if (this.isDatasetVisible(i)) {
372372
for (var j = 0; j < meta.data.length; j++) {
373373
if (meta.data[j].inRange(eventPosition.x, eventPosition.y)) {
374374
return meta.data[j];
@@ -384,8 +384,8 @@ module.exports = function(Chart) {
384384
}
385385

386386
helpers.each(this.data.datasets, function(dataset, datasetIndex) {
387-
var meta = this.getDatasetMeta(datasetIndex);
388-
if (helpers.isDatasetVisible(dataset)) {
387+
if (this.isDatasetVisible(datasetIndex)) {
388+
var meta = this.getDatasetMeta(datasetIndex);
389389
elementsArray.push(meta.data[found._index]);
390390
}
391391
}, this);
@@ -416,6 +416,8 @@ module.exports = function(Chart) {
416416
data: [],
417417
dataset: null,
418418
controller: null,
419+
hiddenData: {},
420+
hidden: null, // See isDatasetVisible() comment
419421
xAxisID: null,
420422
yAxisID: null
421423
};
@@ -424,6 +426,24 @@ module.exports = function(Chart) {
424426
return meta;
425427
},
426428

429+
getVisibleDatasetCount: function() {
430+
var count = 0;
431+
for (var i = 0, ilen = this.data.datasets.length; i<ilen; ++i) {
432+
if (this.isDatasetVisible(i)) {
433+
count++;
434+
}
435+
}
436+
return count;
437+
},
438+
439+
isDatasetVisible: function(datasetIndex) {
440+
var meta = this.getDatasetMeta(datasetIndex);
441+
442+
// meta.hidden is a per chart dataset hidden flag override with 3 states: if true or false,
443+
// the dataset.hidden value is ignored, else if null, the dataset hidden state is returned.
444+
return typeof meta.hidden === 'boolean'? !meta.hidden : !this.data.datasets[datasetIndex].hidden;
445+
},
446+
427447
generateLegend: function generateLegend() {
428448
return this.options.legendCallback(this);
429449
},

src/core/core.helpers.js

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -938,9 +938,6 @@ module.exports = function(Chart) {
938938
array.push(element);
939939
}
940940
};
941-
helpers.isDatasetVisible = function(dataset) {
942-
return !dataset.hidden;
943-
};
944941
helpers.callCallback = function(fn, args, _tArg) {
945942
if (fn && typeof fn.call === 'function') {
946943
fn.apply(_tArg, args);

src/core/core.legend.js

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,11 @@ module.exports = function(Chart) {
1313

1414
// a callback that will handle
1515
onClick: function(e, legendItem) {
16-
var dataset = this.chart.data.datasets[legendItem.datasetIndex];
17-
dataset.hidden = !dataset.hidden;
16+
var index = legendItem.datasetIndex;
17+
var meta = this.chart.getDatasetMeta(index);
18+
19+
// See controller.isDatasetVisible comment
20+
meta.hidden = meta.hidden === null? !this.chart.data.datasets[index].hidden : null;
1821

1922
// We hid a dataset ... rerender the chart
2023
this.chart.update();
@@ -40,7 +43,7 @@ module.exports = function(Chart) {
4043
return {
4144
text: dataset.label,
4245
fillStyle: dataset.backgroundColor,
43-
hidden: dataset.hidden,
46+
hidden: !chart.isDatasetVisible(i),
4447
lineCap: dataset.borderCapStyle,
4548
lineDash: dataset.borderDash,
4649
lineDashOffset: dataset.borderDashOffset,

src/core/core.tooltip.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,7 @@ module.exports = function(Chart) {
236236
tooltipPosition = this.getAveragePosition(this._active);
237237
} else {
238238
helpers.each(this._data.datasets, function(dataset, datasetIndex) {
239-
if (!helpers.isDatasetVisible(dataset)) {
239+
if (!this._chartInstance.isDatasetVisible(datasetIndex)) {
240240
return;
241241
}
242242

src/scales/scale.linear.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ module.exports = function(Chart) {
5959
var positiveValues = valuesPerType[meta.type].positiveValues;
6060
var negativeValues = valuesPerType[meta.type].negativeValues;
6161

62-
if (helpers.isDatasetVisible(dataset) && (this.isHorizontal() ? meta.xAxisID === this.id : meta.yAxisID === this.id)) {
62+
if (this.chart.isDatasetVisible(datasetIndex) && (this.isHorizontal() ? meta.xAxisID === this.id : meta.yAxisID === this.id)) {
6363
helpers.each(dataset.data, function(rawValue, index) {
6464

6565
var value = +this.getRightValue(rawValue);
@@ -96,7 +96,7 @@ module.exports = function(Chart) {
9696
} else {
9797
helpers.each(this.chart.data.datasets, function(dataset, datasetIndex) {
9898
var meta = this.chart.getDatasetMeta(datasetIndex);
99-
if (helpers.isDatasetVisible(dataset) && (this.isHorizontal() ? meta.xAxisID === this.id : meta.yAxisID === this.id)) {
99+
if (this.chart.isDatasetVisible(datasetIndex) && (this.isHorizontal() ? meta.xAxisID === this.id : meta.yAxisID === this.id)) {
100100
helpers.each(dataset.data, function(rawValue, index) {
101101
var value = +this.getRightValue(rawValue);
102102
if (isNaN(value)) {

src/scales/scale.logarithmic.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ module.exports = function(Chart) {
3232

3333
helpers.each(this.chart.data.datasets, function(dataset, datasetIndex) {
3434
var meta = this.chart.getDatasetMeta(datasetIndex);
35-
if (helpers.isDatasetVisible(dataset) && (this.isHorizontal() ? meta.xAxisID === this.id : meta.yAxisID === this.id)) {
35+
if (this.chart.isDatasetVisible(datasetIndex) && (this.isHorizontal() ? meta.xAxisID === this.id : meta.yAxisID === this.id)) {
3636
if (valuesPerType[meta.type] === undefined) {
3737
valuesPerType[meta.type] = [];
3838
}
@@ -66,7 +66,7 @@ module.exports = function(Chart) {
6666
} else {
6767
helpers.each(this.chart.data.datasets, function(dataset, datasetIndex) {
6868
var meta = this.chart.getDatasetMeta(datasetIndex);
69-
if (helpers.isDatasetVisible(dataset) && (this.isHorizontal() ? meta.xAxisID === this.id : meta.yAxisID === this.id)) {
69+
if (this.chart.isDatasetVisible(dataset, datasetIndex) && (this.isHorizontal() ? meta.xAxisID === this.id : meta.yAxisID === this.id)) {
7070
helpers.each(dataset.data, function(rawValue, index) {
7171
var value = +this.getRightValue(rawValue);
7272
if (isNaN(value)) {

0 commit comments

Comments
 (0)