Widget:Interactive research map of ATM
From EngageWiki
<style> div#canvas{ min-width: 800px; margin: auto; }
div.info { max-width: 400px; min-height: 30px; padding: 5px; font: 13px sans-serif; background: lightsteelblue; border: 0px; display: none; max-height: 700px; overflow-y: auto; }
div#current{ position: absolute; min-width: 100px; }
div#selected{ position: fixed; right: 10px; top: 10px; min-width: 300px; padding: 15px; opacity: 0.95; }
div#search-box{ position: fixed; left: 10px; top: 10px; }
.btn, .btn-xs { margin: .5rem 0; padding: .4rem; font-size: .875rem; line-height: .5; border-radius: .2rem; }
div.info div { margin-bottom: 5px; }
div.info ul { padding-left: 20px; font-size: 90%; }
div.info ul li { margin-bottom: 3px; }
div.info .close { color:red; border: 2px solid red; } </style>
<input type="text" id="search_term" value=""> <button id="search">search</button> <button id="reset">reset</button>
Filter by call:
<a onclick="update_call('wp-e')" href="#">WP-E</a>, <a onclick="update_call('ir')" href="#">IR</a>, <a onclick="update_call('ir-demo')" href="#">IR-Demo</a>, <a onclick="update_call('ir-aire iii')" href="#">IR-AIRE III</a>, <a onclick="update_call('ir-lsd')" href="#">IR-LSD</a>, <a onclick="update_call('ir-rpas')" href="#">IR-RPAS</a>, <a onclick="update_call('ir wave 1')" href="#">IR WAVE 1</a>, <a onclick="update_call('er1')" href="#">ER1</a>, <a onclick="update_call('er2')" href="#">ER2</a>, <a onclick="update_call('er3')" href="#">ER3</a>, <a onclick="update_call('er4')" href="#">ER4</a>,
<button id="selected-close" type="button" class="close">
×
</button>
<script src="https://d3js.org/d3.v5.min.js"></script>
<script>
var data;
var width = d3.select("#canvas").node().getBoundingClientRect().width; var height = 1300;
var div_current = d3.select("#current") var div_selected = d3.select("#selected") var div_selected_content = d3.select("#selected-content")
d3.json("extensions/ComplexWorld/visuals/assets/tree_cluster.json").then(function (d) { data = d; visualize(data); });
d3.select("#search").on("click", function () { update_filter(); }) d3.select("#search_term").on("keypress", function () { if (d3.event.keyCode == 13) { update_filter(); } })
function update_filter() { var term = d3.select("#search_term").node().value.toLowerCase(); d3.select("svg").remove(); var data_f = JSON.parse(JSON.stringify(data)); filterData(data_f.children, term); visualize(data_f); }
d3.select("#reset").on("click", function () { d3.select("#search_term").node().value = null; d3.select("svg").remove(); visualize(data); })
function filterData(data, term) { var r = data.filter(function (o) { if (o.children) { o.children = filterData(o.children, term); } else { var words = term.split(" ");
var match = true;
words.forEach((w, i) => { match = match && (o.keywords.includes(w) || o.title.toLowerCase().includes(w)) }); return match } }) return r; }
function visualize(data) { var root = d3.hierarchy(data); var links = root.links(); var nodes = root.descendants();
var simulation = d3.forceSimulation(nodes) .force("link", d3.forceLink(links).id(d => d.id).distance(40).strength(0.5)) .force("charge", d3.forceManyBody().strength(-180)) .force("x", d3.forceX()) .force("y", d3.forceY()) ;
var svg = d3.select("#canvas") .append("svg") .attr("width", width) .attr("height", height) .attr("viewBox", [-width / 2, -height / 2, width, height]);
var link = svg.append("g") // .attr("stroke", "#555") // .attr("stroke-opacity", 0.6) .selectAll("line") .data(links) .join("line") .attr("stroke", "#555") .attr("stroke", d => d.target.children ? "#555" : "#999") .attr("stroke-opacity", d => d.target.children ? 0.6 : 0.4) ;
var node = svg.append("g") .selectAll(".node") .data(nodes) .join("g") .call(drag(simulation));
node.append("circle") .attr("class", "circle") .style("cursor", "pointer") .raise() .on("mouseover", mouseover) .on("mouseout", mouseout) .on("click", click);
reset_all_nodes();
// node.append("text") // .text(d => d.data.wbs ? d.data.wbs : null) // .style('fill', '#000') // .style('font-size', '12px') // .style("text-anchor", "middle"); // // .attr('x', 6) // // .attr('y', 3);
// // unselect // d3.select("body").on("click", function () { // var outside_circle = d3.selectAll('.circle').filter(function () { return this == d3.event.target }).empty(); // var outside_box = d3.select('#selected').filter(function () { return this == d3.event.target }).empty(); // if (outside_circle && outside_box) { // div_selected.style("display", "none"); // selected = false; // } // });
// close selected div d3.select("#selected-close").on("click", function () { div_selected.style("display", "none"); reset_all_nodes(); });
simulation.on("tick", () => { link .attr("x1", d => d.source.x) .attr("y1", d => d.source.y) .attr("x2", d => d.target.x) .attr("y2", d => d.target.y); node .attr("transform", d => `translate(${d.x}, ${d.y})`); }); }
function mouseover(d) { var c = d3.color(d3.interpolateSpectral(d.data.cluster / 20 + 0.1)); div_current.transition().duration(0).style("display", "block"); div_current.html( d.data.name
+ (d.data.wbs ? "
WBS:" + d.data.wbs : "")
).style("background-color", c) .style("left", (d3.event.pageX + 15) + "px") .style("top", (d3.event.pageY - 15) + "px"); }
function mouseout(d) { div_current.transition().duration(0).style("display", "none"); }
function reset_all_nodes() { d3.selectAll(".circle").attr("fill", d => d.data.nodetype == 'project' ? d3.interpolateSpectral(d.data.cluster / 20 + 0.1) : "#eee") .attr("stroke", d => d.data.nodetype == 'project' ? d3.interpolateSpectral(d.data.cluster / 20 + 0.1) : "#000") .attr("r", d => d.data.nodetype == 'project' ? 10 : 7) .attr("stroke-width", 1) .raise(); }
function click(d) { if (d3.event.defaultPrevented) return; // dragged
var html_content;
if (d.data.nodetype == "cluster") {
html_content = "
" + d.data.name + "
"; html_content += "Keywords: " + d.data.keywords + "
"; html_content += "Projects
- ";
d.data.children.forEach(function (project) {
html_content += "
- " + project.title + " "; }) html_content += "
";
} else {
var links = "
";
if (d.data.url) { links += " <a class='btn btn-xs btn-primary' href='" + d.data.url + "' target='_blank'>Website</a> "; } else { links += " <a class='btn btn-xs btn-primary disabled' href='#' target='_blank'>Website</a> "; }
links += " <a class='btn btn-xs btn-primary disabled' href='#' target='_blank'>Reports</a> ";
links += " <a class='btn btn-xs btn-secondary' href='https://google.com/search?q=\"SESAR\" " + d.data.title.replace(/[^a-zA-Z0-9]/g, " ") + "' target='_blank'>Web search</a>";links += "
"; var info = "
- ";
info += "
- " + doc + " "; }) info += "
Call: " + d.data.call + "
";
info += "Call ID: " + d.data.callid + "
";
info += "Partners: " + (d.data.partners ? d.data.partners : "n/a") + "
";
info += "Theme: " + (d.data.theme ? d.data.theme : "n/a") + "
";
info += "Budget: " + (d.data.budget ? d.data.budget : "n/a") + "
";
info += "Duration: " + d.data.start + " - " + d.data.close + "
";
info += "Deliverables:
";
info += "- "
d.data.docs.forEach(function (doc) {info += "
";
html_content = d.data.title + links
+ "
"
+ info
+ "
"
+ " Keywords
"
+ "
" + d.data.keywords + "
";
}
div_selected_content.html(html_content); div_selected .style("background-color", "#dddddd") .style("display", "block");
reset_all_nodes();
d3.select(this).attr("stroke-width", 5) .attr("stroke", "black");
}
function drag(simulation) {
function dragstarted(d) { if (!d3.event.active) simulation.alphaTarget(0.1).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; }
return d3.drag() .on("start", dragstarted) .on("drag", dragged) .on("end", dragended); }
</script> <footer>
<img src="extensions/ComplexWorld/visuals/assets/sesar_logo.png" height="40px" class="mr-2" /> <img src="extensions/ComplexWorld/visuals/assets/eu_logo.jpg" height="40px" class="mr-2" />
This project has received funding from the SESAR Joint Undertaking under the European Union's Horizon 2020 research and innovation programme under grant agreement No 783287.
</footer>