JSFiddle - React, Tailwind, and code Playground

by justinbrown

HTML

<script src="http://d3js.org/d3.v3.min.js"></script>
<script src="https://raw.github.com/wycats/handlebars.js/1.0.0-rc.3/dist/handlebars.js"></script>
<script src="https://raw.github.com/emberjs/ember.js/release-builds/ember-1.0.0-rc.3.js"></script>
<script type="text/x-handlebars" data-template-name="application">
    <input id="nodeName" type="search" placeholder="Search"></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>
    <svg {{bindAttr height="App.height" width="App.width"}}></svg>
</script>

CSS

html, body, .ember-view {
    margin: 0;
    padding: 0;
    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;
}
#tooltipEditor {
    position: absolute;
    right: 20px;
    top: 10px;
}
}

JavaScript

var App = window.App = Ember.Application.create({
    height: $('body').height(),
    width: $('body').width()
});

App.ApplicationView = Em.View.extend({
    nodes: Em.A(),
    links: Em.A(),
    didInsertElement: function () {
        var self = this,
            svg = d3.select('svg').on("mousemove", function () {
                cursor.attr("transform", "translate(" + d3.mouse(this) + ")");
            }).on("mousedown", function () {
                console.log('add node to screen');
                var nodes = self.get('nodes'),
                    links = self.get('links'),
                    nodeName = $('#nodeName').val(),
                    point = d3.mouse(this),
                    node = {
                        x: point[0],
                        y: point[1],
                        name: nodeName,
                        fixed: true
                    };
                console.log('node', node);
                if (nodeName.length) {
                    nodes.push(node);
                    // add links to any nearby nodes
                    nodes.forEach(function (target) {
                        var x = target.x - node.x,
                            y = target.y - node.y;
                        if (Math.sqrt(x * x + y * y) < 30) {
                            links.push({
                                source: node,
                                target: target,
                                tooltip: ''
                            });
                        }
                    });

                    $('#nodeName').val('');
                    self.restart();
                }
            }),
            cursor = svg.append("circle")
                .attr("r", 30)
                .attr("transform", "translate(-100,-100)")
                .attr("class", "cursor");

        var force = d3.layout.force()
            .size([App.get('width'), App.get('height')])
            .nodes([])
            .linkDistance(60)
           ...