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.
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);
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;
}
}
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;
}
}
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;
}
}
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 {
}
},
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();
}
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;
}
}
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;
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 {
}
},
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();
}
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) {
// 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);
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);
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];
}
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);
data: [],
dataset: null,
controller: null,
+ hiddenData: {},
+ hidden: null, // See isDatasetVisible() comment
xAxisID: null,
yAxisID: null
};
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);
},
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);
// 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();
return {
text: dataset.label,
fillStyle: dataset.backgroundColor,
- hidden: dataset.hidden,
+ hidden: !chart.isDatasetVisible(i),
lineCap: dataset.borderCapStyle,
lineDash: dataset.borderDash,
lineDashOffset: dataset.borderDashOffset,
tooltipPosition = this.getAveragePosition(this._active);
} else {
helpers.each(this._data.datasets, function(dataset, datasetIndex) {
- if (!helpers.isDatasetVisible(dataset)) {
+ if (!this._chartInstance.isDatasetVisible(datasetIndex)) {
return;
}
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);
} 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)) {
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] = [];
}
} 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)) {
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)) {
}
// 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);