function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } var PEM = 18; var DEFAULT_HEIGHT = PEM * 2; var DEFAULT_GAP = PEM; var DEFAULT_OPTIONS = { getId: function getId(d) { return d.id || d.name; }, getHGap: function getHGap(d) { return d.hgap || DEFAULT_GAP; }, getVGap: function getVGap(d) { return d.vgap || DEFAULT_GAP; }, getChildren: function getChildren(d) { return d.children; }, getHeight: function getHeight(d) { return d.height || DEFAULT_HEIGHT; }, getWidth: function getWidth(d) { var name = d.name || ' '; return d.width || name.split('').length * PEM; // FIXME DO NOT get width like this } }; var Node = function () { function Node(data) { var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; var isolated = arguments[2]; _classCallCheck(this, Node); var me = this; me.vgap = me.hgap = 0; if (data instanceof Node) return data; me.data = data; /* * Gaps: filling space between nodes * (x, y) ---------------------- * | vgap | * | -------------------- h * | h | | e * | g | | i * | a | | g * | p | | h * | --------------------- t * | | * -----------width------------ */ var hgap = (options.getHGap || DEFAULT_OPTIONS.getHGap)(data); var vgap = (options.getVGap || DEFAULT_OPTIONS.getVGap)(data); /* * BBox: start point, width, height, etc. * (x, y) ---width--->| (x+width, y) * | | * height | * | | * (x, y+height)----->| (x+width, y+height) */ me.width = (options.getWidth || DEFAULT_OPTIONS.getWidth)(data); me.height = (options.getHeight || DEFAULT_OPTIONS.getHeight)(data); me.id = (options.getId || DEFAULT_OPTIONS.getId)(data); me.x = me.y = 0; me.depth = 0; if (!isolated && !data.collapsed) { var nodes = [me]; var node = nodes.pop(); while (node) { if (!node.data.collapsed) { var children = (options.getChildren || DEFAULT_OPTIONS.getChildren)(node.data); var length = children ? children.length : 0; node.children = []; if (children && length) { for (var i = 0; i < length; i++) { var child = new Node(children[i], options); node.children.push(child); nodes.push(child); child.parent = node; child.depth = node.depth + 1; } } } node = nodes.pop(); } } if (!me.children) { me.children = []; } me.addGap(hgap, vgap); } Node.prototype.isRoot = function isRoot() { return this.depth === 0; }; Node.prototype.isLeaf = function isLeaf() { return this.children.length === 0; }; Node.prototype.addGap = function addGap(hgap, vgap) { var me = this; me.hgap += hgap; me.vgap += vgap; me.width += 2 * hgap; me.height += 2 * vgap; }; Node.prototype.eachNode = function eachNode(callback) { // Depth First traverse var me = this; var nodes = [me]; var current = nodes.pop(); while (current) { callback(current); nodes = nodes.concat(current.children); current = nodes.pop(); } }; Node.prototype.DFTraverse = function DFTraverse(callback) { // Depth First traverse this.eachNode(callback); }; Node.prototype.BFTraverse = function BFTraverse(callback) { // Breadth First traverse var me = this; var nodes = [me]; var current = nodes.shift(); while (current) { callback(current); nodes = nodes.concat(current.children); current = nodes.shift(); } }; Node.prototype.getBoundingBox = function getBoundingBox() { var bb = { left: Number.MAX_VALUE, top: Number.MAX_VALUE, width: 0, height: 0 }; this.eachNode(function (node) { bb.left = Math.min(bb.left, node.x); bb.top = Math.min(bb.top, node.y); bb.width = Math.max(bb.width, node.x + node.width); bb.height = Math.max(bb.height, node.y + node.height); }); return bb; }; // translate Node.prototype.translate = function translate() { var tx = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0; var ty = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; this.eachNode(function (node) { node.x += tx; node.y += ty; }); }; Node.prototype.right2left = function right2left() { var me = this; var bb = me.getBoundingBox(); me.eachNode(function (node) { node.x = node.x - (node.x - bb.left) * 2 - node.width; // node.x = - node.x; }); me.translate(bb.width, 0); }; Node.prototype.bottom2top = function bottom2top() { var me = this; var bb = me.getBoundingBox(); me.eachNode(function (node) { node.y = node.y - (node.y - bb.top) * 2 - node.height; // node.y = - node.y; }); me.translate(0, bb.height); }; Node.prototype.getCenterX = function getCenterX() { var me = this; return me.x + me.width / 2; }; Node.prototype.getCenterY = function getCenterY() { var me = this; return me.y + me.height / 2; }; Node.prototype.getActualWidth = function getActualWidth() { var me = this; return me.width - me.hgap * 2; }; Node.prototype.getActualHeight = function getActualHeight() { var me = this; return me.height - me.vgap * 2; }; return Node; }(); Node.prototype.each = Node.prototype.eachNode; module.exports = Node;