From 62a6211592ec7eb344864a72100f1254c824879a Mon Sep 17 00:00:00 2001 From: Mike Bostock Date: Sat, 16 Nov 2019 15:37:18 -0800 Subject: [PATCH] Pass index when traversing. --- README.md | 12 ++++++------ src/hierarchy/each.js | 12 +++++++----- src/hierarchy/eachAfter.js | 14 ++++++++------ src/hierarchy/eachBefore.js | 12 +++++++----- 4 files changed, 28 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index 07ce2b10..c2a2e800 100644 --- a/README.md +++ b/README.md @@ -174,17 +174,17 @@ root You must call *node*.sort before invoking a hierarchical layout if you want the new sort order to affect the layout; see [*node*.sum](#node_sum) for an example. -# node.each(function) · [Source](https://github.com/d3/d3-hierarchy/blob/master/src/hierarchy/each.js), [Examples](https://observablehq.com/@d3/visiting-a-d3-hierarchy) +# node.each(function[, that]) · [Source](https://github.com/d3/d3-hierarchy/blob/master/src/hierarchy/each.js), [Examples](https://observablehq.com/@d3/visiting-a-d3-hierarchy) -Invokes the specified *function* for *node* and each descendant in [breadth-first order](https://en.wikipedia.org/wiki/Breadth-first_search), such that a given *node* is only visited if all nodes of lesser depth have already been visited, as well as all preceding nodes of the same depth. The specified function is passed the current *node*. +Invokes the specified *function* for *node* and each descendant in [breadth-first order](https://en.wikipedia.org/wiki/Breadth-first_search), such that a given *node* is only visited if all nodes of lesser depth have already been visited, as well as all preceding nodes of the same depth. The specified function is passed the current *descendant*, the zero-based traversal *index*, and this *node*. If *that* is specified, it is the this context of the callback. -# node.eachAfter(function) · [Source](https://github.com/d3/d3-hierarchy/blob/master/src/hierarchy/eachAfter.js), [Examples](https://observablehq.com/@d3/visiting-a-d3-hierarchy) +# node.eachAfter(function[, that]) · [Source](https://github.com/d3/d3-hierarchy/blob/master/src/hierarchy/eachAfter.js), [Examples](https://observablehq.com/@d3/visiting-a-d3-hierarchy) -Invokes the specified *function* for *node* and each descendant in [post-order traversal](https://en.wikipedia.org/wiki/Tree_traversal#Post-order), such that a given *node* is only visited after all of its descendants have already been visited. The specified function is passed the current *node*. +Invokes the specified *function* for *node* and each descendant in [post-order traversal](https://en.wikipedia.org/wiki/Tree_traversal#Post-order), such that a given *node* is only visited after all of its descendants have already been visited. The specified function is passed the current *descendant*, the zero-based traversal *index*, and this *node*. If *that* is specified, it is the this context of the callback. -# node.eachBefore(function) · [Source](https://github.com/d3/d3-hierarchy/blob/master/src/hierarchy/eachBefore.js), [Examples](https://observablehq.com/@d3/visiting-a-d3-hierarchy) +# node.eachBefore(function[, that]) · [Source](https://github.com/d3/d3-hierarchy/blob/master/src/hierarchy/eachBefore.js), [Examples](https://observablehq.com/@d3/visiting-a-d3-hierarchy) -Invokes the specified *function* for *node* and each descendant in [pre-order traversal](https://en.wikipedia.org/wiki/Tree_traversal#Pre-order), such that a given *node* is only visited after all of its ancestors have already been visited. The specified function is passed the current *node*. +Invokes the specified *function* for *node* and each descendant in [pre-order traversal](https://en.wikipedia.org/wiki/Tree_traversal#Pre-order), such that a given *node* is only visited after all of its ancestors have already been visited. The specified function is passed the current *descendant*, the zero-based traversal *index*, and this *node*. If *that* is specified, it is the this context of the callback. # node.copy() · [Source](https://github.com/d3/d3-hierarchy/blob/master/src/hierarchy/index.js), [Examples](https://observablehq.com/@d3/d3-hierarchy) diff --git a/src/hierarchy/each.js b/src/hierarchy/each.js index 767e2da1..f1a9bad8 100644 --- a/src/hierarchy/each.js +++ b/src/hierarchy/each.js @@ -1,11 +1,13 @@ -export default function(callback) { - var node = this, current, next = [node], children, i, n; +export default function(callback, that) { + var node = this, current, next = [node], children, i, n, index = -1; do { current = next.reverse(), next = []; while (node = current.pop()) { - callback(node), children = node.children; - if (children) for (i = 0, n = children.length; i < n; ++i) { - next.push(children[i]); + callback.call(that, node, ++index, this); + if (children = node.children) { + for (i = 0, n = children.length; i < n; ++i) { + next.push(children[i]); + } } } } while (next.length); diff --git a/src/hierarchy/eachAfter.js b/src/hierarchy/eachAfter.js index 4ad4f15c..a3f0a2c0 100644 --- a/src/hierarchy/eachAfter.js +++ b/src/hierarchy/eachAfter.js @@ -1,13 +1,15 @@ -export default function(callback) { - var node = this, nodes = [node], next = [], children, i, n; +export default function(callback, that) { + var node = this, nodes = [node], next = [], children, i, n, index = -1; while (node = nodes.pop()) { - next.push(node), children = node.children; - if (children) for (i = 0, n = children.length; i < n; ++i) { - nodes.push(children[i]); + next.push(node); + if (children = node.children) { + for (i = 0, n = children.length; i < n; ++i) { + nodes.push(children[i]); + } } } while (node = next.pop()) { - callback(node); + callback.call(that, node, ++index, this); } return this; } diff --git a/src/hierarchy/eachBefore.js b/src/hierarchy/eachBefore.js index 23c5ccd2..f3cd524b 100644 --- a/src/hierarchy/eachBefore.js +++ b/src/hierarchy/eachBefore.js @@ -1,9 +1,11 @@ -export default function(callback) { - var node = this, nodes = [node], children, i; +export default function(callback, that) { + var node = this, nodes = [node], children, i, index = -1; while (node = nodes.pop()) { - callback(node), children = node.children; - if (children) for (i = children.length - 1; i >= 0; --i) { - nodes.push(children[i]); + callback.call(that, node, ++index, this); + if (children = node.children) { + for (i = children.length - 1; i >= 0; --i) { + nodes.push(children[i]); + } } } return this;