JSFiddle - React, Tailwind, and code Playground

by Cyril Cherian

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.6/d3.min.js"></script>
<div id="tree-container"></div>

CSS

.node {
    cursor: pointer;
}
.overlay {
    background-color:#FFF;
}
.node text {
    font-size: 0.85em;
    font-family:'Roboto Condensed', sans-serif;
    font-weight: 500;
}
.link {
    fill: none;
    stroke:#bcbcbc;
    stroke-width:1px;
}
.templink {
    fill: none;
    stroke: red;
    stroke-width: 3px;
}
.ghostCircle.show {
    display:block;
}
.ghostCircle, .activeDrag .ghostCircle {
    display: none;
}

JavaScript

var treeData = {
    "name": "Parent",
        "_children": [{
        "name": "Child 1",
            "_children": [{
            "name": "Grandchild 1"
        }, {
            "name": "Grandchild 2"
        }]
    }, {
        "name": "Child 2",
            "_children": [{
            "name": "Grandchild 3"
        }, {
            "name": "Grandchild 4"
        }]
    }]
};
// Calculate total nodes, max label length
var totalNodes = 0;
var maxLabelLength = 0;
// variables for drag/drop
var selectedNode = null;
var draggingNode = null;
// panning variables
var panSpeed = 200;
var panBoundary = 20; // Within 20px from edges will pan when dragging.
// Misc. variables
var i = 0;
var duration = 750;
var root;

// size of the diagram
var viewerWidth = $(document).width();
var viewerHeight = $(document).height();

var tree = d3.layout.tree()
    .size([viewerHeight, viewerWidth]);

// define a d3 diagonal projection for use by the node paths later on.
var diagonal = d3.svg.diagonal()
    .projection(function (d) {
    return [d.y, d.x];
});

// A recursive helper function for performing some setup by walking through all nodes

function visit(parent, visitFn, childrenFn) {
    if (!parent) return;

    visitFn(parent);

    var children = childrenFn(parent);
    if (children) {
        var count = children.length;
        for (var i = 0; i < count; i++) {
            visit(children[i], visitFn, childrenFn);
        }
    }
}

// Call visit function to establish maxLabelLength
visit(treeData, function (d) {
    totalNodes++;
    maxLabelLength = Math.max(d.name.length, maxLabelLength);

}, function (d) {
    return d.children && d.children.length > 0 ? d.children : null;
});


// sort the tree according to the node names

function sortTree() {
    tree.sort(function (a, b) {
        return b.name.toLowerCase() < a.name.toLowerCase() ? 1 : -1;
    });
}
// Sort the tree initially incase the JSON isn't in a sorted order.
sortTree();

function pan(domNode, direction) {
  ...