Consistent set of d3 js and css across admin, examples, and welcome
This commit is contained in:
@@ -0,0 +1,33 @@
|
||||
.node {fill: steelblue;
|
||||
stroke: #636363;
|
||||
stroke-width: 1px;}
|
||||
|
||||
.auth {fill: lightgrey;}
|
||||
|
||||
.table {r: 10;}
|
||||
|
||||
.link {stroke: #bbbbbb;
|
||||
stroke-width: 2px;}
|
||||
td {padding: 4px;}
|
||||
|
||||
div.tooltip {
|
||||
position: absolute;
|
||||
text-align: left;
|
||||
/* width: 140px; */
|
||||
/* height: 28px;*/
|
||||
padding: 0px 5px 0px 5px;
|
||||
padding-top: 0px;
|
||||
font: 12px sans-serif;
|
||||
background: #fff7bc;
|
||||
border: solid 1px #aaa;
|
||||
border-radius: 6px;
|
||||
pointer-events: none;}
|
||||
|
||||
h5 { font: 14px sans-serif;
|
||||
background : #ec7014;
|
||||
color: #ffffe5;
|
||||
padding: 5px 2px 5px 2px;
|
||||
margin-top: 1px;}
|
||||
path {
|
||||
fill: #aaaaaa;}
|
||||
|
||||
+8
File diff suppressed because one or more lines are too long
+181
@@ -0,0 +1,181 @@
|
||||
function d3_graph() {
|
||||
|
||||
// Some reference links:
|
||||
// How to get link ids instead of index
|
||||
// http://stackoverflow.com/questions/23986466/d3-force-layout-linking-nodes-by-name-instead-of-index
|
||||
// embedding web2py in d3
|
||||
// http://stackoverflow.com/questions/34326343/embedding-d3-js-graph-in-a-web2py-bootstrap-page
|
||||
|
||||
// nodes and links are defined in appadmin.html <script>
|
||||
|
||||
|
||||
var edges = [];
|
||||
|
||||
links.forEach(function(e) {
|
||||
var sourceNode = nodes.filter(function(n) {
|
||||
return n.name === e.source;
|
||||
})[0],
|
||||
targetNode = nodes.filter(function(n) {
|
||||
return n.name === e.target;
|
||||
})[0];
|
||||
|
||||
edges.push({
|
||||
source: sourceNode,
|
||||
target: targetNode,
|
||||
value: 1});
|
||||
|
||||
});
|
||||
|
||||
edges.forEach(function(e) {
|
||||
|
||||
if (!e.source["linkcount"]) e.source["linkcount"] = 0;
|
||||
if (!e.target["linkcount"]) e.target["linkcount"] = 0;
|
||||
|
||||
e.source["linkcount"]++;
|
||||
e.target["linkcount"]++;
|
||||
});
|
||||
|
||||
//var width = 960, height = 600;
|
||||
var height = window.innerHeight|| docEl.clientHeight|| bodyEl.clientHeight;
|
||||
var width = window.innerWidth || docEl.clientWidth || bodyEl.clientWidth;
|
||||
var svg = d3.select("#vis").append("svg")
|
||||
.attr("width", width)
|
||||
.attr("height", height);
|
||||
|
||||
// updated for d3 v4.
|
||||
var simulation = d3.forceSimulation()
|
||||
.force("link", d3.forceLink().id(function(d) { return d.id; }))
|
||||
.force("charge", d3.forceManyBody().strength(strength))
|
||||
.force("center", d3.forceCenter(width / 2, height / 2))
|
||||
.force("collision", d3.forceCollide(35));
|
||||
|
||||
// Node charge strength. Repel strength greater for less links.
|
||||
//function strength(d) { return -50/d["linkcount"] ; }
|
||||
function strength(d) { return -25 ; }
|
||||
|
||||
// Link distance. Distance increases with number of links at source and target
|
||||
function distance(d) { return (60 + (d.source["linkcount"] * d.target["linkcount"])) ; }
|
||||
|
||||
// Link strength. Strength is less for highly connected nodes (move towards target dist)
|
||||
function strengthl(d) { return 5/(d.source["linkcount"] + d.target["linkcount"]) ; }
|
||||
|
||||
simulation
|
||||
.nodes(nodes)
|
||||
.on("tick", tick);
|
||||
|
||||
simulation.force("link")
|
||||
.links(edges)
|
||||
.distance(distance)
|
||||
.strength(strengthl);
|
||||
|
||||
// build the arrow.
|
||||
svg.append("svg:defs").selectAll("marker")
|
||||
.data(["end"]) // Different link/path types can be defined here
|
||||
.enter().append("svg:marker") // This section adds in the arrows
|
||||
.attr("id", String)
|
||||
.attr("viewBox", "0 -5 10 10")
|
||||
.attr("refX", 25) // Moves the arrow head out, allow for radius
|
||||
.attr("refY", 0) // -1.5
|
||||
.attr("markerWidth", 6)
|
||||
.attr("markerHeight", 6)
|
||||
.attr("orient", "auto")
|
||||
.append("svg:path")
|
||||
.attr("d", "M0,-5L10,0L0,5");
|
||||
|
||||
var link = svg.selectAll('.link')
|
||||
.data(edges)
|
||||
.enter().append('line')
|
||||
.attr("class", "link")
|
||||
.attr("marker-end", "url(#end)");
|
||||
|
||||
var node = svg.selectAll(".node")
|
||||
.data(nodes)
|
||||
.enter().append("g")
|
||||
.attr("class", function(d) { return "node " + d.type;})
|
||||
.attr('transform', function(d) {
|
||||
return "translate(" + d.x + "," + d.y + ")"})
|
||||
.classed("auth", function(d) { return (d.name.startsWith("auth") ? true : false);});
|
||||
|
||||
node.call(d3.drag()
|
||||
.on("start", dragstarted)
|
||||
.on("drag", dragged)
|
||||
.on("end", dragended));
|
||||
|
||||
// add the nodes
|
||||
node.append('circle')
|
||||
.attr('r', 16)
|
||||
;
|
||||
|
||||
// add text
|
||||
node.append("text")
|
||||
.attr("x", 12)
|
||||
.attr("dy", "-1.1em")
|
||||
.text(function(d) {return d.name;});
|
||||
|
||||
node.on("mouseover", function(d) {
|
||||
|
||||
var g = d3.select(this); // the node (table)
|
||||
|
||||
// tooltip
|
||||
|
||||
var fields = d.fields;
|
||||
var fieldformat = "<TABLE>";
|
||||
fields.forEach(function(d) {
|
||||
fieldformat += "<TR><TD><B>"+ d.name+"</B></TD><TD>"+ d.type+"</TD><TD>"+ d.disp+"</TD></TR>";
|
||||
});
|
||||
fieldformat += "</TABLE>";
|
||||
var tiplength = d.fields.length;
|
||||
|
||||
// Define 'div' for tooltips
|
||||
var div = d3.select("body").append("div") // declare the tooltip div
|
||||
.attr("class", "tooltip") // apply the 'tooltip' class
|
||||
.style("opacity", 0)
|
||||
.html('<h5>' + d.name + '</h5>' + fieldformat)
|
||||
.style("left", 20 + (d3.event.pageX) + "px")// or just (d.x + 50 + "px")
|
||||
.style("top", tooltop(tiplength))// or ...
|
||||
.transition()
|
||||
.duration(800)
|
||||
.style("opacity", 0.9);
|
||||
});
|
||||
|
||||
function tooltop(tiplength) {
|
||||
//aim to ensure tooltip is fully visible whenver possible
|
||||
return (Math.max(d3.event.pageY - 20 - (tiplength * 14),0)) + "px"
|
||||
}
|
||||
|
||||
node.on("mouseout", function(d) {
|
||||
d3.select("body").select('div.tooltip').remove();
|
||||
});
|
||||
|
||||
// instead of waiting for force to end with : force.on('end', function()
|
||||
// use .on("tick", instead. Here is the tick function
|
||||
function tick() {
|
||||
node.attr('transform', function(d) {
|
||||
d.x = Math.max(30, Math.min(width - 16, d.x));
|
||||
d.y = Math.max(30, Math.min(height - 16, d.y));
|
||||
return "translate(" + d.x + "," + d.y + ")"; });
|
||||
|
||||
link.attr('x1', function(d) {return d.source.x;})
|
||||
.attr('y1', function(d) {return d.source.y;})
|
||||
.attr('x2', function(d) {return d.target.x;})
|
||||
.attr('y2', function(d) {return d.target.y;});
|
||||
};
|
||||
|
||||
function dragstarted(d) {
|
||||
if (!d3.event.active) simulation.alphaTarget(0.3).restart();
|
||||
d.fx = d.x;
|
||||
d.fy = d.y;
|
||||
};
|
||||
|
||||
function dragged(d) {
|
||||
d.fx = d3.event.x;
|
||||
d.fy = d3.event.y;
|
||||
};
|
||||
|
||||
function dragended(d) {
|
||||
if (!d3.event.active) simulation.alphaTarget(0);
|
||||
d.fx = null;
|
||||
d.fy = null;
|
||||
};
|
||||
|
||||
};
|
||||
@@ -0,0 +1,33 @@
|
||||
.node {fill: steelblue;
|
||||
stroke: #636363;
|
||||
stroke-width: 1px;}
|
||||
|
||||
.auth {fill: lightgrey;}
|
||||
|
||||
.table {r: 10;}
|
||||
|
||||
.link {stroke: #bbbbbb;
|
||||
stroke-width: 2px;}
|
||||
td {padding: 4px;}
|
||||
|
||||
div.tooltip {
|
||||
position: absolute;
|
||||
text-align: left;
|
||||
/* width: 140px; */
|
||||
/* height: 28px;*/
|
||||
padding: 0px 5px 0px 5px;
|
||||
padding-top: 0px;
|
||||
font: 12px sans-serif;
|
||||
background: #fff7bc;
|
||||
border: solid 1px #aaa;
|
||||
border-radius: 6px;
|
||||
pointer-events: none;}
|
||||
|
||||
h5 { font: 14px sans-serif;
|
||||
background : #ec7014;
|
||||
color: #ffffe5;
|
||||
padding: 5px 2px 5px 2px;
|
||||
margin-top: 1px;}
|
||||
path {
|
||||
fill: #aaaaaa;}
|
||||
|
||||
+8
File diff suppressed because one or more lines are too long
+181
@@ -0,0 +1,181 @@
|
||||
function d3_graph() {
|
||||
|
||||
// Some reference links:
|
||||
// How to get link ids instead of index
|
||||
// http://stackoverflow.com/questions/23986466/d3-force-layout-linking-nodes-by-name-instead-of-index
|
||||
// embedding web2py in d3
|
||||
// http://stackoverflow.com/questions/34326343/embedding-d3-js-graph-in-a-web2py-bootstrap-page
|
||||
|
||||
// nodes and links are defined in appadmin.html <script>
|
||||
|
||||
|
||||
var edges = [];
|
||||
|
||||
links.forEach(function(e) {
|
||||
var sourceNode = nodes.filter(function(n) {
|
||||
return n.name === e.source;
|
||||
})[0],
|
||||
targetNode = nodes.filter(function(n) {
|
||||
return n.name === e.target;
|
||||
})[0];
|
||||
|
||||
edges.push({
|
||||
source: sourceNode,
|
||||
target: targetNode,
|
||||
value: 1});
|
||||
|
||||
});
|
||||
|
||||
edges.forEach(function(e) {
|
||||
|
||||
if (!e.source["linkcount"]) e.source["linkcount"] = 0;
|
||||
if (!e.target["linkcount"]) e.target["linkcount"] = 0;
|
||||
|
||||
e.source["linkcount"]++;
|
||||
e.target["linkcount"]++;
|
||||
});
|
||||
|
||||
//var width = 960, height = 600;
|
||||
var height = window.innerHeight|| docEl.clientHeight|| bodyEl.clientHeight;
|
||||
var width = window.innerWidth || docEl.clientWidth || bodyEl.clientWidth;
|
||||
var svg = d3.select("#vis").append("svg")
|
||||
.attr("width", width)
|
||||
.attr("height", height);
|
||||
|
||||
// updated for d3 v4.
|
||||
var simulation = d3.forceSimulation()
|
||||
.force("link", d3.forceLink().id(function(d) { return d.id; }))
|
||||
.force("charge", d3.forceManyBody().strength(strength))
|
||||
.force("center", d3.forceCenter(width / 2, height / 2))
|
||||
.force("collision", d3.forceCollide(35));
|
||||
|
||||
// Node charge strength. Repel strength greater for less links.
|
||||
//function strength(d) { return -50/d["linkcount"] ; }
|
||||
function strength(d) { return -25 ; }
|
||||
|
||||
// Link distance. Distance increases with number of links at source and target
|
||||
function distance(d) { return (60 + (d.source["linkcount"] * d.target["linkcount"])) ; }
|
||||
|
||||
// Link strength. Strength is less for highly connected nodes (move towards target dist)
|
||||
function strengthl(d) { return 5/(d.source["linkcount"] + d.target["linkcount"]) ; }
|
||||
|
||||
simulation
|
||||
.nodes(nodes)
|
||||
.on("tick", tick);
|
||||
|
||||
simulation.force("link")
|
||||
.links(edges)
|
||||
.distance(distance)
|
||||
.strength(strengthl);
|
||||
|
||||
// build the arrow.
|
||||
svg.append("svg:defs").selectAll("marker")
|
||||
.data(["end"]) // Different link/path types can be defined here
|
||||
.enter().append("svg:marker") // This section adds in the arrows
|
||||
.attr("id", String)
|
||||
.attr("viewBox", "0 -5 10 10")
|
||||
.attr("refX", 25) // Moves the arrow head out, allow for radius
|
||||
.attr("refY", 0) // -1.5
|
||||
.attr("markerWidth", 6)
|
||||
.attr("markerHeight", 6)
|
||||
.attr("orient", "auto")
|
||||
.append("svg:path")
|
||||
.attr("d", "M0,-5L10,0L0,5");
|
||||
|
||||
var link = svg.selectAll('.link')
|
||||
.data(edges)
|
||||
.enter().append('line')
|
||||
.attr("class", "link")
|
||||
.attr("marker-end", "url(#end)");
|
||||
|
||||
var node = svg.selectAll(".node")
|
||||
.data(nodes)
|
||||
.enter().append("g")
|
||||
.attr("class", function(d) { return "node " + d.type;})
|
||||
.attr('transform', function(d) {
|
||||
return "translate(" + d.x + "," + d.y + ")"})
|
||||
.classed("auth", function(d) { return (d.name.startsWith("auth") ? true : false);});
|
||||
|
||||
node.call(d3.drag()
|
||||
.on("start", dragstarted)
|
||||
.on("drag", dragged)
|
||||
.on("end", dragended));
|
||||
|
||||
// add the nodes
|
||||
node.append('circle')
|
||||
.attr('r', 16)
|
||||
;
|
||||
|
||||
// add text
|
||||
node.append("text")
|
||||
.attr("x", 12)
|
||||
.attr("dy", "-1.1em")
|
||||
.text(function(d) {return d.name;});
|
||||
|
||||
node.on("mouseover", function(d) {
|
||||
|
||||
var g = d3.select(this); // the node (table)
|
||||
|
||||
// tooltip
|
||||
|
||||
var fields = d.fields;
|
||||
var fieldformat = "<TABLE>";
|
||||
fields.forEach(function(d) {
|
||||
fieldformat += "<TR><TD><B>"+ d.name+"</B></TD><TD>"+ d.type+"</TD><TD>"+ d.disp+"</TD></TR>";
|
||||
});
|
||||
fieldformat += "</TABLE>";
|
||||
var tiplength = d.fields.length;
|
||||
|
||||
// Define 'div' for tooltips
|
||||
var div = d3.select("body").append("div") // declare the tooltip div
|
||||
.attr("class", "tooltip") // apply the 'tooltip' class
|
||||
.style("opacity", 0)
|
||||
.html('<h5>' + d.name + '</h5>' + fieldformat)
|
||||
.style("left", 20 + (d3.event.pageX) + "px")// or just (d.x + 50 + "px")
|
||||
.style("top", tooltop(tiplength))// or ...
|
||||
.transition()
|
||||
.duration(800)
|
||||
.style("opacity", 0.9);
|
||||
});
|
||||
|
||||
function tooltop(tiplength) {
|
||||
//aim to ensure tooltip is fully visible whenver possible
|
||||
return (Math.max(d3.event.pageY - 20 - (tiplength * 14),0)) + "px"
|
||||
}
|
||||
|
||||
node.on("mouseout", function(d) {
|
||||
d3.select("body").select('div.tooltip').remove();
|
||||
});
|
||||
|
||||
// instead of waiting for force to end with : force.on('end', function()
|
||||
// use .on("tick", instead. Here is the tick function
|
||||
function tick() {
|
||||
node.attr('transform', function(d) {
|
||||
d.x = Math.max(30, Math.min(width - 16, d.x));
|
||||
d.y = Math.max(30, Math.min(height - 16, d.y));
|
||||
return "translate(" + d.x + "," + d.y + ")"; });
|
||||
|
||||
link.attr('x1', function(d) {return d.source.x;})
|
||||
.attr('y1', function(d) {return d.source.y;})
|
||||
.attr('x2', function(d) {return d.target.x;})
|
||||
.attr('y2', function(d) {return d.target.y;});
|
||||
};
|
||||
|
||||
function dragstarted(d) {
|
||||
if (!d3.event.active) simulation.alphaTarget(0.3).restart();
|
||||
d.fx = d.x;
|
||||
d.fy = d.y;
|
||||
};
|
||||
|
||||
function dragged(d) {
|
||||
d.fx = d3.event.x;
|
||||
d.fy = d3.event.y;
|
||||
};
|
||||
|
||||
function dragended(d) {
|
||||
if (!d3.event.active) simulation.alphaTarget(0);
|
||||
d.fx = null;
|
||||
d.fy = null;
|
||||
};
|
||||
|
||||
};
|
||||
Reference in New Issue
Block a user