Skip to content

Commit ff50849

Browse files
committed
Do not allow to select() or hover() non-existing points
1 parent 8bfefd3 commit ff50849

3 files changed

Lines changed: 56 additions & 14 deletions

File tree

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
## Next
22

3+
## v0.18.4
4+
5+
- Fix an issues when programmatically trying to `select()` or `hover()` non-existing points
6+
37
## v0.18.3
48

59
- Harmonize `hover(pointIdx, { showReticleOnce, preventEvent })` with `select()` API by allowing it to prevent the `pointover` and `pointout` from being published.

src/index.js

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -632,25 +632,35 @@ const createScatterplot = (initialProperties = {}) => {
632632
};
633633

634634
const select = (pointIdxs, { merge = false, preventEvent = false } = {}) => {
635+
const pointIdxsArr = Array.isArray(pointIdxs) ? pointIdxs : [pointIdxs];
636+
635637
if (merge) {
636-
selection = unionIntegers(selection, pointIdxs);
638+
selection = unionIntegers(selection, pointIdxsArr);
637639
} else {
638640
// Unset previously highlight point connections
639641
if (selection && selection.length)
640642
setPointConnectionColorState(selection, 0);
641-
selection = pointIdxs;
643+
selection = pointIdxsArr;
642644
}
643645

644-
const selectionBuffer = new Float32Array(selection.length * 2);
646+
const selectionBuffer = [];
645647

646648
selectionSet.clear();
647649
selectionConnecionSet.clear();
648-
selection.forEach((pointIdx, i) => {
649-
selectionSet.add(pointIdx);
650-
const texCoords = indexToStateTexCoord(pointIdx);
651-
selectionBuffer[i * 2] = texCoords[0];
652-
selectionBuffer[i * 2 + 1] = texCoords[1];
653-
});
650+
651+
for (let i = selection.length - 1; i >= 0; i--) {
652+
const pointIdx = selection[i];
653+
654+
if (pointIdx < 0 || pointIdx >= numPoints) {
655+
// Remove invalid selection
656+
selection.splice(i, 1);
657+
} else {
658+
selectionSet.add(pointIdx);
659+
const texCoords = indexToStateTexCoord(pointIdx);
660+
selectionBuffer.push(texCoords[0]);
661+
selectionBuffer.push(texCoords[1]);
662+
}
663+
}
654664

655665
selectedPointsIndexBuffer({
656666
usage: 'dynamic',
@@ -2606,7 +2616,7 @@ const createScatterplot = (initialProperties = {}) => {
26062616
) => {
26072617
let needsRedraw = false;
26082618

2609-
if (point >= 0) {
2619+
if (point >= 0 && point < numPoints) {
26102620
needsRedraw = true;
26112621
const oldHoveredPoint = hoveredPoint;
26122622
const newHoveredPoint = point !== hoveredPoint;

tests/index.js

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1690,8 +1690,9 @@ test('select()', async (t) => {
16901690

16911691
await wait(0);
16921692

1693-
t.ok(
1694-
flatArrayEqual([0, 2, 4], selectedPoints),
1693+
t.deepEqual(
1694+
selectedPoints,
1695+
[0, 2, 4],
16951696
'should have selected point 0, 2, and 4'
16961697
);
16971698

@@ -1716,11 +1717,38 @@ test('select()', async (t) => {
17161717

17171718
await wait(0);
17181719

1719-
t.ok(
1720-
flatArrayEqual([0, 2, 4], selectedPoints),
1720+
t.deepEqual(
1721+
selectedPoints,
1722+
[0, 2, 4],
17211723
'should have silently deselected points'
17221724
);
17231725

1726+
scatterplot.select(2);
1727+
1728+
await wait(0);
1729+
1730+
t.deepEqual(selectedPoints, [2], 'should allow single point index selection');
1731+
1732+
scatterplot.select(-1);
1733+
1734+
await wait(0);
1735+
1736+
t.deepEqual(
1737+
selectedPoints,
1738+
[],
1739+
'should have not selected any point because -1 is invalid'
1740+
);
1741+
1742+
scatterplot.select([0, -1, 2, 4, 6]);
1743+
1744+
await wait(0);
1745+
1746+
t.deepEqual(
1747+
selectedPoints,
1748+
[0, 2, 4],
1749+
'should have filtered out invalid point selections'
1750+
);
1751+
17241752
scatterplot.destroy();
17251753
});
17261754

0 commit comments

Comments
 (0)