xxxxxxxxxx
<meta charset="utf-8">
<style>
.node rect {
cursor: pointer;
fill: #fff;
fill-opacity: 0;
// stroke: #3182bd;
stroke-width: 1.5px;
stroke-opacity: 1;
}
.node text {
font: 10px sans-serif;
cursor: pointer;
}
path.link {
fill: none;
stroke: #9ecae1;
stroke-width: 1.5px;
}
</style>
<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></script>
<script>
var margin = {top: 30, right: 20, bottom: 30, left: 20},
width = 960 - margin.left - margin.right,
barHeight = 20,
barWidth = 20;
var i = 0,
duration = 400,
root;
var tree = d3.layout.tree()
.nodeSize([0, 20]);
var diagonal = d3.svg.diagonal()
.projection(function(d) { return [d.y, d.x]; });
var svg = d3.select("body").append("svg")
.attr("width", width + margin.left + margin.right)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
d3.json("flare.json", function(error, flare) {
if (error) throw error;
flare.x0 = 0;
flare.y0 = 0;
update(root = flare);
});
function update(source) {
// Compute the flattened node list. TODO use d3.layout.hierarchy.
var nodes = tree.nodes(root);
var height = Math.max(500, nodes.length * barHeight + margin.top + margin.bottom);
d3.select("svg").transition()
.duration(duration)
.attr("height", height);
d3.select(self.frameElement).transition()
.duration(duration)
.style("height", height + "px");
// Compute the "layout".
nodes.forEach(function(n, i) {
n.x = i * barHeight;
});
var myNext=d3.nest()
.key(function(d) { return d.id || (d.id = ++i); });
// Update the nodes…
var node = svg.selectAll("g.node")
.data(nodes, function(d) { return d.id || (d.id = ++i); });
var nodeEnter = node.enter()
.append("g")
.attr("class", "node")
.attr("transform", function(d) { return "translate(" + source.y0 + "," + source.x0 + ")"; })
.style("opacity", 1e-6);
// Enter any new nodes at the parent's previous position.
// nodeEnter.append("circle")
// .attr("cx", 10)
// .attr("cy", 0)
// .attr("r", 2);
nodeEnter.append("image")
// .attr("xlink:href", function(d) { var icon = d.icon; if (icon==null) {icon = ""} return icon; })
.attr("xlink:href", iconF)
.attr("x", 2)
.attr("y", -8)
.attr("width", "16px")
.attr("height", "16px");
nodeEnter.append("rect")
.attr("y", -barHeight / 2)
.attr("height", barHeight)
.attr("width", barWidth)
.on("click", click);
// text rectangle. gives somewhere to click if text is empty.
nodeEnter.append("rect")
.attr("y", -barHeight / 2)
.attr("x", barWidth)
.attr("height", barHeight)
.attr("width", barWidth)
.on("click", clickText);
nodeEnter.append("text");
var myText = d3.selectAll("text")
.attr("dy", 3.5)
.attr("dx", 25.5)
.text(function(d) { return d.name; })
// .on("click", clickText);
.call(make_editable, "name");
// Transition nodes to their new position.
node.transition()
.duration(duration)
.attr("transform", function(d) { return "translate(" + d.y + "," + d.x + ")"; })
.style("opacity", 1)
// Transition exiting nodes to the parent's new position.
node.exit().transition()
.duration(duration)
.attr("transform", function(d) { return "translate(" + source.y + "," + source.x + ")"; })
.style("opacity", 1e-6)
.remove();
// Update the links…
var link = svg.selectAll("path.link")
.data(tree.links(nodes), function(d) { return d.target.id; });
// Enter any new links at the parent's previous position.
link.enter().insert("path", "g")
.attr("class", "link")
.attr("d", function(d) {
var o = {x: source.x0, y: source.y0};
return diagonal({source: o, target: o});
})
.transition()
.duration(duration)
.attr("d", diagonal);
// Transition links to their new position.
link.transition()
.duration(duration)
.attr("d", diagonal);
// Transition exiting nodes to the parent's new position.
link.exit().transition()
.duration(duration)
.attr("d", function(d) {
var o = {x: source.x, y: source.y};
return diagonal({source: o, target: o});
})
.remove();
// Stash the old positions for transition.
nodes.forEach(function(d) {
d.x0 = d.x;
d.y0 = d.y;
});
}
// Toggle children on click.
function click(d) {
if (d.children) {
d._children = d.children;
d.children = null;
} else {
d.children = d._children;
d._children = null;
}
update(d);
}
function clickText(d) {
d.name = 'xxxxx'
update(d.name);
}
function iconF(d) {
var icon
if (d.icon) {
icon = d.icon
} else if (d.children){
icon="default-folder.svg"
} else {
icon="default-document.svg"
}
// return d.children ? "default-folder.svg" : "";
return icon
return
}
function make_editable(d, field)
{
console.log("make_editable", arguments);
this
.on("mouseover", function() {
d3.select(this).style("fill", "red");
})
.on("mouseout", function() {
d3.select(this).style("fill", null);
})
.on("click", function(d) {
var p = this.parentNode;
console.log(this, arguments);
// inject a HTML form to edit the content here...
// bug in the getBBox logic here, but don't know what I've done wrong here;
// anyhow, the coordinates are completely off & wrong. :-((
var xy = this.getBBox();
var p_xy = p.getBBox();
//xy.x -= p_xy.x;
//xy.y -= p_xy.y;
var el = d3.select(this);
var p_el = d3.select(p);
var frm = p_el.append("foreignObject");
var inp = frm
.attr("x", xy.x)
.attr("y", xy.y)
.attr("width", 300)
.attr("height", 25)
.append("xhtml:form")
.append("input")
.attr("value", function() {
// nasty spot to place this call, but here we are sure that the <input> tag is available
// and is handily pointed at by 'this':
this.focus();
return d[field];
})
.attr("style", "width: 294px;")
// make the form go away when you jump out (form looses focus) or hit ENTER:
.on("blur", function() {
console.log("blur", this, arguments);
var txt = inp.node().value;
d[field] = txt;
el
.text(function(d) { return d[field]; });
// Note to self: frm.remove() will remove the entire <g> group! Remember the D3 selection logic!
p_el.select("foreignObject").remove();
})
.on("keypress", function() {
console.log("keypress", this, arguments);
// IE fix
if (!d3.event)
d3.event = window.event;
var e = d3.event;
if (e.keyCode == 13)
{
if (typeof(e.cancelBubble) !== 'undefined') // IE
e.cancelBubble = true;
if (e.stopPropagation)
e.stopPropagation();
e.preventDefault();
var txt = inp.node().value;
d[field] = txt;
el
.text(function(d) { return d[field]; });
// odd. Should work in Safari, but the debugger crashes on this instead.
// Anyway, it SHOULD be here and it doesn't hurt otherwise.
p_el.select("foreignObject").remove();
}
});
});
}
</script>
https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js