d3.layout.hierarchy = function() { var sort = d3_layout_hierarchySort, children = d3_layout_hierarchyChildren, value = d3_layout_hierarchyValue; // Recursively compute the node depth and value. // Also converts the data representation into a standard hierarchy structure. function recurse(data, depth, nodes) { var childs = children.call(hierarchy, data, depth), node = d3_layout_hierarchyInline ? data : {data: data}; node.depth = depth; nodes.push(node); if (childs) { var i = -1, n = childs.length, c = node.children = [], v = 0, j = depth + 1; while (++i < n) { d = recurse(childs[i], j, nodes); d.parent = node; c.push(d); v += d.value; } if (sort) c.sort(sort); if (value) node.value = v; } else if (value) { node.value = +value.call(hierarchy, data, depth) || 0; } return node; } // Recursively re-evaluates the node value. function revalue(node, depth) { var children = node.children, v = 0; if (children) { var i = -1, n = children.length, j = depth + 1; while (++i < n) v += revalue(children[i], j); } else if (value) { v = +value.call(hierarchy, d3_layout_hierarchyInline ? node : node.data, depth) || 0; } if (value) node.value = v; return v; } function hierarchy(d) { var nodes = []; recurse(d, 0, nodes); return nodes; } hierarchy.sort = function(x) { if (!arguments.length) return sort; sort = x; return hierarchy; }; hierarchy.children = function(x) { if (!arguments.length) return children; children = x; return hierarchy; }; hierarchy.value = function(x) { if (!arguments.length) return value; value = x; return hierarchy; }; // Re-evaluates the `value` property for the specified hierarchy. hierarchy.revalue = function(root) { revalue(root, 0); return root; }; return hierarchy; }; // A method assignment helper for hierarchy subclasses. function d3_layout_hierarchyRebind(object, hierarchy) { object.sort = d3.rebind(object, hierarchy.sort); object.children = d3.rebind(object, hierarchy.children); object.links = d3_layout_hierarchyLinks; object.value = d3.rebind(object, hierarchy.value); // If the new API is used, enabling inlining. object.nodes = function(d) { d3_layout_hierarchyInline = true; return (object.nodes = object)(d); }; return object; } function d3_layout_hierarchyChildren(d) { return d.children; } function d3_layout_hierarchyValue(d) { return d.value; } function d3_layout_hierarchySort(a, b) { return b.value - a.value; } // Returns an array source+target objects for the specified nodes. function d3_layout_hierarchyLinks(nodes) { return d3.merge(nodes.map(function(parent) { return (parent.children || []).map(function(child) { return {source: parent, target: child}; }); })); } // For backwards-compatibility, don't enable inlining by default. var d3_layout_hierarchyInline = false;