Skip to content

Commit

Permalink
remove all children (#276)
Browse files Browse the repository at this point in the history
* remove all children

fixes #275

* more defensive copy selectAll

* comment array

Co-authored-by: Mike Bostock <mbostock@gmail.com>
  • Loading branch information
Fil and mbostock authored Jun 7, 2021
1 parent 54a3acf commit 690dd20
Show file tree
Hide file tree
Showing 6 changed files with 33 additions and 11 deletions.
12 changes: 8 additions & 4 deletions src/array.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
export default function(x) {
return typeof x === "object" && "length" in x
? x // Array, TypedArray, NodeList, array-like
: Array.from(x); // Map, Set, iterable, string, or anything else
// Given something array like (or null), returns something that is strictly an
// array. This is used to ensure that array-like objects passed to d3.selectAll
// or selection.selectAll are converted into proper arrays when creating a
// selection; we don’t ever want to create a selection backed by a live
// HTMLCollection or NodeList. However, note that selection.selectAll will use a
// static NodeList as a group, since it safely derived from querySelectorAll.
export default function array(x) {
return x == null ? [] : Array.isArray(x) ? x : Array.from(x);
}
2 changes: 1 addition & 1 deletion src/selectAll.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@ import {Selection, root} from "./selection/index.js";
export default function(selector) {
return typeof selector === "string"
? new Selection([document.querySelectorAll(selector)], [document.documentElement])
: new Selection([selector == null ? [] : array(selector)], root);
: new Selection([array(selector)], root);
}
15 changes: 13 additions & 2 deletions src/selection/data.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import {Selection} from "./index.js";
import {EnterNode} from "./enter.js";
import array from "../array.js";
import constant from "../constant.js";

function bindIndex(parent, group, enter, update, exit, data) {
Expand Down Expand Up @@ -90,7 +89,7 @@ export default function(value, key) {
var parent = parents[j],
group = groups[j],
groupLength = group.length,
data = array(value.call(parent, parent && parent.__data__, j, parents)),
data = arraylike(value.call(parent, parent && parent.__data__, j, parents)),
dataLength = data.length,
enterGroup = enter[j] = new Array(dataLength),
updateGroup = update[j] = new Array(dataLength),
Expand All @@ -115,3 +114,15 @@ export default function(value, key) {
update._exit = exit;
return update;
}

// Given some data, this returns an array-like view of it: an object that
// exposes a length property and allows numeric indexing. Note that unlike
// selectAll, this isn’t worried about “live” collections because the resulting
// array will only be used briefly while data is being bound. (It is possible to
// cause the data to change while iterating by using a key function, but please
// don’t; we’d rather avoid a gratuitous copy.)
function arraylike(data) {
return typeof data === "object" && "length" in data
? data // Array, TypedArray, NodeList, array-like
: Array.from(data); // Map, Set, iterable, string, or anything else
}
3 changes: 1 addition & 2 deletions src/selection/selectAll.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@ import selectorAll from "../selectorAll.js";

function arrayAll(select) {
return function() {
var group = select.apply(this, arguments);
return group == null ? [] : array(group);
return array(select.apply(this, arguments));
};
}

Expand Down
2 changes: 1 addition & 1 deletion src/selection/selectChildren.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {childMatcher} from "../matcher.js";
var filter = Array.prototype.filter;

function children() {
return this.children;
return Array.from(this.children);
}

function childrenFilter(match) {
Expand Down
10 changes: 9 additions & 1 deletion test/selection/remove-test.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import assert from "assert";
import {selectAll} from "../../src/index.js";
import {select, selectAll} from "../../src/index.js";
import it from "../jsdom.js";

it("selection.remove() removes selected elements from their parent", "<h1 id='one'></h1><h1 id='two'></h1>", () => {
Expand Down Expand Up @@ -29,3 +29,11 @@ it("selection.remove() skips missing elements", "<h1 id='one'></h1><h1 id='two'>
assert.strictEqual(one.parentNode, null);
assert.strictEqual(two.parentNode, document.body);
});

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>", () => {
const p = document.querySelector("div");
const selection = select(p).selectChildren();
assert.strictEqual(selection.size(), 10);
assert.strictEqual(selection.remove(), selection);
assert.strictEqual(select(p).selectChildren().size(), 0);
});

0 comments on commit 690dd20

Please sign in to comment.