From: Evert Timberg Date: Wed, 7 Oct 2015 23:54:11 +0000 (-0400) Subject: Update controllers to handle datasets that are not visible X-Git-Tag: 2.0.0-beta~15^2~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b36c8ff7882a766b77e7e79483c165e1dd24fd06;p=thirdparty%2FChart.js.git Update controllers to handle datasets that are not visible --- diff --git a/src/controllers/controller.bar.js b/src/controllers/controller.bar.js index 3ec3be6da..a850269a0 100644 --- a/src/controllers/controller.bar.js +++ b/src/controllers/controller.bar.js @@ -66,15 +66,15 @@ // 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; }, @@ -192,14 +192,16 @@ 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; } } } @@ -225,10 +227,11 @@ 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++) { @@ -266,14 +269,28 @@ }, + // 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) { @@ -283,9 +300,9 @@ 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) { @@ -301,10 +318,13 @@ 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; + } } } diff --git a/src/controllers/controller.doughnut.js b/src/controllers/controller.doughnut.js index da3386e31..4ab485058 100644 --- a/src/controllers/controller.doughnut.js +++ b/src/controllers/controller.doughnut.js @@ -101,18 +101,35 @@ } }, + 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) { diff --git a/src/controllers/controller.polarArea.js b/src/controllers/controller.polarArea.js index c962b9c38..709cc1591 100644 --- a/src/controllers/controller.polarArea.js +++ b/src/controllers/controller.polarArea.js @@ -96,10 +96,14 @@ } }, + 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) { diff --git a/src/core/core.controller.js b/src/core/core.controller.js index 6d8d5e25e..773f54319 100644 --- a/src/core/core.controller.js +++ b/src/core/core.controller.js @@ -260,7 +260,9 @@ // 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 @@ -275,12 +277,14 @@ 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; @@ -291,11 +295,13 @@ 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; @@ -305,15 +311,17 @@ 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 : []; }, diff --git a/test/controller.bar.tests.js b/test/controller.bar.tests.js index d71dc0986..028ed368a 100644 --- a/test/controller.bar.tests.js +++ b/test/controller.bar.tests.js @@ -78,6 +78,39 @@ describe('Bar controller tests', function() { 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: { diff --git a/test/controller.doughnut.tests.js b/test/controller.doughnut.tests.js index d4ff2ff51..29811e111 100644 --- a/test/controller.doughnut.tests.js +++ b/test/controller.doughnut.tests.js @@ -68,6 +68,8 @@ describe('Doughnut controller tests', function() { }, data: { datasets: [{ + hidden: true + }, { data: [10, 15, 0, 4] }, { data: [1] @@ -94,10 +96,10 @@ describe('Doughnut controller tests', function() { } }; - 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, @@ -106,7 +108,7 @@ describe('Doughnut controller tests', function() { 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, @@ -115,7 +117,7 @@ describe('Doughnut controller tests', function() { 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, @@ -124,7 +126,7 @@ describe('Doughnut controller tests', function() { 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, @@ -135,7 +137,7 @@ describe('Doughnut controller tests', function() { 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, @@ -152,7 +154,7 @@ describe('Doughnut controller tests', function() { 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, @@ -169,7 +171,7 @@ describe('Doughnut controller tests', function() { 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, @@ -186,7 +188,7 @@ describe('Doughnut controller tests', function() { 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, @@ -204,24 +206,24 @@ describe('Doughnut controller tests', function() { }); // 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() {