Published
Edited
Oct 1, 2022
Insert cell
Insert cell
Insert cell
/**
* Class representing a Node in a tree.
* You should not need to edit this.
*/
class Node {
/**
* Creates a Node and intializes the following fields to null/empty:
* parentNode, children, parentName,level,position
* @param {string} nodeName - The name of the node.
* @param {string} parentName - The name of the parent node.
*/
constructor(nodeName, parentName) {
/** String of Node Name */
this.name = nodeName;

/** String of Parent Name */
this.parentName = parentName;

/** Reference to parent Node Object. */
this.parentNode = null;

/** Array of Children. */
this.children = [];

/** Level of the node. */
this.level = null;

/**
* Position of the node.
* Initialize to -1
*/
this.position = -1;
}

/**
* Add child to current Node.
* @param {Node} childNode - add a child to this node.
*/
addChild(childNode) {
this.children.push(childNode);
}
}
Insert cell
/**
* Class representing a Tree.
*/
class Tree {
/**
* Creates a Tree Object
* Populates a single attribute that contains a list (array) of Node objects to be used by the other functions in this class
* note: Node objects will have a name, parentNode, parentName, children, level, and position
* @param {json[]} json - array of json object with name and parent fields
*/
constructor(json) {

// Create nodes here.
this.nodes = [];
for (let i = 0; i < json.length; i++) {
this.nodes.push(new Node(json[i].name, json[i].parent));
}
// Assign parents and children.
for (let i = 0; i < this.nodes.length; i++) {
for (let j = 0; j < this.nodes.length; j++) {
if(this.nodes[j].parentName == this.nodes[i].name){
this.nodes[i].addChild(this.nodes[j]);
this.nodes[j].parentNode = this.nodes[i]}}}
}

/**
* Function that builds a tree from a list of nodes with parent refs
*/
buildLayout() {
// fill this in. It will need to call assignLevel and assignPosition.
this.assignLevel(this.nodes[0], 0)
this.assignPosition(this.nodes[0], 0)
return this;
}

/**
* Assign levels to nodes. The root should be level 0, its children level 1, etc.
*/
assignLevel(node, level) {
// fill this in
node.level = level;
for (let child of node.children) {
this.assignLevel(child,level+1);
}
}

/**
* Assign positions to nodes.
*/
assignPosition(node, position) {
// fill this in.
node.position = position;
if (node.children.length == 0) {
return position + 1;
}
for (let child of node.children) {
position = this.assignPosition(child, position);
}
return position;
}

render() {

// Create svg plot.
const svg = d3.create('svg')
.attr('width', 600)
.attr('height', 800);

// Add scaling
const linearScale = d3.scaleLinear()
.domain([0,4]) // for level
.range([0,400])

const g = svg.append('g')
.classed('nodeGroup', true)
.classed('label', true)
.attr('transform', 'translate(50, 50)')

g.selectAll('circle')
.data(this.nodes)
.join('circle')
.attr("cx", d => linearScale(d.level))
.attr("cy", d => linearScale(d.position))
.attr('r', 30)
g.selectAll('line')
.data(this.nodes)
.join('line')
//.attr("x1", d => linearScale(d.level))
// .attr("y1", d => linearScale(d.position))
// .attr("x2", d => linearScale(d.children.level))
// .attr("y2", d => linearScale(d.children.position))
.text(d => d.name)

g.selectAll('text')
.data(this.nodes)
.join('text')
.attr("x", d => linearScale(d.level))
.attr("y", d => linearScale(d.position))
.text(d => d.name)

// Create an SVG and render the tree into it.
return svg.node();
}
}
Insert cell
Insert cell
// Uncommenting the line below should return a list of nodes with their parent and children assigned.
new Tree(data).nodes
Insert cell
Insert cell
// Uncommenting the line below should return a list of nodes with their position and layers assigned.
new Tree(data).buildLayout().nodes
Insert cell
Insert cell
// Uncommenting the line below should render the tree as an SVG.
new Tree(data).buildLayout().render()
Insert cell
Insert cell
Insert cell
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more