Skip to content

Commit 690dd20

Browse files
Filmbostock
andauthored
remove all children (#276)
* remove all children fixes #275 * more defensive copy selectAll * comment array Co-authored-by: Mike Bostock <mbostock@gmail.com>
1 parent 54a3acf commit 690dd20

File tree

6 files changed

+33
-11
lines changed

6 files changed

+33
-11
lines changed

src/array.js

+8-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
1-
export default function(x) {
2-
return typeof x === "object" && "length" in x
3-
? x // Array, TypedArray, NodeList, array-like
4-
: Array.from(x); // Map, Set, iterable, string, or anything else
1+
// Given something array like (or null), returns something that is strictly an
2+
// array. This is used to ensure that array-like objects passed to d3.selectAll
3+
// or selection.selectAll are converted into proper arrays when creating a
4+
// selection; we don’t ever want to create a selection backed by a live
5+
// HTMLCollection or NodeList. However, note that selection.selectAll will use a
6+
// static NodeList as a group, since it safely derived from querySelectorAll.
7+
export default function array(x) {
8+
return x == null ? [] : Array.isArray(x) ? x : Array.from(x);
59
}

src/selectAll.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,5 @@ import {Selection, root} from "./selection/index.js";
44
export default function(selector) {
55
return typeof selector === "string"
66
? new Selection([document.querySelectorAll(selector)], [document.documentElement])
7-
: new Selection([selector == null ? [] : array(selector)], root);
7+
: new Selection([array(selector)], root);
88
}

src/selection/data.js

+13-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import {Selection} from "./index.js";
22
import {EnterNode} from "./enter.js";
3-
import array from "../array.js";
43
import constant from "../constant.js";
54

65
function bindIndex(parent, group, enter, update, exit, data) {
@@ -90,7 +89,7 @@ export default function(value, key) {
9089
var parent = parents[j],
9190
group = groups[j],
9291
groupLength = group.length,
93-
data = array(value.call(parent, parent && parent.__data__, j, parents)),
92+
data = arraylike(value.call(parent, parent && parent.__data__, j, parents)),
9493
dataLength = data.length,
9594
enterGroup = enter[j] = new Array(dataLength),
9695
updateGroup = update[j] = new Array(dataLength),
@@ -115,3 +114,15 @@ export default function(value, key) {
115114
update._exit = exit;
116115
return update;
117116
}
117+
118+
// Given some data, this returns an array-like view of it: an object that
119+
// exposes a length property and allows numeric indexing. Note that unlike
120+
// selectAll, this isn’t worried about “live” collections because the resulting
121+
// array will only be used briefly while data is being bound. (It is possible to
122+
// cause the data to change while iterating by using a key function, but please
123+
// don’t; we’d rather avoid a gratuitous copy.)
124+
function arraylike(data) {
125+
return typeof data === "object" && "length" in data
126+
? data // Array, TypedArray, NodeList, array-like
127+
: Array.from(data); // Map, Set, iterable, string, or anything else
128+
}

src/selection/selectAll.js

+1-2
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,7 @@ import selectorAll from "../selectorAll.js";
44

55
function arrayAll(select) {
66
return function() {
7-
var group = select.apply(this, arguments);
8-
return group == null ? [] : array(group);
7+
return array(select.apply(this, arguments));
98
};
109
}
1110

src/selection/selectChildren.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import {childMatcher} from "../matcher.js";
33
var filter = Array.prototype.filter;
44

55
function children() {
6-
return this.children;
6+
return Array.from(this.children);
77
}
88

99
function childrenFilter(match) {

test/selection/remove-test.js

+9-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import assert from "assert";
2-
import {selectAll} from "../../src/index.js";
2+
import {select, selectAll} from "../../src/index.js";
33
import it from "../jsdom.js";
44

55
it("selection.remove() removes selected elements from their parent", "<h1 id='one'></h1><h1 id='two'></h1>", () => {
@@ -29,3 +29,11 @@ it("selection.remove() skips missing elements", "<h1 id='one'></h1><h1 id='two'>
2929
assert.strictEqual(one.parentNode, null);
3030
assert.strictEqual(two.parentNode, document.body);
3131
});
32+
33+
it("selectChildren().remove() removes all children", "<div><span>0</span><span>1</span><span>2</span><span>3</span><span>4</span><span>5</span><span>6</span><span>7</span><span>8</span><span>9</span></div>", () => {
34+
const p = document.querySelector("div");
35+
const selection = select(p).selectChildren();
36+
assert.strictEqual(selection.size(), 10);
37+
assert.strictEqual(selection.remove(), selection);
38+
assert.strictEqual(select(p).selectChildren().size(), 0);
39+
});

0 commit comments

Comments
 (0)