- Timestamp:
- 01/13/13 14:23:17 (11 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
SMC/trunk/SMC/src/web/scripts/js/cmd-dep-graph.js
r2455 r2456 6 6 var data_all = null; // global holder for all (input) data 7 7 var nodes_sel = null; // global holder for selected data (selected nodes) 8 var data_show = null; // global holder for data to show closure over data_sel8 var data_show = null; // global holder for data to show closure over nodes_sel 9 9 var nest = {}; 10 10 var detail_data = null; // global holder for detail-data (in html) … … 30 30 var opts = {"depth-before": {"value":2, "min":0, "max":10, "widget":"slider"}, 31 31 "depth-after":{"value":2, "min":0, "max":10, "widget":"slider"}, 32 "link-distance": {"value": 30, "min":10, "max":200, "widget":"slider" },32 "link-distance": {"value":80, "min":10, "max":200, "widget":"slider" }, 33 33 "charge":{"value":400, "min":10, "max":1000, "widget":"slider" }, 34 34 "node-weight": {"value":"1", "values":["1","usage"], "widget":"selectone" }, 35 35 "curve": {"value":"straight", "values":["straight","arc"], "widget":"selectone" }, 36 36 "layout": {"value":"horizontal-tree", "values":["vertical-tree", "horizontal-tree", "weak-tree","force","dot"], "widget":"selectone" }, 37 37 "labels": {"value":"hide", "values":["show","hide"], "widget":"selectone" }, 38 38 }; 39 39 40 /** for faster/simpler neighborhood lookup41 from: http://stackoverflow.com/questions/8739072/highlight-selected-node-its-links-and-its-children-in-a-d3-js-force-directed-g42 */43 var linkedByIndex = {};44 var neighbours_in = {};45 var links_in = {};46 var neighbours_out = {};47 var links_out = {};48 49 /** loads from separate file detail info about individual nodes (in html)50 later used in renderDetail()51 invoked during the (jquery-)initalization */52 53 function loadDetailInfo () {54 55 $(detail_info_holder_selector).load(detail_file,function(data) {56 $(detail_container_selector).html(getDetailInfo("summary", "overall"));57 });58 59 60 /* $.get(detail_file, function(data) {61 detail_data = data;62 notify('Detail data loaded');63 64 }); */65 }66 67 function getDetailInfo(type, id) {68 notify("getDetailInfo: #" + type + "-" + id );69 var d = $(detail_info_holder_selector).find("#" + type + "-" + id );70 // notify(d);71 return d.html();72 }73 40 74 41 … … 113 80 src_key = d.source.key; 114 81 trg_key = d.target.key; 115 // generate lookup hashes for neighbours; 116 linkedByIndex[src_key + "," + trg_key] = d; 117 if (d.source) { 118 if (! neighbours_in[trg_key]) { 119 neighbours_in[trg_key] = [d.source]; 120 links_in[trg_key] = [d]; 121 } else { 122 neighbours_in[trg_key].push(d.source); 123 links_in[trg_key].push(d); 124 } 125 } 126 if (d.target) { 127 if (! neighbours_out[src_key]) { 128 neighbours_out[src_key] = [d.target]; 129 links_out[src_key] = [d]; 130 } else { 131 neighbours_out[src_key].push(d.target); 132 links_out[src_key].push(d) ; 133 } 134 } 135 }); 136 137 renderIndex_default(); 138 //renderGraph(data_all, graph_container); 82 }); 83 // generate lookup hashes for neighbours; 84 add_lookups(data_all); 85 86 // should be delivered by the data directly 87 data_all.nodes.forEach(function(d,i) { 88 d.x = d.init_x; 89 d.y = d.init_y; 90 }); 91 92 renderIndex(); 93 139 94 }); 140 95 } 141 96 142 /* there was a strange problem with overloading */ 143 function renderIndex_default () { 144 renderIndex (data_all.nodes, index_container_selector) 145 } 146 147 /** generate the index lists 97 /** put grouped list of nodes into the target container*/ 98 function renderIndex () { 99 renderNodeList (data_all.nodes, index_container_selector) 100 } 101 102 103 /** generate the detail lists 104 @param nodes 105 */ 106 function renderDetail (nodes) { 107 renderNodeList (nodes, detail_container_selector); 108 } 109 110 111 /** generate a grouped (by type) list of nodes 148 112 @param nodes - accepts an array of nodes (like in data.nodes) 149 113 */ 150 function render Index(nodes, target_container_selector) {114 function renderNodeList (nodes, target_container_selector) { 151 115 152 116 nest = d3.nest() … … 158 122 target_container.selectAll("div").remove(); 159 123 160 // rendering extra-information about the displayed data only in detail-index 161 if (target_container_selector != index_container_selector) { 162 target_container.append("span") 163 .text("show nodes: " + data_show.nodes.length + "; " 164 + "show links: " + data_show.links.length); 165 } 124 166 125 167 126 var group_divs = target_container.selectAll("div").data(nest) … … 192 151 } else { 193 152 var item_detail = item_li.append("div") 194 .classed("node-detail", 1);153 .classed("node-detail", 1); 195 154 196 item_detail.text(function (d) { return "links_in: " + dataShowCount(d.key, "links_in") + "; links_out: " + dataShowCount(d.key, "links_out") ; 197 }) 198 .append("a") 199 .attr("href",function (d) { if (d.type.toLowerCase()=='datcat') return d.id 155 item_detail.append("a") 156 .attr("href",function (d) { if (d.type.toLowerCase()=='datcat') return d.id 200 157 else return comp_reg_url + d.id }) 201 .text(function (d) { return d.id }); 202 item_detail.append("div").html( 203 function (d) { var detail_info_div = getDetailInfo(d.type.toLowerCase(), d.key); 204 if (detail_info_div) {return detail_info_div } else 205 { return "<div>No detail</div>"; } 158 .text(function (d) { return d.id }); 159 item_detail.append("div").html( 160 function (d) { 161 var detail_info_div = getDetailInfo(d.type.toLowerCase(), d.key); 162 if (detail_info_div) { 163 return detail_info_div 164 } else { 165 return "<div>No detail</div>"; 166 } 206 167 }); 207 208 168 169 } 209 170 210 }211 //.classed("detail", 1);212 //console.log($(target_container_selector).find(".cmds-ui-block"));213 171 handleUIBlock($(target_container_selector).find(".cmds-ui-block")); 214 172 … … 220 178 return d.name.toLowerCase().indexOf(search_string) > -1; 221 179 }); 222 console.log(filtered_index_nodes);223 180 181 renderIndex(filtered_index_nodes, index_container_selector); 224 182 } 225 183 … … 240 198 $(target_container).text(""); 241 199 } 242 200 201 // information about the displayed data 202 notify("show nodes: " + data_show.nodes.length + "; " 203 + "show links: " + data_show.links.length); 204 205 206 243 207 244 208 var w = $(target_container).width(), … … 251 215 .links(data.links) 252 216 .size([w, h]) 253 // .gravity(0)254 .linkDistance( opt("link-distance"))255 .charge( opt("charge") * -1)217 // .gravity(0.3) 218 .linkDistance(parseInt(opt("link-distance"))) 219 .charge(parseInt(opt("charge")) * -1) 256 220 .on("tick", tick) 257 221 .start(); 258 console.log ("gravity: " + force.gravity() ); 259 // remove old render: 222 // console.log ("gravity: " + force.gravity() ); 223 224 // remove old render: 260 225 d3.select(graph_container_selector).selectAll("svg").remove(); 261 // console.log(force.size())226 262 227 svg = d3.select(graph_container_selector).append("svg:svg") 263 228 .attr("width", w) .attr("height", h); … … 280 245 .data(force.links()) 281 246 .enter().append("svg:path") 282 .attr("class", function(d) { return "link uses"; }) 247 /* .attr("class", function(d) { return "link uses"; })*/ 248 .classed("link", 1) 249 .classed("uses", 1) 250 .classed("highlight", function(d) { d.highlight } ) 283 251 .attr("marker-end", function(d) { return "url(#uses)"; }); 284 252 /* .style("stroke-width", function(d) { return Math.sqrt(d.value); });*/ … … 303 271 .attr("class", function(d) { return "type-" + d.type.toLowerCase()}) 304 272 .classed("selected", function(d) { return d.selected; }) 305 .on("click", function(d) {d.selected= d.selected ? 0 : 1; updateSelected() }) ;306 .on("mouseover", function(d) {console.log(this)});307 308 273 .on("click", function(d) {d.selected= d.selected ? 0 : 1; updateSelected() }) 274 .on("mouseover", highlight("in")).on("mouseout", highlight("out")); 275 276 /* 309 277 var textgroup = svg.append("svg:g").selectAll("g") 310 278 .data(data.nodes) … … 328 296 .attr("y", ".31em") 329 297 .text(function(d) { return d.name; }); 330 331 332 333 /*334 force.start();335 force.tick();336 force.stop();337 338 force.on("tick",tick);339 force.start();340 var n = 100;341 console.log("start ticking");342 for (var i = 0; i < n; ++i) force.tick();343 force.stop();344 298 */ 345 /*346 data.links.forEach(function(d, i) {347 d.source.x -= d.source.init_x;348 d.target.x += d.target.init_x;349 });350 */351 352 function statick(e) {353 354 data.nodes.forEach(function(d,i) {355 d.x = d.init_x;356 d.y = d.init_y;357 });358 359 transform();360 }361 299 362 300 function tick(e) { 363 var link_distance = parseInt(opt("link-distance"));364 var k = 10 * e.alpha;301 var link_distance_int = parseInt(opt("link-distance")); 302 var k = 10 * e.alpha; 365 303 if (opt("layout")=='dot') { 366 var link_distance_int = parseInt(opt("link-distance"));367 304 data.links.forEach(function(d, i) { 368 305 d.source.x = (d.source.init_x / 150 * link_distance_int) ; 369 306 d.target.x = (d.target.init_x / 150 * link_distance_int); 370 //d.target.y += (d.target.init_y / 300 ) * k; 371 /* d.source.x = (d.source.level * link_distance_int) + link_distance_int; 372 d.target.x = (d.target.level * link_distance_int) + link_distance_int;*/ 373 /*d.source.x = d.source.level * 2 * opt("link-distance") + 50; 374 d.target.x = d.target.level * 2 * opt("link-distance") + 50;*/ 307 375 308 }); 376 309 } else if (opt("layout")=='weak-tree') { … … 378 311 d.source.x -= k; 379 312 d.target.x += k; 380 381 //d.source.x -= k * d.source.level / (dataShowCount(d.source.key, "links_out") + 0.1); // 0.1 to prevent div/0382 //d.target.x += k * d.target.level / (dataShowCount(d.target.key, "links_in") + 0.1);383 313 }); 384 314 } else if (opt("layout")=='vertical-tree') { … … 387 317 if (d.source.level==0) { d.source.y = 20 }; 388 318 d.target.x += (d.source.x - d.target.x) * kx; 389 d.target.y += (d.source.y - d.target.y + link_distance ) * ky;319 d.target.y += (d.source.y - d.target.y + link_distance_int) * ky; 390 320 }); 391 321 } else if (opt("layout")=='horizontal-tree') { … … 394 324 if (d.source.level==0) { d.source.x = 20 }; 395 325 d.target.y += (d.source.y - d.target.y) * ky; 396 d.target.x += (d.source.x - d.target.x + link_distance ) * kx;326 d.target.x += (d.source.x - d.target.x + link_distance_int ) * kx; 397 327 }); 398 328 } … … 404 334 });*/ 405 335 406 /* obsoleted:407 /*data.links.forEach(function(d, i) {408 d.source.x -= (k * d.source.init_x / (200 * Math.sqrt(d.source.count)) );409 d.target.x += (k * d.target.init_x / (50 * Math.sqrt(d.target.count)) );410 });*/411 412 /*d.source.y = d.source.init_y - d.source.y * k;413 d.target.y = d.target.init_y + d.target.y * k;*/414 /*d.source.x -= k * d.target.sum_level ;415 d.target.x += k * d.source.sum_level ;*/416 /* d.source.y = d.source.init_y ;417 d.target.y = d.target.init_y;*/418 //d.source.x -= d.source.level * 0.2 ;419 //d.target.x += d.target.level * 0.2;420 336 421 337 transform(); … … 444 360 });*/ 445 361 446 textgroup.attr("transform", function(d) {362 /* textgroup.attr("transform", function(d) { 447 363 return "translate(" + d.x + "," + d.y + ")"; 448 }); 364 });*/ 449 365 } 450 366 … … 484 400 485 401 486 /** generate the detail lists 487 @param nodes 488 */ 489 function renderDetail (nodes) { 490 491 renderIndex (nodes, detail_container_selector); 492 } 493 494 function renderDetail_old (nodes) { 495 /* 496 nest = d3.nest() 497 .key(function(d) { return d.group; }) 498 .sortValues(function(a, b) { return d3.ascending(a.name, b.name); }) 499 .entries(nodes); 500 */ 501 detail_container = d3.select("#detail-container"); 502 detail_container.selectAll("div").remove(); 503 /* 504 var group_divs = detail_container.selectAll("div").data(nest) 505 .enter().append("div") 506 .attr("id", function (d) { return "detail-" + d.key }) 507 .classed("cmds-ui-block init-show", 1); 508 509 var group_headers = group_divs.append("div").classed("header", 1) 510 .text(function (d) { return d.key}); 511 */ 512 var item_li = detail_container.append("div") 513 .append("ul").selectAll(".node-item") 514 .data(nodes) 515 .enter().append("li") 516 .attr("class", "node-item") 517 .attr("id", function (d) { return "n-" + d.name }); 518 item_li.append("span") 519 .text(function (d) { return d.type + ": " + d.name}) 520 .on("click", function(d) { d.selected= d.selected ? 0 : 1 ; updateSelected() }); 521 var item_detail = item_li.append("div") 522 .classed("node-detail", 1); 523 524 item_detail.append("a") 525 .attr("href",function (d) { if (d.type.toLowerCase()=='datcat') return d.id 526 else return comp_reg_url + d.id }) 527 .text(function (d) { return d.id }); 528 item_detail.append("div").html( 529 function (d) { var detail_info_div = getDetailInfo(d.type.toLowerCase(), d.key); 530 if (detail_info_div) {return detail_info_div } else 531 { return "<div>No detail</div>"; } 532 }); 533 534 535 // handleUIBlock($(".cmds-ui-block")); 536 } 537 538 402 /** loads detail info about individual nodes (in html) from separate file 403 later used in renderDetail() 404 invoked during the (jquery-)initalization */ 405 function loadDetailInfo () { 406 407 $(detail_info_holder_selector).load(detail_file,function(data) { 408 $(detail_container_selector).html(getDetailInfo("summary", "overall")); 409 }); 410 } 411 412 function getDetailInfo(type, id) { 413 //notify("getDetailInfo: #" + type + "-" + id ); 414 var d = $(detail_info_holder_selector).find("#" + type + "-" + id ); 415 // notify(d); 416 return d.html(); 417 } 418 419 539 420 /** select the nodes within the specified rectangle. */ 540 421 function selectNodes(nodes, x0, y0, x3, y3) { … … 564 445 565 446 447 // Returns an event handler for fading a given chord group. 448 function highlight() { 449 return function(d, i) { 450 // console.log ("fade:" + d.key); 451 var connected_subgraph_in = neighboursWithLinks(data_show, d,'in', -1); 452 var connected_subgraph_out = neighboursWithLinks(data_show, d,'out', -1); 453 var connected_subgraph = {"nodes": [], "links": []}; 454 connected_subgraph.nodes = connected_subgraph.nodes.concat(connected_subgraph_in.nodes).concat(connected_subgraph_out.nodes); 455 connected_subgraph.links = connected_subgraph.links.concat(connected_subgraph_in.links).concat(connected_subgraph_out.links); 456 add_lookups(connected_subgraph); 457 svg.selectAll("path.link") 458 /* .filter( d.source.index != i && d.target.index != i; })*/ 459 /* .transition()*/ 460 .classed("highlight", function(p) { return connected_subgraph.links_index[p.source.key + ',' + p.target.key] }) 461 .classed("fade", function(p) { return !(connected_subgraph.links_index[p.source.key + ',' + p.target.key]) }); 462 463 svg.selectAll("circle") 464 /* .filter( d.source.index != i && d.target.index != i; })*/ 465 /* .transition()*/ 466 .classed("highlight", function(d) { return connected_subgraph.nodes_in[d.key] || connected_subgraph.nodes_out[d.key] }) 467 .classed("fade", function(d) { return !(connected_subgraph.nodes_in[d.key] || connected_subgraph.nodes_out[d.key]) }); 468 469 }; 470 } 471 566 472 567 473 /** generates the subset of data to display (based on selected nodes + options) … … 574 480 575 481 nodes.forEach(function(n) { 576 var data_add_in = neighboursWithLinks( n,'in', opt("depth-before"));577 var data_add_out = neighboursWithLinks( n,'out', opt("depth-after"));482 var data_add_in = neighboursWithLinks(data_all, n,'in', opt("depth-before")); 483 var data_add_out = neighboursWithLinks(data_all, n,'out', opt("depth-after")); 578 484 data_show_collect.nodes = data_show_collect.nodes.concat(data_add_in.nodes).concat(data_add_out.nodes); 579 485 data_show_collect.links = data_show_collect.links.concat(data_add_in.links).concat(data_add_out.links); … … 584 490 data_show.links = unique_links(data_show_collect.links); 585 491 586 // extend the object, with some lookup hashes on neighbourhood 587 hashes = gen_neighbours(data_show.links); 588 data_show = $.extend(data_show, hashes); 589 /* data_show.nodes.forEach; data_all.links; 590 .filter(function(e) {*/ 591 /* console.log ("DEBUG: links.filter::" + (nodes_sel.indexOf(e.target) > -1 ) )*/ 592 /* return (data_show.nodes.indexOf(data_all.nodes[e.target]) > -1 || data_show.nodes.indexOf(data_all.nodes[e.source]) > -1) */ 593 /* return (data_show.nodes.indexOf(data_all.nodes[e.s]) > -1 || data_show.nodes.indexOf(e.target) > -1) 594 });*/ 595 492 // extend the object, with some lookup hashes on neighbourhood 493 add_lookups(data_show); 494 596 495 return data_show; 597 496 } 598 497 599 498 /** generate lookup hashes for neighbours; 499 for faster/simpler neighborhood lookup 500 from: http://stackoverflow.com/questions/8739072/highlight-selected-node-its-links-and-its-children-in-a-d3-js-force-directed-g 600 501 */ 601 function gen_neighbours(links) { 602 502 function add_lookups(data) { 503 504 var links = data.links; 603 505 var neighbours = {"links_index": {}, 604 506 "nodes_in": {}, "nodes_out": {}, … … 630 532 }); 631 533 632 return neighbours; 633 634 } 635 534 data = $.extend(data, neighbours); 535 return data; 536 } 537 538 539 540 /* item_detail.text(function (d) { return "links_in: " + dataShowCount(d.key, "links_in") + "; links_out: " + dataShowCount(d.key, "links_out") ; 541 })*/ 636 542 function dataShowCount(n_key, info_type) { 637 543 … … 642 548 } 643 549 } 550 644 551 /** returns appropriate link 645 552 */ … … 648 555 } 649 556 650 /** access function to retrieve the neigbours from the hashes 651 especially handles the (necessarily?) empty elements (undefined), 652 as not every position is filled 653 (perhaps other key, than index would be less confusing) 557 558 function neighboursWithLinks (n, dir, depth=1) { 559 return neighboursWithLinks (data_all, n, dir, depth); 560 } 561 /** access function to retrieve the neighbours from the hashes 562 @param dir in|out|any - but "any" branches in unexpected ways (because it goes in and out on every level = it takes all the children of the parent) 563 @param depth 0-n - go depth-levels; negative depth := no depth restriction = go to the end of the paths; 564 @returns a sub-graph 654 565 */ 655 function neighbours (n, dir, depth=1) { 656 var n_in = neighbours_in[n.key] ? neighbours_in[n.key] : [] ; 657 var n_out = neighbours_out[n.key] ? neighbours_out[n.key] : [] ; 658 var result_n; 659 if (dir == 'in' ) { result_n = n_in; } 660 else if (dir == 'out' ) { result_n = n_out; } 661 else { result_n = n_out.concat(n_in); } 662 var n_nextlevel = []; 663 if (depth > 1) { 664 result_n.forEach (function(n) 665 { var n_neighbours = neighbours(n, dir, depth - 1); 666 n_nextlevel = n_nextlevel.concat(n_neighbours); } 667 ) 668 } 669 return result_n.concat(n_nextlevel); 670 671 } 672 673 function neighboursWithLinks (n, dir, depth=1) { 674 var n_in = neighbours_in[n.key] ? neighbours_in[n.key] : [] ; 675 var n_out = neighbours_out[n.key] ? neighbours_out[n.key] : [] ; 676 var l_in = links_in[n.key] ? links_in[n.key] : [] ; 677 var l_out = links_out[n.key] ? links_out[n.key] : [] ; 566 function neighboursWithLinks (data, n, dir, depth=1) { 567 if (depth==0) { return {nodes:[], links:[]};} 568 569 var n_in = data.nodes_in[n.key] ? data.nodes_in[n.key] : [] ; 570 var n_out = data.nodes_out[n.key] ? data.nodes_out[n.key] : [] ; 571 var l_in = data.links_in[n.key] ? data.links_in[n.key] : [] ; 572 var l_out = data.links_out[n.key] ? data.links_out[n.key] : [] ; 678 573 679 574 var result_n = {nodes:[], links:[]}; … … 682 577 else { result_n.nodes = n_out.concat(n_in); result_n.links = l_out.concat(l_in); } 683 578 var n_nextlevel = {nodes:[], links:[]}; 684 if (depth > 1) {579 if (depth > 0 || depth < 0) { 685 580 result_n.nodes.forEach (function(n) 686 { var n_neighbours = neighboursWithLinks( n, dir, depth - 1);581 { var n_neighbours = neighboursWithLinks(data, n, dir, depth - 1); 687 582 n_nextlevel.nodes = n_nextlevel.nodes.concat(n_neighbours.nodes); 688 583 n_nextlevel.links = n_nextlevel.links.concat(n_neighbours.links); … … 694 589 return result_n; 695 590 696 }697 698 function neighbour_links (nodes, dir) {699 var l_result = []700 701 nodes.forEach (function(n) {702 var l_in = links_in[n.key] ? links_in[n.key] : [] ;703 var l_out = links_out[n.key] ? links_out[n.key] : [] ;704 if (dir == 'in' ) { l_result = l_result.concat(l_in); }705 else if (dir == 'out' ) { l_result = l_result.concat(l_out); }706 else { l_result = l_result.concat(l_out.concat(l_in)); }707 } );708 709 return l_result;710 591 } 711 592 … … 723 604 return result; 724 605 } 725 726 606 727 607 /** deduplicates links (based on source-target-index … … 801 681 } 802 682 803 804 /* 805 d3.select(trg_container).selectAll("input").data(opts[) 806 .enter().append("input") 807 .attr("id", "k") 808 .attr("type", "text") 809 .attr("value", "val") 810 // .attr("value", function (d) { return d } ) 811 ; 812 813 */ 683 814 684 } 815 685
Note: See TracChangeset
for help on using the changeset viewer.