Widget:Interactive research map of ATM

From EngageWiki
Revision as of 20:45, 3 December 2021 by WikiVisor (talk | contribs)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
<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>
       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 += "
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:
    "


           d.data.docs.forEach(function (doc) {
    
    info += "
  • " + doc + "
  • "; }) info += "
"; 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>

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.