Skip to content

Commit

Permalink
Use global element hidden status for Pie charts (#7156)
Browse files Browse the repository at this point in the history
Use global element hidden status for Pie / polarArea charts
  • Loading branch information
kurkle authored Mar 1, 2020
1 parent 3b915cb commit a3dddb4
Show file tree
Hide file tree
Showing 9 changed files with 52 additions and 55 deletions.
17 changes: 17 additions & 0 deletions docs/developers/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,23 @@ chart.setDataVisibility(0, 2, false); // hides the item in dataset 0, at index 2
chart.update(); // chart now renders with item hidden
```

## toggleDataVisibility(index)

Toggles the visibility of an item in all datasets. A dataset needs to explicitly support this feature for it to have an effect. From internal chart types, doughnut / pie and polar area use this.

```javascript
chart.toggleDataVisibility(2); // toggles the item in all datasets, at index 2
chart.update(); // chart now renders with item hidden
```

## getDataVisibility(index)

Returns the stored visibility state of an data index for all datasets. Set by [toggleDataVisibility](#toggleDataVisibility). A dataset controller should use this method to determine if an item should not be visible.

```javascript
var visible = chart.getDataVisibility(2);
```

## hide(datasetIndex)

Sets the visibility for the given dataset to false. Updates the chart and animates the dataset with `'hide'` mode. This animation can be configured under the `hide` key in animation options. Please see [animations](../configuration/animations.md) docs for more details.
Expand Down
1 change: 1 addition & 0 deletions docs/getting-started/v3-migration.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ Animation system was completely rewritten in Chart.js v3. Each property can now
* `DatasetController.createMetaDataset`
* `Element.getArea`
* `Element.height`
* `Element.hidden` was replaced by chart level status, usable with `getDataVisibility(index)` / `toggleDataVisibility(index)`
* `Element.initialize`
* `Element.inLabelRange`
* `helpers.addEvent`
Expand Down
21 changes: 5 additions & 16 deletions src/controllers/controller.doughnut.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ defaults.set('doughnut', {
fillStyle: style.backgroundColor,
strokeStyle: style.borderColor,
lineWidth: style.borderWidth,
hidden: isNaN(data.datasets[0].data[i]) || meta.data[i].hidden,
hidden: !chart.getDataVisibility(i),

// Extra data used for toggling the correct item
index: i
Expand All @@ -48,19 +48,8 @@ defaults.set('doughnut', {
},

onClick(e, legendItem) {
const index = legendItem.index;
const chart = this.chart;
let i, ilen, meta;

for (i = 0, ilen = (chart.data.datasets || []).length; i < ilen; ++i) {
meta = chart.getDatasetMeta(i);
// toggle visibility of index if exists
if (meta.data[index]) {
meta.data[index].hidden = !meta.data[index].hidden;
}
}

chart.update();
this.chart.toggleDataVisibility(legendItem.index);
this.chart.update();
}
},

Expand Down Expand Up @@ -202,7 +191,7 @@ export default class DoughnutController extends DatasetController {
const me = this;
const opts = me.chart.options;
const meta = me._cachedMeta;
return reset && opts.animation.animateRotate ? 0 : meta.data[i].hidden ? 0 : me.calculateCircumference(meta._parsed[i] * opts.circumference / DOUBLE_PI);
return reset && opts.animation.animateRotate ? 0 : this.chart.getDataVisibility(i) ? me.calculateCircumference(meta._parsed[i] * opts.circumference / DOUBLE_PI) : 0;
}

updateElements(arcs, start, mode) {
Expand Down Expand Up @@ -258,7 +247,7 @@ export default class DoughnutController extends DatasetController {

for (i = 0; i < metaData.length; i++) {
const value = meta._parsed[i];
if (!isNaN(value) && !metaData[i].hidden) {
if (!isNaN(value) && this.chart.getDataVisibility(i)) {
total += Math.abs(value);
}
}
Expand Down
20 changes: 6 additions & 14 deletions src/controllers/controller.polarArea.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ defaults.set('polarArea', {
fillStyle: style.backgroundColor,
strokeStyle: style.borderColor,
lineWidth: style.borderWidth,
hidden: isNaN(data.datasets[0].data[i]) || meta.data[i].hidden,
hidden: !chart.getDataVisibility(i),

// Extra data used for toggling the correct item
index: i
Expand All @@ -56,16 +56,8 @@ defaults.set('polarArea', {
},

onClick(e, legendItem) {
const index = legendItem.index;
const chart = this.chart;
let i, ilen, meta;

for (i = 0, ilen = (chart.data.datasets || []).length; i < ilen; ++i) {
meta = chart.getDatasetMeta(i);
meta.data[index].hidden = !meta.data[index].hidden;
}

chart.update();
this.chart.toggleDataVisibility(legendItem.index);
this.chart.update();
}
},

Expand Down Expand Up @@ -160,7 +152,7 @@ export default class PolarAreaController extends DatasetController {
const index = start + i;
let startAngle = angle;
let endAngle = angle + me._computeAngle(index);
let outerRadius = arc.hidden ? 0 : scale.getDistanceFromCenterForValue(dataset.data[index]);
let outerRadius = this.chart.getDataVisibility(index) ? scale.getDistanceFromCenterForValue(dataset.data[index]) : 0;
angle = endAngle;

if (reset) {
Expand Down Expand Up @@ -193,7 +185,7 @@ export default class PolarAreaController extends DatasetController {
let count = 0;

meta.data.forEach((element, index) => {
if (!isNaN(dataset.data[index]) && !element.hidden) {
if (!isNaN(dataset.data[index]) && this.chart.getDataVisibility(index)) {
count++;
}
});
Expand All @@ -210,7 +202,7 @@ export default class PolarAreaController extends DatasetController {
const count = meta.count;
const dataset = me.getDataset();

if (isNaN(dataset.data[index]) || meta.data[index].hidden) {
if (isNaN(dataset.data[index]) || !this.chart.getDataVisibility(index)) {
return 0;
}

Expand Down
11 changes: 6 additions & 5 deletions src/core/core.controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,7 @@ export default class Chart {
this.scale = undefined;
this.$plugins = undefined;
this.$proxies = {};
this._hiddenIndices = {};

// Add the chart instance to the global namespace
Chart.instances[me.id] = me;
Expand Down Expand Up @@ -864,12 +865,12 @@ export default class Chart {
meta.hidden = !visible;
}

setDataVisibility(datasetIndex, index, visible) {
const meta = this.getDatasetMeta(datasetIndex);
toggleDataVisibility(index) {
this._hiddenIndices[index] = !this._hiddenIndices[index];
}

if (meta.data[index]) {
meta.data[index].hidden = !visible;
}
getDataVisibility(index) {
return !this._hiddenIndices[index];
}

/**
Expand Down
7 changes: 3 additions & 4 deletions src/core/core.datasetController.js
Original file line number Diff line number Diff line change
Expand Up @@ -624,15 +624,15 @@ export default class DatasetController {
*/
getMinMax(scale, canStack) {
const meta = this._cachedMeta;
const {data, _parsed} = meta;
const _parsed = meta._parsed;
const sorted = meta._sorted && scale === meta.iScale;
const ilen = _parsed.length;
const otherScale = this._getOtherScale(scale);
const stack = canStack && meta._stacked && {keys: getSortedDatasetIndices(this.chart, true), values: null};
let min = Number.POSITIVE_INFINITY;
let max = Number.NEGATIVE_INFINITY;
const {min: otherMin, max: otherMax} = getUserBounds(otherScale);
let i, item, value, parsed, otherValue;
let i, value, parsed, otherValue;

function _compute() {
if (stack) {
Expand All @@ -648,11 +648,10 @@ export default class DatasetController {
}

function _skip() {
item = data[i];
parsed = _parsed[i];
value = parsed[scale.axis];
otherValue = parsed[otherScale.axis];
return ((item && item.hidden) || isNaN(value) || otherMin > otherValue || otherMax < otherValue);
return (isNaN(value) || otherMin > otherValue || otherMax < otherValue);
}

for (i = 0; i < ilen; ++i) {
Expand Down
1 change: 0 additions & 1 deletion src/core/core.element.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ export default class Element {
constructor(cfg) {
this.x = undefined;
this.y = undefined;
this.hidden = false;
this.active = false;
this.options = undefined;
this.$animations = undefined;
Expand Down
13 changes: 8 additions & 5 deletions test/specs/core.controller.tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -1365,20 +1365,23 @@ describe('Chart', function() {
expect(meta.hidden).toBe(true);
});

it('should hide a single data item', function() {
it('should toggle data visibility by index', function() {
var chart = acquireChart({
type: 'polarArea',
type: 'pie',
data: {
datasets: [{
data: [1, 2, 3]
}]
}
});

chart.setDataVisibility(0, 1, false);
expect(chart.getDataVisibility(1)).toBe(true);

var meta = chart.getDatasetMeta(0);
expect(meta.data[1].hidden).toBe(true);
chart.toggleDataVisibility(1);
expect(chart.getDataVisibility(1)).toBe(false);

chart.update();
expect(chart.getDataVisibility(1)).toBe(false);
});
});
});
16 changes: 6 additions & 10 deletions test/specs/global.defaults.tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ describe('Default Configs', function() {
}, {
text: 'label3',
fillStyle: 'blue',
hidden: true,
hidden: false,
index: 2,
strokeStyle: '#000',
lineWidth: 2
Expand All @@ -144,18 +144,16 @@ describe('Default Configs', function() {
},
options: config
});
var meta = chart.getDatasetMeta(0);

spyOn(chart, 'update').and.callThrough();

var legendItem = chart.legend.legendItems[0];
config.legend.onClick.call(chart.legend, null, legendItem);

expect(meta.data[0].hidden).toBe(true);
expect(chart.getDataVisibility(0)).toBe(false);
expect(chart.update).toHaveBeenCalled();

config.legend.onClick.call(chart.legend, null, legendItem);
expect(meta.data[0].hidden).toBe(false);
expect(chart.getDataVisibility(0)).toBe(true);
});
});

Expand Down Expand Up @@ -219,7 +217,7 @@ describe('Default Configs', function() {
}, {
text: 'label3',
fillStyle: 'blue',
hidden: true,
hidden: false,
index: 2,
strokeStyle: '#000',
lineWidth: 2
Expand All @@ -242,18 +240,16 @@ describe('Default Configs', function() {
},
options: config
});
var meta = chart.getDatasetMeta(0);

spyOn(chart, 'update').and.callThrough();

var legendItem = chart.legend.legendItems[0];
config.legend.onClick.call(chart.legend, null, legendItem);

expect(meta.data[0].hidden).toBe(true);
expect(chart.getDataVisibility(0)).toBe(false);
expect(chart.update).toHaveBeenCalled();

config.legend.onClick.call(chart.legend, null, legendItem);
expect(meta.data[0].hidden).toBe(false);
expect(chart.getDataVisibility(0)).toBe(true);
});
});
});

0 comments on commit a3dddb4

Please sign in to comment.