import "../arrays/merge"; import "../core/rebind"; import "layout"; 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 to a standard hierarchy structure. function recurse(node, depth, nodes) { var childs = children.call(hierarchy, node, depth); node.depth = depth; nodes.push(node); if (childs && (n = childs.length)) { var i = -1, n, c = node.children = [], v = 0, j = depth + 1, d; 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, node, depth) || 0; } return node; } // Recursively re-evaluates the node value. function revalue(node, depth) { var children = node.children, v = 0; if (children && (n = children.length)) { var i = -1, n, j = depth + 1; while (++i < n) v += revalue(children[i], j); } else if (value) { v = +value.call(hierarchy, node, 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) { d3.rebind(object, hierarchy, "sort", "children", "value"); // Add an alias for nodes and links, for convenience. object.nodes = object; object.links = d3_layout_hierarchyLinks; 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}; }); })); }