JSFiddle - React, Tailwind, and code Playground

by justinbrown

HTML

<script src="http://d3js.org/d3.v3.min.js"></script>
<input id="nodeName" type="search" placeholder="Search"></input>
<button id="saveBtn">Save</button>
<textarea id="saveText"></textarea>
<input id="loadInput" type="text" placeholder="Paste to load"></input>
<div id="tooltipEditor" style="display:none">
    <p><b>Tooltip Editor</b></p>
    <textarea id="tooltipInput"></textarea>
    <p>
    <input id="tooltipSave" type="submit" value="Save" />
    </p>
</div>

CSS

html, body {
    height: 100%;
    width: 100%;
    position: relative;
}
rect {
    fill: none;
    pointer-events: all;
}
.node {
    fill: #000;
}
.cursor {
    fill: none;
    stroke: brown;
    pointer-events: none;
}
.link {
    stroke: #999;
    stroke-opacity: .4;
    stroke-width: 3px;
}
text {
    font: 10px sans-serif;
    pointer-events: none;
}
text.shadow {
    stroke: #fff;
    stroke-width: 3px;
    stroke-opacity: .8;
}
div.tooltip {
    position: absolute;
    text-align: center;
    /*width: 60px;
    height: 28px;*/
    padding: 6px;
    font: 12px sans-serif;
    background: lightsteelblue;
    border: 0px;
    border-radius: 8px;
    pointer-events: none;
}

.linkTooltip {
    text-align: center;
    padding: 6px;
    font: 12px sans-serif;
    background: lightsteelblue;
    border-radius: 8px;
    pointer-events: none;
}
#tooltipEditor {
 position: absolute;
    right: 20px;
    top: 10px;
}
}

JavaScript

var w = $('body').width(),
    h = $('body').height(),
    selectedLink,
    selectedNodes = [],
    key = function(d) { return d.key; };

var force = d3.layout.force()
    .size([w, h])
    .nodes([])
    .linkDistance(60)
    .charge(-60)
    .on("tick", tick);

d3.select("body")
    .on("keydown", function() {
        if($('#nodeName').is(':focus') || $('#tooltipInput').is(':focus')) {return;}
        
        if(d3.event.keyCode == 68) {
            console.log('deleting', 'nodes', nodes.length, 'links', links.length);
            if(selectedNodes.length) {
                var nodeToRemove = selectedNodes.pop();
               console.log(nodes.indexOf(nodeToRemove));
                nodes.splice(nodes.indexOf(nodeToRemove), 1);
                
                var linksToKeep = [];
                for(var i=0; i < links.length; i++) {
                    var l = links[i];
                     console.log('checking link', l.source == nodeToRemove, l.target == nodeToRemove);
                    if(l.source != nodeToRemove && l.target != nodeToRemove) {
                        linksToKeep.push(l);
                    }
                }
                
                links = linksToKeep;
                
                restart();
            }
            else if(selectedLink) {
                console.log(links.indexOf(selectedLink));
                links.splice(links.indexOf(selectedLink), 1);
                selectedLink = null;
                $('#tooltipEditor').fadeOut();
                $('#tooltipInput').val('');
                restart();
            }
            console.log('deleting done!', 'nodes', nodes.length, 'links', links.length);
        }
    });

var svg = d3.select("body").append("svg")
    .attr("width", w)
    .attr("height", h)
    .on("mousemove", mousemove)
    .on("mousedown", mousedown);

var nodes = force.nodes(),
    links = force.links();

var cursor = svg.append("circle")
    .attr("r", 30)
    .attr("transform",...