// Get the number of datasets that display bars. We use this to correctly calculate the bar width
getBarCount: function getBarCount() {
var barCount = 0;
-
helpers.each(this.chart.data.datasets, function(dataset) {
- if (dataset.type === 'bar') {
- ++barCount;
- } else if (dataset.type === undefined && this.chart.config.type === 'bar') {
- ++barCount;
+ if (helpers.isDatasetVisible(dataset)) {
+ if (dataset.type === 'bar') {
+ ++barCount;
+ } else if (dataset.type === undefined && this.chart.config.type === 'bar') {
+ ++barCount;
+ }
}
}, this);
-
return barCount;
},
if (value < 0) {
for (var i = 0; i < datasetIndex; i++) {
- if (this.chart.data.datasets[i].yAxisID === yScale.id) {
- base += this.chart.data.datasets[i].data[index] < 0 ? this.chart.data.datasets[i].data[index] : 0;
+ var negDS = this.chart.data.datasets[i];
+ if (helpers.isDatasetVisible(negDS) && negDS.yAxisID === yScale.id) {
+ base += negDS.data[index] < 0 ? negDS.data[index] : 0;
}
}
} else {
for (var j = 0; j < datasetIndex; j++) {
- if (this.chart.data.datasets[j].yAxisID === yScale.id) {
- base += this.chart.data.datasets[j].data[index] > 0 ? this.chart.data.datasets[j].data[index] : 0;
+ var posDS = this.chart.data.datasets[j];
+ if (helpers.isDatasetVisible(posDS) && posDS.yAxisID === yScale.id) {
+ base += posDS.data[index] > 0 ? posDS.data[index] : 0;
}
}
}
var xScale = this.getScaleForID(this.getDataset().xAxisID);
var yScale = this.getScaleForID(this.getDataset().yAxisID);
-
- var datasetCount = !this.chart.isCombo ? this.chart.data.datasets.length : helpers.where(this.chart.data.datasets, function(ds) {
+ /*var datasetCount = !this.chart.isCombo ? this.chart.data.datasets.length : helpers.where(this.chart.data.datasets, function(ds) {
return ds.type == 'bar';
- }).length;
+ }).length;*/
+ var datasetCount = this.getBarCount();
+
var tickWidth = (function() {
var min = xScale.getPixelForValue(null, 1) - xScale.getPixelForValue(null, 0);
for (var i = 2; i < this.getDataset().data.length; i++) {
},
+ // Get bar index from the given dataset index accounting for the fact that not all bars are visible
+ getBarIndex: function(datasetIndex) {
+ var barIndex = 0;
+
+ for (var j = 0; j < datasetIndex; ++j) {
+ if (helpers.isDatasetVisible(this.chart.data.datasets[j]) &&
+ (this.chart.data.datasets[j].type === 'bar' || (this.chart.data.datasets[j].type === undefined && this.chart.config.type === 'bar'))) {
+ ++barIndex;
+ }
+ }
+
+ return barIndex;
+ },
calculateBarX: function(index, datasetIndex) {
var yScale = this.getScaleForID(this.getDataset().yAxisID);
var xScale = this.getScaleForID(this.getDataset().xAxisID);
+ var barIndex = this.getBarIndex(datasetIndex);
var ruler = this.getRuler();
- var leftTick = xScale.getPixelForValue(null, index, datasetIndex, this.chart.isCombo);
+ var leftTick = xScale.getPixelForValue(null, index, barIndex, this.chart.isCombo);
leftTick -= this.chart.isCombo ? (ruler.tickWidth / 2) : 0;
if (yScale.options.stacked) {
return leftTick +
(ruler.barWidth / 2) +
ruler.categorySpacing +
- (ruler.barWidth * datasetIndex) +
+ (ruler.barWidth * barIndex) +
(ruler.barSpacing / 2) +
- (ruler.barSpacing * datasetIndex);
+ (ruler.barSpacing * barIndex);
},
calculateBarY: function(index, datasetIndex) {
sumNeg = 0;
for (var i = 0; i < datasetIndex; i++) {
- if (this.chart.data.datasets[i].data[index] < 0) {
- sumNeg += this.chart.data.datasets[i].data[index] || 0;
- } else {
- sumPos += this.chart.data.datasets[i].data[index] || 0;
+ var ds = this.chart.data.datasets[i];
+ if (helpers.isDatasetVisible(ds)) {
+ if (ds.data[index] < 0) {
+ sumNeg += ds.data[index] || 0;
+ } else {
+ sumPos += ds.data[index] || 0;
+ }
}
}
}
},
+ 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])) {
+ ++ringIndex;
+ }
+ }
+
+ return ringIndex;
+ },
+
update: function update(reset) {
this.chart.outerRadius = Math.max((helpers.min([this.chart.chart.width, this.chart.chart.height]) / 2) - this.chart.options.elements.arc.borderWidth / 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.chart.data.datasets.length;
+ this.chart.radiusLength = (this.chart.outerRadius - this.chart.innerRadius) / this.getVisibleDatasetCount();
this.getDataset().total = 0;
helpers.each(this.getDataset().data, function(value) {
this.getDataset().total += Math.abs(value);
}, this);
- this.outerRadius = this.chart.outerRadius - (this.chart.radiusLength * this.index);
+ this.outerRadius = this.chart.outerRadius - (this.chart.radiusLength * this.getRingIndex(this.index));
this.innerRadius = this.outerRadius - this.chart.radiusLength;
helpers.each(this.getDataset().metaData, function(arc, index) {
}
},
+ getVisibleDatasetCount: function getVisibleDatasetCount() {
+ return helpers.where(this.chart.data.datasets, function(ds) { return helpers.isDatasetVisible(ds); }).length;
+ },
+
update: function update(reset) {
this.chart.outerRadius = Math.max((helpers.min([this.chart.chart.width, this.chart.chart.height]) - 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.chart.data.datasets.length;
+ this.chart.radiusLength = (this.chart.outerRadius - this.chart.innerRadius) / this.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) {
- dataset.controller.draw(ease);
+ if (helpers.isDatasetVisible(dataset)) {
+ dataset.controller.draw(ease);
+ }
}, this);
// Finally draw the tooltip
var elementsArray = [];
helpers.each(this.data.datasets, function(dataset, datasetIndex) {
- helpers.each(dataset.metaData, function(element, index) {
- if (element.inRange(eventPosition.x, eventPosition.y)) {
- elementsArray.push(element);
- return elementsArray;
- }
- }, this);
+ if (helpers.isDatasetVisible(dataset)) {
+ helpers.each(dataset.metaData, function(element, index) {
+ if (element.inRange(eventPosition.x, eventPosition.y)) {
+ elementsArray.push(element);
+ return elementsArray;
+ }
+ }, this);
+ }
}, this);
return elementsArray;
var elementsArray = [];
helpers.each(this.data.datasets, function(dataset, datasetIndex) {
- helpers.each(dataset.metaData, function(element, index) {
- if (element.inLabelRange(eventPosition.x, eventPosition.y)) {
- elementsArray.push(element);
- }
- }, this);
+ if (helpers.isDatasetVisible(dataset)) {
+ helpers.each(dataset.metaData, function(element, index) {
+ if (element.inLabelRange(eventPosition.x, eventPosition.y)) {
+ elementsArray.push(element);
+ }
+ }, this);
+ }
}, this);
return elementsArray;
var eventPosition = helpers.getRelativePosition(e, this.chart);
var elementsArray = [];
- for (var datasetIndex = 0; datasetIndex < this.data.datasets.length; datasetIndex++) {
- for (var elementIndex = 0; elementIndex < this.data.datasets[datasetIndex].metaData.length; elementIndex++) {
- if (this.data.datasets[datasetIndex].metaData[elementIndex].inLabelRange(eventPosition.x, eventPosition.y)) {
- helpers.each(this.data.datasets[datasetIndex].metaData, function(element, index) {
- elementsArray.push(element);
- }, this);
+ helpers.each(this.data.datasets, function(dataset, datasetIndex) {
+ if (helpers.isDatasetVisible(dataset)) {
+ for (var elementIndex = 0; elementIndex < dataset.metaData.length; elementIndex++) {
+ if (dataset.metaData[elementIndex].inLabelRange(eventPosition.x, eventPosition.y)) {
+ helpers.each(dataset.metaData, function(element, index) {
+ elementsArray.push(element);
+ }, this);
+ }
}
}
- }
+ }, this);
return elementsArray.length ? elementsArray : [];
},
expect(controller.getBarCount()).toBe(2);
});
+ it('should correctly get the bar index accounting for hidden datasets', function() {
+ var chart = {
+ data: {
+ datasets: [{
+
+ }, {
+ hidden: true
+ }, {
+ type: 'line'
+ }, {
+
+ }]
+ },
+ config: {
+ type: 'bar'
+ },
+ options: {
+ scales: {
+ xAxes: [{
+ id: 'firstXScaleID'
+ }],
+ yAxes: [{
+ id: 'firstYScaleID'
+ }]
+ }
+ }
+ };
+
+ var controller = new Chart.controllers.bar(chart, 1);
+ expect(controller.getBarIndex(0)).toBe(0);
+ expect(controller.getBarIndex(3)).toBe(1);
+ });
+
it('Should create rectangle elements for each data item during initialization', function() {
var chart = {
data: {
},
data: {
datasets: [{
+ hidden: true
+ }, {
data: [10, 15, 0, 4]
}, {
data: [1]
}
};
- var controller = new Chart.controllers.doughnut(chart, 0);
+ var controller = new Chart.controllers.doughnut(chart, 1);
controller.reset(); // reset first
- expect(chart.data.datasets[0].metaData[0]._model).toEqual({
+ expect(chart.data.datasets[1].metaData[0]._model).toEqual({
x: 50,
y: 100,
startAngle: Math.PI * -0.5,
innerRadius: 36.75,
});
- expect(chart.data.datasets[0].metaData[1]._model).toEqual({
+ expect(chart.data.datasets[1].metaData[1]._model).toEqual({
x: 50,
y: 100,
startAngle: Math.PI * -0.5,
innerRadius: 36.75,
});
- expect(chart.data.datasets[0].metaData[2]._model).toEqual({
+ expect(chart.data.datasets[1].metaData[2]._model).toEqual({
x: 50,
y: 100,
startAngle: Math.PI * -0.5,
innerRadius: 36.75,
});
- expect(chart.data.datasets[0].metaData[3]._model).toEqual({
+ expect(chart.data.datasets[1].metaData[3]._model).toEqual({
x: 50,
y: 100,
startAngle: Math.PI * -0.5,
controller.update();
- expect(chart.data.datasets[0].metaData[0]._model).toEqual({
+ expect(chart.data.datasets[1].metaData[0]._model).toEqual({
x: 50,
y: 100,
startAngle: Math.PI * -0.5,
label: 'label0',
});
- expect(chart.data.datasets[0].metaData[1]._model).toEqual({
+ expect(chart.data.datasets[1].metaData[1]._model).toEqual({
x: 50,
y: 100,
startAngle: 0.5958182130626666,
label: 'label1'
});
- expect(chart.data.datasets[0].metaData[2]._model).toEqual({
+ expect(chart.data.datasets[1].metaData[2]._model).toEqual({
x: 50,
y: 100,
startAngle: 3.8457400228490113,
label: 'label2'
});
- expect(chart.data.datasets[0].metaData[3]._model).toEqual({
+ expect(chart.data.datasets[1].metaData[3]._model).toEqual({
x: 50,
y: 100,
startAngle: 3.8457400228490113,
});
// Change the amount of data and ensure that arcs are updated accordingly
- chart.data.datasets[0].data = [1, 2]; // remove 2 elements from dataset 0
+ chart.data.datasets[1].data = [1, 2]; // remove 2 elements from dataset 0
controller.buildOrUpdateElements();
controller.update();
- expect(chart.data.datasets[0].metaData.length).toBe(2);
- expect(chart.data.datasets[0].metaData[0] instanceof Chart.elements.Arc).toBe(true);
- expect(chart.data.datasets[0].metaData[1] instanceof Chart.elements.Arc).toBe(true);
+ expect(chart.data.datasets[1].metaData.length).toBe(2);
+ expect(chart.data.datasets[1].metaData[0] instanceof Chart.elements.Arc).toBe(true);
+ expect(chart.data.datasets[1].metaData[1] instanceof Chart.elements.Arc).toBe(true);
// Add data
- chart.data.datasets[0].data = [1, 2, 3, 4];
+ chart.data.datasets[1].data = [1, 2, 3, 4];
controller.buildOrUpdateElements();
controller.update();
- expect(chart.data.datasets[0].metaData.length).toBe(4);
- expect(chart.data.datasets[0].metaData[0] instanceof Chart.elements.Arc).toBe(true);
- expect(chart.data.datasets[0].metaData[1] instanceof Chart.elements.Arc).toBe(true);
- expect(chart.data.datasets[0].metaData[2] instanceof Chart.elements.Arc).toBe(true);
- expect(chart.data.datasets[0].metaData[3] instanceof Chart.elements.Arc).toBe(true);
+ expect(chart.data.datasets[1].metaData.length).toBe(4);
+ expect(chart.data.datasets[1].metaData[0] instanceof Chart.elements.Arc).toBe(true);
+ expect(chart.data.datasets[1].metaData[1] instanceof Chart.elements.Arc).toBe(true);
+ expect(chart.data.datasets[1].metaData[2] instanceof Chart.elements.Arc).toBe(true);
+ expect(chart.data.datasets[1].metaData[3] instanceof Chart.elements.Arc).toBe(true);
});
it ('should draw all arcs', function() {