VueJS Hand-made Tree graph V2 (recursive)

by downedcrane

HTML

<script type="x-template" id="node-template">
  <g class="node" transform="translate({{node.x - 50}}, {{node.y - 25}})">
    <rect x="0" y="0" height="50" width="100"></rect>
    <text x="5" y="15">{{node.label}}</text>
    <text x="5" y="30">treePos: [{{node.level}}][{{node.index}}]</text>
    <text x="5" y="45">weight: {{node.weight}}</text>
  </g>
</script>

<script type="x-template" id="link-template">
  <path id="{{link.id}}" class="link" v-bind:d="getPath(link)">
</script>

<div id="container">
  <button v-on:click="insertRandomNode()">Insert random</button>
  <svg v-bind:width="service.svgWidth" v-bind:height="service.svgHeight + 10">
    <link-template v-for="link in getAllLinks(service.data)" v-bind:link="link"></link-template>
    <node-template v-for="node in getAllNodes(service.data)" v-bind:node="node"></node-template>
  </svg>
</div>

SCSS

.link {
  fill: none;
  stroke: #ccc;
  stroke-width: 1px;
}

.node {
  &:hover {
    cursor: pointer;
    rect {
      fill: #49ACEE;
    }
  }
  rect {
     fill: #DFF3FF;
     stroke: #49ACEE;
  }
}

JavaScript

/*** COMPONENTS ***/
var nodeTemplate = {
  template: '#node-template',
  props: ['node']
};

var linkTemplate = {
  template: '#link-template',
  props: ['link'],
  methods: {
    getPath
  }
};

/** DATA + SERVICE **/

var data = [
      [{
        level: 0,
        index: 0,
        label: 'root',
        children: [{
          level: 1,
          index: 0
        }, {
          level: 1,
          index: 1
        }]
      }],
      [{
        level: 1,
        index: 0,
        label: 'node1',
        parents: [{
          level: 0,
          index: 0
        }],
        children: [{
          level: 2,
          index: 0
        }]
      }, {
        level: 1,
        index: 1,
        label: 'node2',
        parents: [{
          level: 0,
          index: 0
        }],
        children: [{
          level: 2,
          index: 0
        }]
      }],
      [{
        level: 2,
        index: 0,
        label: 'node3',
        parents: [{
          level: 1,
          index: 0
        }, {
          level: 1,
          index: 1
        }],
      }]
    ];

var treeService = {
  data: data,
  verticalSpacing: 50,
  componentMargin: 25,
  componentHeight: 50,
  componentWidth: 100,
  svgWidth: 0,
  svgHeight: 0,
  svgPadding: {
    top: 50,
    bottom: 0,
    left: 0,
    right: 0
  }
};

/***** ALGO DRAW TREE *****/

/** START TOOLS FUNCTIONS **/
function hasParents(node) {
  return node.parents && node.parents.length > 0;
}

function hasChildren(node) {
  return node.children && node.children.length > 0;
}

function firstParent(node) {
  var firstParent = node;
  var savedX = treeService.svgWidth + treeService.svgPadding.left + treeService.svgPadding.right;

  if (hasParents(node)) {
    node.parents.forEach(function(parent) {
      if (treeService.data[parent.level][parent.index].x < savedX) {
        savedX = treeService.data[parent.level][parent.index].x;
        firstParent = treeService.data[parent.level][parent.index];
      }
    });
  }
  return...