- Timestamp:
- 11/25/15 13:01:31 (8 years ago)
- Location:
- SMC/trunk/SMC/src/web
- Files:
-
- 55 added
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
SMC/trunk/SMC/src/web/get.php
r5304 r6846 1 1 <?php 2 header('Access-Control-Allow-Origin: *'); 3 header('Access-Control-Allow-Headers: X-Requested-With, Content-Type'); 2 4 3 5 function file_get_contents_utf8($fn) { 4 $content = file_get_contents($fn); 5 return mb_convert_encoding($content, 'UTF-8', 6 mb_detect_encoding($content, 'UTF-8, ISO-8859-1', true)); 6 $content = file_get_contents($fn); 7 $content = mb_convert_encoding( 8 $content, 9 'UTF-8', 10 mb_detect_encoding($content, 'UTF-8, ISO-8859-1', true) 11 ); 12 return $content; 7 13 } 8 14 9 $link = $_GET['link'];10 $content = file_get_contents_utf8($link);15 $content = file_get_contents_utf8(@$_GET['link']); 16 echo($content); 11 17 12 //$referer = $_SERVER['SERVER_NAME'];13 //echo($referer );14 echo($content);15 16 17 ?> -
SMC/trunk/SMC/src/web/index.html
r6834 r6846 8 8 <link href="scripts/style/smc-graph.css" media="screen" rel="stylesheet" type="text/css" /> 9 9 10 <script src="scripts/js/d3. js" type="text/javascript"></script>11 <script src="scripts/js/jquery/jquery -1.10.2.js" type="text/javascript"></script>12 <script src="scripts/js/jquery/jquery-ui -1.10.4.custom.min.js" type="text/javascript"></script>13 <script src="scripts/js/jquery/jquery.layout- latest.js" type="text/javascript"></script>10 <script src="scripts/js/d3.v2.min.js" type="text/javascript"></script> 11 <script src="scripts/js/jquery/jquery.js" type="text/javascript"></script> 12 <script src="scripts/js/jquery/jquery-ui.min.js" type="text/javascript"></script> 13 <script src="scripts/js/jquery/jquery.layout-1.3.0.rc29.12.js" type="text/javascript"></script> 14 14 <script src="scripts/js/mdservice/mdservice_ui_helpers.js" type="text/javascript"></script> 15 16 15 <script src="scripts/js/query_input/qi.js" type="text/javascript"></script> 16 <script src="scripts/js/query_input/lib/URI.js" type="text/javascript"></script> 17 17 18 18 <script src="scripts/js/config.js" type="text/javascript"></script> … … 26 26 <div class="cmds-ui-block" id="header"><span id="logo"><a href="http://www.clarin.eu"><img src="scripts/style/imgs/clarin-logo.png" alt="CLARIN" /></a></span> 27 27 <div id="site-name">SMC Browser</div><span id="top-menu"> 28 <!-- class="open-in-context" --><a href="."> home </a><a target="_blank" href="docs/userdocs.html"> docs</a><a target="_blank" href="data/smc_stats_summary1.html"> stats</a><a target="_blank" href="docs/examples.html"> examples</a><a target="_blank" href="docs/reports.html"> reports</a></span> 28 <!-- class="open-in-context" --> 29 <a href="."> home </a> 30 <a target="_blank" href="docs/userdocs.html"> docs</a> 31 <!--<a target="_blank" href="data/smc_stats_summary1.html"> stats</a>--> 32 <a target="_blank" href="docs/examples.html"> examples</a> 33 <!--<a target="_blank" href="docs/reports.html"> reports</a>--> 34 </span> 29 35 <div id="notify" class="cmds-elem-plus note"> 30 36 <div id="notifylist" class="note"> -
SMC/trunk/SMC/src/web/scripts/js/config.js
r6834 r6846 1 2 var config ={ 3 "url": {// "data_prefix":"data/", 4 "data_prefix":"/graph-data/", 5 //"detail":"get.xql" , 6 "detail":"http://localhost:8082/exist/rest/db/cr-projects/tester/get.xql?key=", 7 // "detail":"http://localhost:8580/exist/apps/smc-browser/get.xql" , 8 // "detail":"data/smc_stats_detail.html", 9 "userdocs":"docs/userdocs.html" 10 }, 11 "mode":"dynamic", // "static | dynamic" 12 "min_circle":4, 13 "max_circle":80, 14 "base_font_size":10, 15 "select_rect_min_size":5, 16 "first_level_margin":20, 17 "show_count":1 18 1 var config = { 2 "url": { 3 "data_prefix":"", 4 //"detail":"get.xql" , 5 //"detail":"http://localhost:8580/exist/apps/smc-browser/get.xql" , 6 //"detail":"http://localhost:8082/exist/rest/db/cr-projects/tester/get.xql?key=", 7 //"detail":"data/smc_stats_detail.html", 8 "detail":"docs/empty.html", 9 "userdocs":"docs/userdocs.html" 10 }, 11 "mode":"dynamic", // "static | dynamic" 12 "min_circle":4, 13 "max_circle":80, 14 "base_font_size":10, 15 "select_rect_min_size":5, 16 "first_level_margin":20, 17 "show_count":1 19 18 }; 20 19 21 20 // configuration of the navigation widgets 22 var opts = {"graph": {"value":"issues/issues_all_c747_2015-03-20_graph.json", 23 "values":[{value: "smc/smc-graph-basic.js", label:"SMC graph basic"}, 24 {value: "smc/smc-graph-all.js", label:"SMC graph all"}, 25 {value: "smc/smc-graph-profiles-datcats.js", label:"only profiles + datcats"}, 26 {value: "smc/smc-graph-groups-profiles-datcats-rr.js", label:"profiles+datcats+groups+rr"}, 27 {value: "smc/smc-graph-profiles-similarity.js", label:"profiles similarity"}, 28 {value: "philosophers/dbpedia_philosophers_influence_years_graph.json", label:"Philosophers"}, 29 {value: "SC_Persons_120201_cAll_graph.json", label:"Schnitzler Cooccurrences"}, 30 {value: "issues/issues_all_c747_2015-03-20_graph.json", label:"Issues"}, 31 32 /*, 33 {value: "smc-graph-mdrepo-stats.js", label:"instance data"}*/ 34 35 ], "widget":"selectone" }, 36 "depth-before": {"value":2, "min":0, "max":10, "widget":"slider"}, 37 "depth-after":{"value":2, "min":0, "max":10, "widget":"slider"}, 38 "link-distance": {"value":120, "min":10, "max":300, "widget":"slider" }, 39 "charge":{"value":250, "min":10, "max":1000, "widget":"slider" }, 40 "friction":{"value":75, "min":1, "max":100, "widget":"slider" }, 41 "gravity":{"value":10, "min":1, "max":100, "widget":"slider" }, 42 "node-size": {"value":"4", "values":["1","4","8","16","count"], "widget":"selectone" }, 43 "link-width": {"value":"1", "values":["1","value"], "widget":"selectone" }, 44 "weight":{"value":100, "min":1, "max":100, "widget":"slider" }, 45 "labels": {"value":"show", "values":["show","hide"], "widget":"selectone" }, 46 "curve": {"value":"straight-arrow", "values":["straight-line","arc-line","straight-arrow","arc-arrow"], "widget":"selectone" }, 47 "layout": {"value":"horizontal-tree", "values":["vertical-tree", "horizontal-tree", "weak-tree","force","dot", "freeze"], "widget":"selectone" }, 48 "selected": {"widget":"hidden" }, 49 "link": {"widget":"link", "label":""}, 50 "download": {"widget":"link", "label":""}, 51 "add_profile": {"widget":"link", "label":"Add profile", "widget":""} 52 }; 21 var opts = { 22 "graph": { 23 "value":"data/philosophers/dbpedia_philosophers_influence_years_graph.json", 24 "values":[ 25 {value: "data/smc/smc-graph-basic.js", label:"SMC graph basic"}, 26 {value: "data/smc/smc-graph-all.js", label:"SMC graph all"}, 27 {value: "data/smc/smc-graph-profiles-datcats.js", label:"only profiles + datcats"}, 28 {value: "data/smc/smc-graph-groups-profiles-datcats-rr.js", label:"profiles+datcats+groups+rr"}, 29 {value: "data/smc/smc-graph-profiles-similarity.js", label:"profiles similarity"}, 30 {value: "data/philosophers/dbpedia_philosophers_influencedBy_graph.json", label:"Philosophers influenced by"}, 31 {value: "data/philosophers/dbpedia_philosophers_influence_graph.json", label:"Philosophers influence"}, 32 {value: "data/philosophers/dbpedia_philosophers_influence_years_graph.json", label:"Philosophers influence years"} 33 /*{value: "SC_Persons_120201_cAll_graph.json", label:"Schnitzler Cooccurrences"}*/ 34 /*{value: "issues/issues_all_c747_2015-03-20_graph.json", label:"Issues"}*/ 35 /*{value: "smc-graph-mdrepo-stats.js", label:"instance data"}*/ 36 ], 37 "widget":"selectone" 38 }, 39 "depth-before": {"value":2, "min":0, "max":10, "widget":"slider"}, 40 "depth-after":{"value":2, "min":0, "max":10, "widget":"slider"}, 41 "link-distance": {"value":120, "min":10, "max":300, "widget":"slider" }, 42 "charge":{"value":250, "min":10, "max":1000, "widget":"slider" }, 43 "friction":{"value":75, "min":1, "max":100, "widget":"slider" }, 44 "gravity":{"value":10, "min":1, "max":100, "widget":"slider" }, 45 "node-size": { 46 "value":"4", 47 "values":["1","4","8","16","count"], 48 "widget":"selectone" 49 }, 50 "link-width": { 51 "value":"1", 52 "values":["1","value"], 53 "widget":"selectone" 54 }, 55 "weight":{"value":100, "min":1, "max":100, "widget":"slider" }, 56 "labels": { 57 "value":"show", 58 "values":["show","hide"], 59 "widget":"selectone" 60 }, 61 "curve": { 62 "value":"straight-arrow", 63 "values":["straight-line","arc-line","straight-arrow","arc-arrow"], 64 "widget":"selectone" 65 }, 66 "layout": { 67 "value":"horizontal-tree", 68 "values":["vertical-tree", "horizontal-tree", "weak-tree","force","dot", "freeze"], 69 "widget":"selectone" 70 }, 71 "selected": {"widget":"hidden" }, 72 "link": {"widget":"link", "label":""}, 73 "download": {"widget":"link", "label":""}, 74 "add_profile": {"widget":"link", "label":"Add profile", "widget":""} 75 }; -
SMC/trunk/SMC/src/web/scripts/js/jquery/jquery.layout-1.3.0.rc29.12.js
r2438 r6846 1430 1430 1431 1431 if ($C.is(":visible") && $C.innerHeight() < 2){ 1432 alert( lang.errContainerHeight.replace(/CONTAINER/, sC.ref) );1432 console.log( lang.errContainerHeight.replace(/CONTAINER/, sC.ref) ); 1433 1433 } 1434 1434 … … 1756 1756 1757 1757 if ($Container.innerHeight() < 2){ 1758 alert( lang.errContainerHeight.replace(/CONTAINER/, sC.ref) );1758 console.log( lang.errContainerHeight.replace(/CONTAINER/, sC.ref) ); 1759 1759 } 1760 1760 -
SMC/trunk/SMC/src/web/scripts/js/main.js
r6834 r6846 10 10 var navi_container_selector = '#navigate'; 11 11 var detail_container_selector = "#detail-container"; 12 var detail_info_holder_selector = 12 var detail_info_holder_selector = '#detail-info-holder'; 13 13 var graph_container = null; 14 var index_container = null; 14 var index_container = null; 15 15 16 $(function (){17 18 19 try{20 21 }catch(e){22 23 24 25 26 27 // loading userdocs as welcome info28 $(graph_container).load(config.url.userdocs + " div.document");29 30 loadDetailInfo();31 32 33 34 35 36 37 createBlock('base','');38 39 40 16 $(function () { 17 18 // check for jQuery 19 try { 20 jQuery; 21 } catch (e) { 22 alert('You need to include jQuery!'); 23 } 24 25 graph_container = $(graph_container_selector); 26 27 // loading userdocs as welcome info 28 $(graph_container).load(config.url.userdocs + " div.document"); 29 30 loadDetailInfo(); 31 32 addFunctionality(); 33 34 initGraph(opt("graph")); 35 36 ////////////// CREATE UI-LAYOUT 37 createBlock('base', ''); 38 createLayouts('base'); 39 40 41 41 }); 42 42 … … 45 45 * @function 46 46 */ 47 function addFunctionality() {48 47 function addFunctionality() { 48 49 49 // $("#input-filter-index").live('change', function(event) { 50 $( document ).on( "change", '#input-filter-index', function(event) {51 filterIndex($(this).val());52 53 50 $(document).on("change", '#input-filter-index', function (event) { 51 filterIndex($(this).val()); 52 }); 53 54 54 /*fillOpts(navi_container_selector); 55 $("#navigate .slider").slider();56 */57 $("#navigate").QueryInput({params: opts, onValueChanged: renderGraph});58 59 /* $('#infovis-wrapper').resizable( {60 61 62 63 64 65 66 67 68 55 $("#navigate .slider").slider(); 56 */ 57 $("#navigate").QueryInput({params: opts, onValueChanged: renderGraph}); 58 59 /* $('#infovis-wrapper').resizable( { 60 start: function(event, ui) { 61 graph_container.hide(); 62 }, 63 stop: function(event, ui) { 64 graph_container.show(); 65 renderGraph(); 66 } 67 } 68 );*/ 69 69 70 70 /*$('#input-link').live("mousedown", function(event) { 71 console.log(this);72 73 74 75 */76 71 console.log(this); 72 $(this).attr("target", "_blank"); 73 $(this).attr("href", generateLink()); 74 }); 75 */ 76 77 77 //$('#input-download').live("mousedown", genDownload); 78 $( document ).on( "mousedown", '#input-download', genDownload);79 78 $(document).on("mousedown", '#input-download', genDownload); 79 80 80 // $(".detail-caller").live("click", function(event) { 81 $( document ).on( "click", '.detail-caller', function(event) {82 83 84 85 81 $(document).on("click", '.detail-caller', function (event) { 82 //console.log(this); 83 event.preventDefault(); 84 $(this).parent().find('.detail').toggle(); 85 }); 86 86 87 87 // $(".node-item .detail a").live("click", 88 $( document ).on( "click", '.node-item .detail a', function(event) {89 event.preventDefault();90 91 92 93 88 $(document).on("click", '.node-item .detail a', function (event) { 89 event.preventDefault(); 90 key = $(this).attr("data-key"); 91 console.log(key); 92 selectNodeByKey([key]); 93 }); 94 94 95 95 //$("a.scan").live("click", function(event) { 96 $( document ).on( "click", 'a.scan', function(event) {97 98 99 100 101 102 96 $(document).on("click", 'a.scan', function (event) { 97 console.log(this); 98 event.preventDefault(); 99 url = $(this).attr("href"); 100 $(this).parent().find('.node-detail').html("loading"); 101 $(this).parent().find('.node-detail').load(url + " div.content"); 102 }); 103 103 } -
SMC/trunk/SMC/src/web/scripts/js/smc-graph.js
r6834 r6846 3 3 var item_li = null; 4 4 5 var svg 6 var css; 5 var svg = null; // main svg-element 6 var css; 7 7 var data_all = null; // global holder for all (input) data 8 8 var nodes_sel = []; // global holder for selected data (selected nodes) 9 9 var data_show = null; // global holder for data to show closure over nodes_sel 10 var nest = {}; 10 var nest = {}; 11 11 var detail_data = null; // global holder for detail-data (in html) 12 var mode = " dynamic"; // dynamic or static (default) static=load detail data all at once on init;13 12 var mode = "static"; // dynamic or static (default) static=load detail data all at once on init; 13 14 14 15 15 var input_prefix = "input-"; 16 16 var select_rect_min_size = config.select_rect_min_size; 17 var first_level_margin = config.first_level_margin 18 var base_font_size = config.base_font_size 17 var first_level_margin = config.first_level_margin; 18 var base_font_size = config.base_font_size; 19 19 var min_circle = config.min_circle; 20 20 var max_circle = config.max_circle; 21 21 22 22 var show_count = config.show_count; 23 23 24 24 25 25 //var detail_url = "http://localhost:8580/exist/apps/smc-browser/get.xql"; obsoleted by config … … 31 31 /*var source_file = "../scripts/cmd-dep-graph-d3_all_svg.json"*/ 32 32 /*var source_file = "file:/C:/Users/m/3/clarin/_repo/SMC/output/cmd-dep-graph.d3.js" 33 var detail_file = "file:/C:/Users/m/3/clarin/_repo/SMC/output/smc_stats_detail.html"34 */33 var detail_file = "file:/C:/Users/m/3/clarin/_repo/SMC/output/smc_stats_detail.html" 34 */ 35 35 /* 36 var source_file = "/smc/_structure-graph.json";37 var source_file = "cmd-dep-graph.d3.js";38 var detail_file = "smc_stats_detail.html";39 var userdocs_file = "userdocs.html";40 */36 var source_file = "/smc/_structure-graph.json"; 37 var source_file = "cmd-dep-graph.d3.js"; 38 var detail_file = "smc_stats_detail.html"; 39 var userdocs_file = "userdocs.html"; 40 */ 41 41 //now graph-param is used 42 42 //var source_file = "/smc/smc-graph.d3"; … … 49 49 50 50 /** temporary helper function 51 to easily get the param-data52 */51 to easily get the param-data 52 */ 53 53 function opt(key) { 54 var val = $("#navigate").data("qi").getParamValue(key);55 return typeof val == 'undefined' ? "" : val;56 } 57 58 function currentOpts 59 return $("#navigate").data("qi");54 var val = $("#navigate").data("qi").getParamValue(key); 55 return typeof val == 'undefined' ? "" : val; 56 } 57 58 function currentOpts() { 59 return $("#navigate").data("qi"); 60 60 } 61 61 … … 64 64 * @function 65 65 */ 66 function initGraph (graph_source) 67 { 68 69 // load data 70 d3.json(config.url.data_prefix + graph_source, 71 function(json) { 72 // return if data missing 73 if (json==null) { notifyUser("source data missing: " + graph_source ); return null} 74 data_all = json; 75 data_all.nodes_index = {}; 76 data_all.nodes.forEach(function(d){ 77 data_all.nodes_index[d.key] = d; 78 }); 66 function initGraph(graph_source) { 67 68 // load data 69 d3.json(config.url.data_prefix + graph_source, 70 function (json) { 71 // return if data missing 72 if (json == null) { 73 notifyUser("source data missing: " + graph_source); 74 return null 75 } 76 data_all = json; 77 data_all.nodes_index = {}; 78 data_all.nodes.forEach(function (d) { 79 data_all.nodes_index[d.key] = d; 80 }); 81 82 data_all.links.forEach(function (d) { 83 // try to interpret node references as nodes ids 84 // if it fail, try to interpret them as indexes 85 if(data_all.nodes_index.hasOwnProperty(d.source)){ 86 d.source = data_all.nodes_index[d.source]; 87 }else{ 88 d.source = data_all.nodes[d.source]; 89 } 79 90 80 data_all.links.forEach(function(d) { 81 //resolve numeric index to node references 82 src_ix = d.source; 83 d.source = data_all.nodes_index[src_ix]; 84 //d.source.index = src_ix; 85 trg_ix = d.target; 86 d.target = data_all.nodes_index[trg_ix]; 87 //d.target.index = trg_ix; 88 // src_key = d.source.key; 89 // trg_key = d.target.key; 90 if (d.target == null | d.source == null) { 91 notifyUser("nodes for link missing: " + src_ix + " - " + trg_ix); 92 } 93 94 }); 95 // remove links for which nodes are missing! 96 data_all.links = data_all.links.filter(function(d){return (d.source !=null & d.target != null ) } ) 97 91 if(data_all.nodes_index.hasOwnProperty(d.target)){ 92 d.target = data_all.nodes_index[d.target]; 93 }else{ 94 d.target = data_all.nodes[d.target]; 95 } 96 97 if (d.target === null || d.source === null) { 98 notifyUser("nodes for link missing: " + src_ix + " - " + trg_ix); 99 } 100 101 }); 102 // remove links for which nodes are missing! 103 data_all.links = data_all.links.filter(function (d) { 104 return (d.source != null & d.target != null) 105 }) 106 98 107 // generate lookup hashes for neighbours; 99 add_lookups(data_all); 100 101 // get min/max on some properties 102 var init_x_arr = []; 103 data_all.nodes.forEach(function(d,i){init_x_arr.push(d.init_x);}) 104 data_all.init_x_min = d3.min(init_x_arr); 105 data_all.init_x_max = d3.max(init_x_arr); 106 107 var init_level = []; 108 data_all.nodes.forEach(function(d,i){init_level.push(+d.level);}) 109 data_all.level_min = (d3.min(init_level)==d3.max(init_level)) ? (d3.min(init_level) - 1) : d3.min(init_level) ; 110 111 var init_count = []; 112 data_all.nodes.forEach(function(d,i){init_count.push(+d.count);}) 113 114 data_all.count_max = d3.max(init_count); 115 data_all.node_size_ratio = Math.sqrt(data_all.count_max) / max_circle; 116 117 var init_weight = []; 118 data_all.links.forEach(function(d,i){init_weight.push(+d.weight);}) 119 120 data_all.weight_min = d3.min(init_weight); 108 add_lookups(data_all); 109 110 // get min/max on some properties 111 var init_x_arr = []; 112 data_all.nodes.forEach(function (d, i) { 113 init_x_arr.push(d.init_x); 114 }) 115 data_all.init_x_min = d3.min(init_x_arr); 116 data_all.init_x_max = d3.max(init_x_arr); 117 118 var init_level = []; 119 data_all.nodes.forEach(function (d, i) { 120 init_level.push(+d.level); 121 }) 122 data_all.level_min = (d3.min(init_level) == d3.max(init_level)) ? (d3.min(init_level) - 1) : d3.min(init_level); 123 124 var init_count = []; 125 data_all.nodes.forEach(function (d, i) { 126 init_count.push(+d.count); 127 }) 128 129 data_all.count_max = d3.max(init_count); 130 data_all.node_size_ratio = Math.sqrt(data_all.count_max) / max_circle; 131 132 var init_weight = []; 133 data_all.links.forEach(function (d, i) { 134 init_weight.push(+d.weight); 135 }) 136 137 data_all.weight_min = d3.min(init_weight); 121 138 curr_params = $("#navigate").data("qi").params; 122 139 /* if weight is not used (all weight==1 deactivate the weight widget */ 123 if (data_all.weight_min ==1) {124 125 126 /* $("#navigate").init(curr_opts );*/127 128 129 140 if (data_all.weight_min == 1) { 141 142 delete curr_params.weight; 143 /* $("#navigate").init(curr_opts );*/ 144 $("#navigate").QueryInput({params: curr_params, 145 onValueChanged: renderGraph 146 }); 130 147 } else { 131 curr_params.weight = {"value":70, "min":1, "max":100, "widget":"slider"};132 133 134 148 curr_params.weight = {"value": 70, "min": 1, "max": 100, "widget": "slider"}; 149 $("#navigate").QueryInput({params: curr_params, 150 onValueChanged: renderGraph 151 }); 135 152 } 136 137 153 154 138 155 notifyUser("count max: " + data_all.count_max + "; " 139 156 + "node_size_ratio: " + data_all.node_size_ratio); 140 141 142 data_all.nodes.forEach(function(d,i) {143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 */160 renderIndex();161 162 163 });157 158 // should be delivered by the data directly 159 data_all.nodes.forEach(function (d, i) { 160 d.x = d.init_x; 161 d.y = d.init_y; 162 }); 163 164 // get selected nodes (if any) from param 165 selected_ids = opt("selected").split(","); 166 selectNodeByKey(selected_ids); 167 /*var selected_match = 0; 168 for (var i = 0; i < selected_ids.length; i++) 169 { if (data_all.nodes_index[selected_ids[i]]) { 170 data_all.nodes_index[selected_ids[i]].selected = 1; 171 selected_match ++; 172 } 173 } 174 // if something was selected, update and render Graph and Detail 175 if (selected_match) { updateSelected();} 176 */ 177 renderIndex(); 178 179 180 }); 164 181 } 165 182 166 183 /** put grouped list of nodes into the target container*/ 167 function renderIndex 184 function renderIndex(data, target_container_selector) { 168 185 data = typeof data !== 'undefined' ? data : data_all.nodes; 169 186 target_container_selector = typeof target_container_selector !== 'undefined' ? target_container_selector : index_container_selector; 170 renderNodeList (data, target_container_selector);187 renderNodeList(data, target_container_selector); 171 188 } 172 189 173 190 174 191 /** generate the detail lists 175 176 */ 177 function renderDetail (nodes) {178 renderNodeList (nodes, detail_container_selector);192 @param nodes 193 */ 194 function renderDetail(nodes) { 195 renderNodeList(nodes, detail_container_selector); 179 196 } 180 197 … … 182 199 183 200 /** generate a grouped (by type) list of nodes 184 185 */ 186 function renderNodeList 201 @param nodes - accepts an array of nodes (like in data.nodes) 202 */ 203 function renderNodeList(nodes, target_container_selector) { 187 204 188 205 nest = d3.nest() 189 .key(function(d) { return d.type; }) 190 .sortValues(function(a, b) { return d3.ascending(a.name, b.name); }) 191 .entries(nodes); 192 206 .key(function (d) { 207 return d.type; 208 }) 209 .sortValues(function (a, b) { 210 return d3.ascending(a.name, b.name); 211 }) 212 .entries(nodes); 213 193 214 target_container = d3.select(target_container_selector); 194 target_container.selectAll("div.node-detail").remove(); 195 196 var group_divs = target_container.selectAll("div.node-detail").data(nest) 197 .enter().append("div") 198 .attr("id", function (d) { return "detail-" + d.key }) 199 .classed("node-detail cmds-ui-block init-show", 1) 200 // collapse groups in index, but expand right away in detail view 201 //.classed("init-show", (target_container_selector != index_container_selector)); 202 203 var group_headers = group_divs.append("div").classed("header", 1) 204 .text(function (d) { return d.key + " |" + d.values.length + "|"}); 205 206 var list = group_divs.append("div").classed("content",1) 207 .append("ul"); 208 var item_li = list.selectAll(".node-item") 209 .data(function(d) { return d.values; }) 210 .enter().append("li") 211 .attr("class", "node-item"); 212 item_li.append("span") 213 /* .text(function (d) { return d.name})*/ 214 .text(renderItemText) 215 .on("click", function(d) { d.selected= d.selected ? 0 : 1 ; updateSelected() }); 216 217 218 /* slightly different behaviour for the main-index and rendering of the selected nodes in the detail-view */ 219 // console.log("target_container:" + target_container_selector); 220 if (target_container_selector == index_container_selector) { 221 index_container = target_container; 222 item_li.attr("id", function (d) { return "n-" + d.name }) 223 .attr("title", function(d) { return d.id }); 224 item_li.classed("highlight", function (d) { return d.selected }); 225 /* item_li.classed("highlight", liveSelected);*/ 226 227 228 } else { 229 var item_detail = item_li.append("div"); 230 /* .classed("node-detail", 1);*/ 231 232 item_detail.append("a") 233 .attr("href",function (d) { if (d.type.toLowerCase()=='datcat') return d.id 234 else if (d.type.toLowerCase()=='philosopher') return wiki_url + d.id; 235 else return comp_reg_url + d.id }) 236 .text(function (d) { return d.id }); 237 238 profile_item_detail = item_detail.filter(function(d, i) { return d.type.toLowerCase()=='profile' }); 239 profile_item_detail.append("a") 240 .attr("target",'_blank') 241 .attr("href",function (d) { return 'profiles/' + d.key + '.html' }) 242 .text(' html-view '); 243 244 /* profile_item_detail.append("a")*/ 245 /* item_detail.append("a") 246 .classed("scan", function (d) { return !(d.type=='Profile') } ) 247 .attr("target",'_blank') 248 .attr("href",function (d) { if (d.type=='Profile') { return mdrepo_url_search + 'cmd.profile=%22' + d.id + '%22'; } 249 else { return mdrepo_url_scan + 'cmd:' + d.name; } } ) 250 .text(' mdrepo-view ');*/ 251 252 item_detail_detail = item_detail.append("div").html( 253 function (d) { 254 var detail_info_div = getDetailInfo(d.type.toLowerCase(), d.key, this); 255 if (detail_info_div) { 256 return detail_info_div 257 } else { 258 return "<div>No detail</div>"; 259 } 260 }); 261 262 item_detail_detail.classed("node-detail", 1); 263 264 } 265 266 handleUIBlock($(target_container_selector).find(".node-detail.cmds-ui-block")); 267 268 } 269 270 function renderItemText(d) { 215 target_container.selectAll("div.node-detail").remove(); 216 217 var group_divs = target_container.selectAll("div.node-detail").data(nest) 218 .enter().append("div") 219 .attr("id", function (d) { 220 return "detail-" + d.key 221 }) 222 .classed("node-detail cmds-ui-block init-show", 1) 223 // collapse groups in index, but expand right away in detail view 224 //.classed("init-show", (target_container_selector != index_container_selector)); 225 226 var group_headers = group_divs.append("div").classed("header", 1) 227 .text(function (d) { 228 return d.key + " |" + d.values.length + "|" 229 }); 230 231 var list = group_divs.append("div").classed("content", 1) 232 .append("ul"); 233 var item_li = list.selectAll(".node-item") 234 .data(function (d) { 235 return d.values; 236 }) 237 .enter().append("li") 238 .attr("class", "node-item"); 239 item_li.append("span") 240 /* .text(function (d) { return d.name})*/ 241 .text(renderItemText) 242 .on("click", function (d) { 243 d.selected = d.selected ? 0 : 1; 244 updateSelected() 245 }); 246 247 248 /* slightly different behaviour for the main-index and rendering of the selected nodes in the detail-view */ 249 // console.log("target_container:" + target_container_selector); 250 if (target_container_selector == index_container_selector) { 251 index_container = target_container; 252 item_li.attr("id", function (d) { 253 return "n-" + d.name 254 }) 255 .attr("title", function (d) { 256 return d.id 257 }); 258 item_li.classed("highlight", function (d) { 259 return d.selected 260 }); 261 /* item_li.classed("highlight", liveSelected);*/ 262 263 264 } else { 265 var item_detail = item_li.append("div"); 266 /* .classed("node-detail", 1);*/ 267 268 item_detail.append("a") 269 .attr("href", function (d) { 270 if (d.type.toLowerCase() == 'datcat') 271 return d.id 272 else if (d.type.toLowerCase() == 'philosopher') 273 return wiki_url + d.id; 274 else 275 return comp_reg_url + d.id 276 }) 277 .text(function (d) { 278 return d.id 279 }); 280 281 profile_item_detail = item_detail.filter(function (d, i) { 282 return d.type.toLowerCase() == 'profile' 283 }); 284 profile_item_detail.append("a") 285 .attr("target", '_blank') 286 .attr("href", function (d) { 287 return 'profiles/' + d.key + '.html' 288 }) 289 .text(' html-view '); 290 291 /* profile_item_detail.append("a")*/ 292 /* item_detail.append("a") 293 .classed("scan", function (d) { return !(d.type=='Profile') } ) 294 .attr("target",'_blank') 295 .attr("href",function (d) { if (d.type=='Profile') { return mdrepo_url_search + 'cmd.profile=%22' + d.id + '%22'; } 296 else { return mdrepo_url_scan + 'cmd:' + d.name; } } ) 297 .text(' mdrepo-view ');*/ 298 299 item_detail_detail = item_detail.append("div").html( 300 function (d) { 301 var detail_info_div = getDetailInfo(d.type.toLowerCase(), d.key, this); 302 if (detail_info_div) { 303 return detail_info_div 304 } else { 305 return "<div>No detail</div>"; 306 } 307 }); 308 309 item_detail_detail.classed("node-detail", 1); 310 311 } 312 313 handleUIBlock($(target_container_selector).find(".node-detail.cmds-ui-block")); 314 315 } 316 317 function renderItemText(d) { 271 318 if (show_count) { 272 return d.name + ' |' + d.count + '|'; 273 } 274 else { 319 return d.name + ' |' + d.count + '|'; 320 } else { 275 321 return d.name; 276 277 278 279 function filterIndex (search_string){280 var filtered_index_nodes = data_all.nodes.filter(function (d, i) {281 // console.log(d.name.indexOf(search_string));282 return d.name.toLowerCase().indexOf(search_string.toLowerCase()) > -1; 322 } 323 } 324 325 function filterIndex(search_string) { 326 var filtered_index_nodes = data_all.nodes.filter(function (d, i) { 327 // console.log(d.name.indexOf(search_string)); 328 return d.name.toLowerCase().indexOf(search_string.toLowerCase()) > -1; 283 329 }); 284 285 renderIndex(filtered_index_nodes, index_container_selector);330 331 renderIndex(filtered_index_nodes, index_container_selector); 286 332 } 287 333 288 334 289 335 /** render data (data_show) as graph into target-container (graph_container) */ 290 function renderGraph 336 function renderGraph(data, target_container) { 291 337 // setting defaults 292 338 // for now, ignore the params, as they are always the same 293 339 294 340 //data = typeof data !== 'undefined' ? data : dataToShow(nodes_sel); 295 296 if ($(this).is('#input-graph')) { 297 console.log("graph-source changed! reinitializing graph"); 298 initGraph(data); 299 } 300 341 342 try { 343 if ($(this).is('#input-graph')) { 344 console.log("graph-source changed! reinitializing graph"); 345 initGraph(data); 346 } 347 } catch (e) { 348 } 349 301 350 data = dataToShow(nodes_sel); 302 303 target_container = graph_container;304 305 if (data == null) { 306 $(target_container).text("no data to show");307 return;308 309 $(target_container).text("");310 311 312 // compute the maximum number, but only if it will be needed (i.e. node-size=count)313 if (opt("node-size") =="count") {351 352 target_container = graph_container; 353 354 if (data == null) { 355 $(target_container).text("no data to show"); 356 return; 357 } else { 358 $(target_container).text(""); 359 } 360 361 // compute the maximum number, but only if it will be needed (i.e. node-size=count) 362 if (opt("node-size") == "count") { 314 363 var init_count = []; 315 data.nodes.forEach(function(d,i){init_count.push(+d.count);}) 316 data.count_max = d3.max(init_count); 317 data.node_size_ratio = Math.sqrt(data.count_max) / max_circle; 318 } 319 320 // information about the displayed data 321 notifyUser("show nodes: " + data_show.nodes.length + "; " 322 + "show links: " + data_show.links.length + "; " 323 + "max count:" + data.count_max + "; " 324 + "node_size_ration:" + data.node_size_ratio); 325 326 327 328 329 var w = $(target_container).width(), 330 h = $(target_container).height(); 331 332 var ratio = w / (data_all.init_x_max - data_all.init_x_min); 364 data.nodes.forEach(function (d, i) { 365 init_count.push(+d.count); 366 }) 367 data.count_max = d3.max(init_count); 368 data.node_size_ratio = Math.sqrt(data.count_max) / max_circle; 369 } 370 371 // information about the displayed data 372 notifyUser("show nodes: " + data_show.nodes.length + "; " 373 + "show links: " + data_show.links.length + "; " 374 + "max count:" + data.count_max + "; " 375 + "node_size_ration:" + data.node_size_ratio); 376 377 378 379 380 var w = $(target_container).width(), 381 h = $(target_container).height(); 382 383 var ratio = w / (data_all.init_x_max - data_all.init_x_min); 333 384 var node_size_int = parseInt(opt("node-size")); 334 var font_size_int = base_font_size + (node_size_int / 2); 335 var link_distance = parseInt(opt("link-distance"))336 337 338 385 var font_size_int = base_font_size + (node_size_int / 2); 386 var link_distance = parseInt(opt("link-distance")) 387 388 // console.log (w + '-' + h); 389 var force = d3.layout.force() 339 390 .nodes(data.nodes) 340 391 .links(data.links) 341 392 .size([w, h]) 342 393 343 .friction(parseInt(opt("friction")) / 100 344 345 .gravity(parseInt(opt("gravity")) / 100 346 394 .friction(parseInt(opt("friction")) / 100) 395 396 .gravity(parseInt(opt("gravity")) / 100) 397 347 398 .linkDistance(parseInt(opt("link-distance"))) 348 349 /* .linkDistance(function(d){return link_distance / (d.weight * d.value) })*/ 350 /* Profiles: 351 .linkStrength(function(d){return d.value}) 352 353 */ 354 //.charge(parseInt(opt("charge")) * -1) 355 356 if (parseInt(opt("charge"))==0) { 357 force.charge(0); 358 } else { 359 force.charge(function(d) { if (opt("node-size")=="count") 360 {var node_charge = (Math.sqrt(d.count)<=min_circle) ? min_circle : Math.sqrt(d.count) / data.node_size_ratio; 361 //console.log (node_charge + ':' + d.count); 362 return node_charge * -1 * parseInt(opt("charge")); 363 } 364 //{ return -d.count * parseInt(opt("charge")); } 365 else { return parseInt(opt("charge")) * -1} }) 366 } 367 368 force.on("tick", tick) 399 400 /* .linkDistance(function(d){return link_distance / (d.weight * d.value) })*/ 401 /* Profiles: 402 .linkStrength(function(d){return d.value}) 403 404 */ 405 //.charge(parseInt(opt("charge")) * -1) 406 407 if (parseInt(opt("charge")) == 0) { 408 force.charge(0); 409 } else { 410 force.charge(function (d) { 411 if (opt("node-size") == "count") 412 { 413 var node_charge = (Math.sqrt(d.count) <= min_circle) ? min_circle : Math.sqrt(d.count) / data.node_size_ratio; 414 //console.log (node_charge + ':' + d.count); 415 return node_charge * -1 * parseInt(opt("charge")); 416 } 417 //{ return -d.count * parseInt(opt("charge")); } 418 else { 419 return parseInt(opt("charge")) * -1 420 } 421 }) 422 } 423 424 force.on("tick", tick) 369 425 .start(); 370 371 if (opt("layout")=='freeze') { 372 data.nodes.forEach(function(d) { d.fixed=true }); 373 } else { 374 data.nodes.forEach(function(d) { d.fixed=false}); 375 } 376 377 426 427 if (opt("layout") == 'freeze') { 428 data.nodes.forEach(function (d) { 429 d.fixed = true 430 }); 431 } else { 432 data.nodes.forEach(function (d) { 433 d.fixed = false 434 }); 435 } 436 437 378 438 // console.log ("gravity: " + force.gravity() ); 379 380 381 382 383 384 .attr("width", w) 385 386 387 388 if (opt("curve").indexOf("arrow") > -1){439 440 // remove old render: 441 d3.select(graph_container_selector).selectAll("svg").remove(); 442 443 svg = d3.select(graph_container_selector).append("svg:svg") 444 .attr("width", w).attr("height", h); 445 446 // Per-type markers, as they don't inherit styles. 447 448 if (opt("curve").indexOf("arrow") > -1) { 389 449 svg.append("svg:defs").selectAll("marker") 390 .data(["uses"])391 .enter().append("svg:marker")392 .attr("id", String)393 .attr("markerUnits", "userSpaceOnUse")394 .attr("viewBox", "0 -5 10 10")395 .attr("refX", 10)396 /*.attr("refY", -1.5)*/397 .attr("markerWidth", 10)398 .attr("markerHeight", 10)399 .attr("orient", "auto")400 .append("svg:path")401 .attr("d", "M0,-3L10,0L0,3");402 403 404 450 .data(["uses"]) 451 .enter().append("svg:marker") 452 .attr("id", String) 453 .attr("markerUnits", "userSpaceOnUse") 454 .attr("viewBox", "0 -5 10 10") 455 .attr("refX", 10) 456 /*.attr("refY", -1.5)*/ 457 .attr("markerWidth", 10) 458 .attr("markerHeight", 10) 459 .attr("orient", "auto") 460 .append("svg:path") 461 .attr("d", "M0,-3L10,0L0,3"); 462 } 463 464 var path = svg.append("svg:g").selectAll("path") 405 465 .data(force.links()) 406 466 .enter().append("svg:path") 407 /* .attr("class", function(d) { return "link uses"; })*/467 /* .attr("class", function(d) { return "link uses"; })*/ 408 468 .classed("link", 1) 409 469 .classed("uses", 1) 410 .classed("highlight", function(d) { d.highlight } ) 411 .attr("marker-end", function(d) { return "url(#uses)"; }); 412 413 if (opt("link-width")=="value") { 414 path.style("stroke-width", function(d) { return Math.sqrt(d.value); }); 415 /* .style("stroke-width", function(d) { return d.value });*/ 416 } 417 418 path.append("title").text(function(d){ return d.value }); 419 420 var gnodes = svg.append("svg:g") 421 .selectAll("g.node") 422 .data(force.nodes()) 423 .enter().append("g") 424 .attr("class", function(d) { return "node type-" + d.type.toLowerCase()}) 425 .classed("selected", function(d) { return d.selected; }) 426 .call(force.drag); 427 428 // dragging of all selected nodes on freeze layout 429 // this does not work yet 430 /*if (opt("layout")=="freeze") { 431 gnodes.on("mousedown", function() { 432 var m0 = d3.mouse(this); 433 434 gnodes.on("mousemove", function() { 435 var m1 = d3.mouse(this), 436 x0 = Math.min(w, m0[0], m1[0]), 437 y0 = Math.min(w, m0[1], m1[1]), 438 x1 = Math.max(0, m0[0], m1[0]), 439 y1 = Math.max(0, m0[1], m1[1]); 440 // console.log("DEBUG: mousedown: " + (x1-x0) + ( y1-y0)); 441 x_d = (x1 - x0); 442 y_d = (y1 - y0); 443 // y_d = d.y - d.py; 444 // x_d = d.x - d.px; 445 446 nodes_sel.forEach(function (d) { 447 d.x += x_d; 448 d.y += y_d; 449 }); 450 451 }); 452 453 gnodes.on("mouseup", function() { 454 gnodes.on("mousemove", null).on("mouseup", null); 455 }); 456 457 d3.event.preventDefault(); 458 }); 459 } 460 */ 461 gnodes.append("svg:circle") 462 /* .attr("r", 6)*/ 463 .on("click", function(d) {d.selected= d.selected ? 0 : 1; 464 console.log("click:" + d.key); 465 updateSelected(); }) 466 .on("mouseover", highlight()).on("mouseout", unhighlight()) 467 .attr("r", function(d) { if (opt("node-size")=="count") 468 {return (Math.sqrt(d.count)<=min_circle) ? min_circle : Math.sqrt(d.count) / data.node_size_ratio; 469 } 470 else { return node_size_int; } 471 }) 472 473 gnodes.append("title") 474 /* .text(function (d) { return d.name + ' |' + d.count + '|' })*/ 475 .text(renderItemText); 476 477 478 479 480 /* 481 svg.selectAll("circle") 482 .attr("class", function(d) { return "type-" + d.type.toLowerCase()}) 483 .classed("selected", function(d) { return d.selected; }) 484 .on("click", function(d) {d.selected= d.selected ? 0 : 1; updateSelected() }) 485 .on("mouseover", highlight("in")).on("mouseout", highlight("out")); 486 */ 487 488 // A copy of the text with a thick white stroke for legibility. 489 //if (opt("labels") =='show') { 490 gnodes.append("svg:text") 491 .attr("x", 8) 492 .attr("y", ".31em") 493 .style("font-size", function(d) { 494 var fontsize = ''; 495 if (opt("node-size")=="count") 496 { fontsize = (Math.sqrt(d.count)<=min_circle) ? base_font_size : Math.sqrt(d.count) / data.node_size_ratio; 497 } 498 else { fontsize = font_size_int; } 499 return fontsize + 'px'; 500 }) 501 .attr("class", "shadow") 502 .classed("hide", opt("labels")=='hide') 503 .text(function(d) { return d.name; }); 504 gnodes.append("svg:text") 505 .attr("x", 8) 506 .attr("y", ".31em") 507 .style("font-size", function(d) { 508 var fontsize = ''; 509 if (opt("node-size")=="count") 510 { fontsize = (Math.sqrt(d.count)<=min_circle) ? base_font_size : Math.sqrt(d.count) / data.node_size_ratio; 511 } 512 else { fontsize = font_size_int; } 513 return fontsize + 'px'; 514 }) 515 .classed("hide", function(d) { return !d.selected && opt("labels")=='hide'}) 516 .text(function(d) { return d.name; }); 517 //} 518 519 520 var tick_counter=0; 521 function tick(e) { 522 var link_distance_int = parseInt(opt("link-distance")); 523 var k = 10 * e.alpha; 524 if (opt("layout")=='dot') { 470 .classed("highlight", function (d) { 471 d.highlight 472 }) 473 .attr("marker-end", function (d) { 474 return "url(#uses)"; 475 }); 476 477 if (opt("link-width") == "value") { 478 path.style("stroke-width", function (d) { 479 return Math.sqrt(d.value); 480 }); 481 /* .style("stroke-width", function(d) { return d.value });*/ 482 } 483 484 path.append("title").text(function (d) { 485 return d.value 486 }); 487 488 var gnodes = svg.append("svg:g") 489 .selectAll("g.node") 490 .data(force.nodes()) 491 .enter().append("g") 492 .attr("class", function (d) { 493 return "node type-" + d.type.toLowerCase() 494 }) 495 .classed("selected", function (d) { 496 return d.selected; 497 }) 498 .call(force.drag); 499 500 // dragging of all selected nodes on freeze layout 501 // this does not work yet 502 /*if (opt("layout")=="freeze") { 503 gnodes.on("mousedown", function() { 504 var m0 = d3.mouse(this); 505 506 gnodes.on("mousemove", function() { 507 var m1 = d3.mouse(this), 508 x0 = Math.min(w, m0[0], m1[0]), 509 y0 = Math.min(w, m0[1], m1[1]), 510 x1 = Math.max(0, m0[0], m1[0]), 511 y1 = Math.max(0, m0[1], m1[1]); 512 // console.log("DEBUG: mousedown: " + (x1-x0) + ( y1-y0)); 513 x_d = (x1 - x0); 514 y_d = (y1 - y0); 515 // y_d = d.y - d.py; 516 // x_d = d.x - d.px; 517 518 nodes_sel.forEach(function (d) { 519 d.x += x_d; 520 d.y += y_d; 521 }); 522 523 }); 524 525 gnodes.on("mouseup", function() { 526 gnodes.on("mousemove", null).on("mouseup", null); 527 }); 528 529 d3.event.preventDefault(); 530 }); 531 } 532 */ 533 gnodes.append("svg:circle") 534 /* .attr("r", 6)*/ 535 .on("click", function (d) { 536 d.selected = d.selected ? 0 : 1; 537 console.log("click:" + d.key); 538 updateSelected(); 539 }) 540 .on("mouseover", highlight()).on("mouseout", unhighlight()) 541 .attr("r", function (d) { 542 if (opt("node-size") == "count") 543 { 544 return (Math.sqrt(d.count) <= min_circle) ? min_circle : Math.sqrt(d.count) / data.node_size_ratio; 545 } else { 546 return node_size_int; 547 } 548 }) 549 550 gnodes.append("title") 551 /* .text(function (d) { return d.name + ' |' + d.count + '|' })*/ 552 .text(renderItemText); 553 554 555 556 557 /* 558 svg.selectAll("circle") 559 .attr("class", function(d) { return "type-" + d.type.toLowerCase()}) 560 .classed("selected", function(d) { return d.selected; }) 561 .on("click", function(d) {d.selected= d.selected ? 0 : 1; updateSelected() }) 562 .on("mouseover", highlight("in")).on("mouseout", highlight("out")); 563 */ 564 565 // A copy of the text with a thick white stroke for legibility. 566 //if (opt("labels") =='show') { 567 gnodes.append("svg:text") 568 .attr("x", 8) 569 .attr("y", ".31em") 570 .style("font-size", function (d) { 571 var fontsize = ''; 572 if (opt("node-size") == "count") 573 { 574 fontsize = (Math.sqrt(d.count) <= min_circle) ? base_font_size : Math.sqrt(d.count) / data.node_size_ratio; 575 } else { 576 fontsize = font_size_int; 577 } 578 return fontsize + 'px'; 579 }) 580 .attr("class", "shadow") 581 .classed("hide", opt("labels") == 'hide') 582 .text(function (d) { 583 return d.name; 584 }); 585 gnodes.append("svg:text") 586 .attr("x", 8) 587 .attr("y", ".31em") 588 .style("font-size", function (d) { 589 var fontsize = ''; 590 if (opt("node-size") == "count") 591 { 592 fontsize = (Math.sqrt(d.count) <= min_circle) ? base_font_size : Math.sqrt(d.count) / data.node_size_ratio; 593 } else { 594 fontsize = font_size_int; 595 } 596 return fontsize + 'px'; 597 }) 598 .classed("hide", function (d) { 599 return !d.selected && opt("labels") == 'hide' 600 }) 601 .text(function (d) { 602 return d.name; 603 }); 604 //} 605 606 607 var tick_counter = 0; 608 function tick(e) { 609 var link_distance_int = parseInt(opt("link-distance")); 610 var k = 10 * e.alpha; 611 if (opt("layout") == 'dot') { 525 612 var offset = data_all.init_x_min; 526 613 /*data.links.forEach(function(d, i) { 527 528 529 530 });*/531 532 data.nodes.forEach (function(d,i) {533 d.x = d.init_x * ratio - link_distance_int; 614 d.source.x = (d.source.init_x / 150 * link_distance_int) ; 615 d.target.x = (d.target.init_x / 150 * link_distance_int); 616 617 });*/ 618 619 data.nodes.forEach(function (d, i) { 620 d.x = d.init_x * ratio - link_distance_int; 534 621 }); 535 536 } else if (opt("layout")=='weak-tree') {537 data.links.forEach(function(d, i) {538 d.source.x -= k;622 623 } else if (opt("layout") == 'weak-tree') { 624 data.links.forEach(function (d, i) { 625 d.source.x -= k; 539 626 d.target.x += k; 540 }); 541 } else if (opt("layout")=='vertical-tree') { 542 var ky= 1.4 * e.alpha, kx = .4 * e.alpha; 543 data.links.forEach(function(d, i) { 544 if (d.source.level==data_all.level_min) { d.source.y = first_level_margin }; 545 // d.target.x += (d.source.x - d.target.x) * kx; 546 d.target.y += (d.source.y - d.target.y + link_distance_int) * ky; 547 }); 548 } else if (opt("layout")=='horizontal-tree') { 549 var kx= 1.4 * e.alpha, ky = .4 * e.alpha; 550 data.links.forEach(function(d, i) { 551 //if (d.source.level==data_all.level_min) { d.source.x = first_level_margin }; 552 if (data_show.roots.indexOf(d.source.key) > -1 ) { d.source.x = first_level_margin }; 553 //d.target.y += (d.source.y - d.target.y) * ky; 554 d.target.x += (d.source.x - d.target.x + link_distance_int ) * kx; 555 //d.target.x += (d.source.x - d.target.x ) * kx; 556 }); 557 } 558 /* parent foci 559 var kx = 1.2 * e.alpha; 560 data.links.forEach(function(d, i) { 561 d.target.x += (d.target.level * link_distance - d.target.x) * kx; 562 });*/ 563 564 tick_counter ++; 565 if (tick_counter % 2 == 0) {transform(); } 566 } // end tick() 567 568 569 function transform () { 570 571 path.attr("d", function(d) { 572 // links as elliptical arc path segments 627 }); 628 } else if (opt("layout") == 'vertical-tree') { 629 var ky = 1.4 * e.alpha, kx = .4 * e.alpha; 630 data.links.forEach(function (d, i) { 631 if (d.source.level == data_all.level_min) { 632 d.source.y = first_level_margin 633 } 634 ; 635 // d.target.x += (d.source.x - d.target.x) * kx; 636 d.target.y += (d.source.y - d.target.y + link_distance_int) * ky; 637 }); 638 } else if (opt("layout") == 'horizontal-tree') { 639 var kx = 1.4 * e.alpha, ky = .4 * e.alpha; 640 data.links.forEach(function (d, i) { 641 //if (d.source.level==data_all.level_min) { d.source.x = first_level_margin }; 642 if (data_show.roots.indexOf(d.source.key) > -1) { 643 d.source.x = first_level_margin 644 } 645 ; 646 //d.target.y += (d.source.y - d.target.y) * ky; 647 d.target.x += (d.source.x - d.target.x + link_distance_int) * kx; 648 //d.target.x += (d.source.x - d.target.x ) * kx; 649 }); 650 } 651 /* parent foci 652 var kx = 1.2 * e.alpha; 653 data.links.forEach(function(d, i) { 654 d.target.x += (d.target.level * link_distance - d.target.x) * kx; 655 });*/ 656 657 tick_counter++; 658 if (tick_counter % 2 == 0) { 659 transform(); 660 } 661 } // end tick() 662 663 664 function transform() { 665 666 path.attr("d", function (d) { 667 // links as elliptical arc path segments 573 668 if (opt("curve").indexOf("arc") > -1) 574 { var dx = d.target.x - d.source.x, 575 dy = d.target.y - d.source.y, 576 dr = Math.sqrt(dx * dx + dy * dy); 669 { 670 var dx = d.target.x - d.source.x, 671 dy = d.target.y - d.source.y, 672 dr = Math.sqrt(dx * dx + dy * dy); 577 673 return "M" + d.source.x + "," + d.source.y + "A" + dr + "," + dr + " 0 0,1 " + d.target.x + "," + d.target.y; 578 } else { 579 // or straight674 } else { 675 // or straight 580 676 return "M" + d.source.x + "," + d.source.y + "L" + d.target.x + "," + d.target.y; 581 } 582 });583 584 585 586 gnodes.attr("transform", function(d) {677 } 678 }); 679 680 /*circle.attr("cx", function(d) {return d.x;}) 681 .attr("cy", function(d) {return d.y;});*/ 682 gnodes.attr("transform", function (d) { 587 683 return "translate(" + d.x + "," + d.y + ")"; 588 });589 590 /* textgroup.attr("transform", function(d) {591 592 });*/593 } 594 595 596 svg.on("mousedown", function() {597 598 599 600 .style("fill", "#999")601 .style("fill-opacity", .5);602 603 d3.select(window).on("mousemove", function() {684 }); 685 686 /* textgroup.attr("transform", function(d) { 687 return "translate(" + d.x + "," + d.y + ")"; 688 });*/ 689 } 690 691 // Highlight selected nodes using the quadtree. 692 svg.on("mousedown", function () { 693 var m0 = d3.mouse(this); 694 695 var rect = d3.select(this).append("rect") 696 .style("fill", "#999") 697 .style("fill-opacity", .5); 698 699 d3.select(window).on("mousemove", function () { 604 700 var m1 = d3.mouse(rect.node()), 605 x0 = Math.min(w, m0[0], m1[0]),606 y0 = Math.min(w, m0[1], m1[1]),607 x1 = Math.max(0, m0[0], m1[0]),608 y1 = Math.max(0, m0[1], m1[1]);609 610 selectNodes(data.nodes, x0, y0, x1, y1);611 612 613 614 615 d3.select(window).on("mouseup", function() {701 x0 = Math.min(w, m0[0], m1[0]), 702 y0 = Math.min(w, m0[1], m1[1]), 703 x1 = Math.max(0, m0[0], m1[0]), 704 y1 = Math.max(0, m0[1], m1[1]); 705 // console.log("DEBUG: mousedown: " + (x1-x0) + ( y1-y0)); 706 selectNodes(data.nodes, x0, y0, x1, y1); 707 rect.attr("x", x0).attr("y", y0).attr("width", x1 - x0).attr("height", y1 - y0); 708 709 }); 710 711 d3.select(window).on("mouseup", function () { 616 712 // only change selection, if the rectangle was big enough 617 713 // (mainly to prevent clearing of the graph on clicks that look like mousemoves to the system) … … 621 717 rect.remove(); 622 718 d3.select(window).on("mousemove", null).on("mouseup", null); 623 624 625 626 719 }); 720 721 d3.event.preventDefault(); 722 }); 627 723 } // end renderGraph 628 724 629 725 630 726 /** loads detail info about individual nodes (in html) from separate file 631 later used in renderDetail() 632 invoked during the (jquery-)initalization */ 633 function loadDetailInfo () { 634 635 if (mode=='static') { 636 $(detail_info_holder_selector).load(config.url.detail,function(data) { 637 $(detail_container_selector).find("h3").after( 638 '<div id="detail-summary-overall" class="cmds-ui-block init-show" ><div class="header">Overview</div><div class="content">' 639 + getDetailInfo("summary", "overall") + '</div></div>'); 640 641 handleUIBlock($(detail_container_selector).find(".cmds-ui-block")); 642 643 // only render detail for initially selected nodes, after the detail info has been loaded 644 if (nodes_sel) { renderDetail(nodes_sel) }; 645 646 }); 647 } else { 648 var target_container = $(detail_container_selector).append( 649 '<div id="detail-summary-overall" class="cmds-ui-block init-show" ><div class="header">Overview</div></div>'); 650 $(detail_container_selector).find('#detail-summary-overall').append('<div class="content"></div>'); 651 target = $(detail_container_selector).find("#detail-summary-overall .content") 652 getDetailInfo("summary", "overall", target, function() { 653 handleUIBlock($(detail_container_selector).find(".cmds-ui-block")); 654 }); 655 656 } 657 658 // loading css to store in extra variable, for later use = injecting into exported SVG 659 $.get("scripts/style/smc-graph.css", function(data) { 660 // console.log(data) 661 css = data 662 }); 663 664 } 665 666 function getDetailInfo(type, id, target,load_callback) { 727 later used in renderDetail() 728 invoked during the (jquery-)initalization */ 729 function loadDetailInfo() { 730 if (mode == 'static') { 731 $(detail_info_holder_selector).load(config.url.detail, function (data) { 732 $(detail_container_selector).find("h3").after( 733 '<div id="detail-summary-overall" class="cmds-ui-block init-show" ><div class="header">Overview</div><div class="content">' + 734 getDetailInfo("summary", "overall") + 735 '</div></div>' 736 ); 737 738 handleUIBlock($(detail_container_selector).find(".cmds-ui-block")); 739 740 // only render detail for initially selected nodes, after the detail info has been loaded 741 if (nodes_sel) { 742 renderDetail(nodes_sel) 743 } 744 ; 745 746 }); 747 } else { 748 var target_container = $(detail_container_selector).append( 749 '<div id="detail-summary-overall" class="cmds-ui-block init-show" ><div class="header">Overview</div></div>' 750 ); 751 $(detail_container_selector).find('#detail-summary-overall').append('<div class="content"></div>'); 752 target = $(detail_container_selector).find("#detail-summary-overall .content") 753 getDetailInfo("summary", "overall", target, function () { 754 handleUIBlock($(detail_container_selector).find(".cmds-ui-block")); 755 }); 756 } 757 758 // loading css to store in extra variable, for later use = injecting into exported SVG 759 $.get("scripts/style/smc-graph.css", function (data) { 760 // console.log(data) 761 css = data 762 }); 763 } 764 765 function getDetailInfo(type, id, target, load_callback) { 667 766 //notify("getDetailInfo: #" + type + "-" + id ); 668 669 if (type=='philosopher') { 670 // access origin problem! 671 url = "http://localhost/smc-dev/get.php?link=" + wiki_url + id; 672 $(target).load(url + " .infobox"); 673 } else 674 if (mode=='static' ) { 675 var d = $(detail_info_holder_selector).find("#" + type + "-" + id ); 676 return d.html(); 677 } else { 678 var url = config.url.detail + "?type=" + type + "&key=" + id; 679 console.log("get-detail:" + url ); 680 $(target).toggleClass("loading"); 681 $(target).load(url,load_callback); 682 } 767 768 if (type == 'philosopher') { 769 url = "get.php?link=" + wiki_url + id; 770 $(target).load(url + " .infobox"); 771 } else if (mode == 'static') { 772 var d = $(detail_info_holder_selector).find("#" + type + "-" + id); 773 return d.html(); 774 } else { 775 var url = config.url.detail + "?type=" + type + "&key=" + id; 776 console.log("get-detail:" + url); 777 $(target).toggleClass("loading"); 778 $(target).load(url, load_callback); 779 } 683 780 // notify(d); 684 781 685 782 } 686 783 687 784 /** generates a base64-data encoded url out of the current svg 688 does some preprocessing: injects the css and sets the @viewBox, @width and @height attributes to ensure,689 that everything is visible in the exported svg.690 later perhaps even exporting to server, for rendering to PNG, PDF691 http://d3export.cancan.cshl.edu/692 called on mousedown of the download-link, so assumes the <a>-element as this693 */694 function genDownload 785 does some preprocessing: injects the css and sets the @viewBox, @width and @height attributes to ensure, 786 that everything is visible in the exported svg. 787 later perhaps even exporting to server, for rendering to PNG, PDF 788 http://d3export.cancan.cshl.edu/ 789 called on mousedown of the download-link, so assumes the <a>-element as this 790 */ 791 function genDownload(event) { 695 792 //console.log("genDownload:" + this); 696 793 … … 700 797 var margin = 30; 701 798 var link_dist = parseInt(opt("link-distance")); 702 799 703 800 var x, y, w, h; 704 x = Math.floor(bounds["x-min"]) - margin 801 x = Math.floor(bounds["x-min"]) - margin 705 802 y = Math.floor(bounds["y-min"]) - margin 706 803 // add extra space to the right, because of the possible labels 707 w = (bounds["width"] > svg_w) ? bounds["width"] + 2 * margin + link_dist : svg_w + link_dist; 804 w = (bounds["width"] > svg_w) ? bounds["width"] + 2 * margin + link_dist : svg_w + link_dist; 708 805 h = (bounds["height"] > svg_h) ? bounds["height"] + 2 * margin : svg_h; 709 806 710 807 var viewBox = x + " " + y + " " + w + " " + h; 711 808 712 svg.attr("title", "SMC Browser - export")713 .attr("version", 1.1)714 .attr("viewBox", viewBox)715 .attr("width", w)716 .attr("height", h)717 .attr("xmlns", "http://www.w3.org/2000/svg");718 var style = svg.append("style");719 720 721 722 var html = svg.node().parentNode.innerHTML;723 724 /* $(html).append("<style type='text/css'><![CDATA[" + css + "]]> </style>" );*/725 726 809 svg.attr("title", "SMC Browser - export") 810 .attr("version", 1.1) 811 .attr("viewBox", viewBox) 812 .attr("width", w) 813 .attr("height", h) 814 .attr("xmlns", "http://www.w3.org/2000/svg"); 815 var style = svg.append("style"); 816 style.attr("type", 'text/css'); 817 style.text(css); 818 819 var html = svg.node().parentNode.innerHTML; 820 821 /* $(html).append("<style type='text/css'><![CDATA[" + css + "]]> </style>" );*/ 822 823 727 824 //console.log(html); 728 825 729 826 $(this).attr("title", "smc-browser-export.svg") 730 .attr("target", "_blank")731 .attr("href-lang", "image/svg+xml")732 .attr("href", "data:image/svg+xml;base64,\n" + btoa(html));733 827 .attr("target", "_blank") 828 .attr("href-lang", "image/svg+xml") 829 .attr("href", "data:image/svg+xml;base64,\n" + btoa(html)); 830 734 831 } 735 832 … … 737 834 /** select the nodes within the specified rectangle. */ 738 835 function selectNodes(nodes, x0, y0, x3, y3) { 739 740 var points = [];741 nodes.forEach(function(n) {742 if (n && (n.x >= x0) && (n.x < x3) && (n.y >= y0) && (n.y < y3)) {836 837 var points = []; 838 nodes.forEach(function (n) { 839 if (n && (n.x >= x0) && (n.x < x3) && (n.y >= y0) && (n.y < y3)) { 743 840 points.push(n); 744 841 n.selected = 1; … … 746 843 n.selected = 0; 747 844 } 748 /* return x1 >= x3 || y1 >= y3 || x2 < x0 || y2 < y0;*/749 });750 return points;845 /* return x1 >= x3 || y1 >= y3 || x2 < x0 || y2 < y0;*/ 846 }); 847 return points; 751 848 } 752 849 … … 754 851 755 852 // get selected nodes (if any) from param 756 var selected_match = 0; 757 for (var i = 0; i < nodes_keys.length; i++) 758 { if (data_all.nodes_index[nodes_keys[i]]) { 759 data_all.nodes_index[nodes_keys[i]].selected = 1; 760 selected_match ++; 761 } 762 } 763 // if something was selected, update and render Graph and Detail 764 if (selected_match) { updateSelected();} 765 } 766 767 function updateSelected () { 853 var selected_match = 0; 854 for (var i = 0; i < nodes_keys.length; i++) 855 { 856 if (data_all.nodes_index[nodes_keys[i]]) { 857 data_all.nodes_index[nodes_keys[i]].selected = 1; 858 selected_match++; 859 } 860 } 861 // if something was selected, update and render Graph and Detail 862 if (selected_match) { 863 updateSelected(); 864 } 865 } 866 867 function updateSelected() { 768 868 769 869 // don't change the selected nodes on freeze-layout 770 if (opt("layout")!='freeze') { 771 nodes_sel = data_all.nodes.filter(function (d) { return d.selected }); 772 console.log("updateSelected:" + nodes_sel); 773 // update param 774 var selected = []; 775 nodes_sel.forEach(function(d) { selected.push(d.key) }); 776 $("#navigate").data("qi").setParamValue("selected",selected.join()); 777 renderDetail(nodes_sel); 778 779 } 780 870 if (opt("layout") != 'freeze') { 871 nodes_sel = data_all.nodes.filter(function (d) { 872 return d.selected 873 }); 874 console.log("updateSelected:"); 875 console.log(nodes_sel); 876 // update param 877 var selected = []; 878 nodes_sel.forEach(function (d) { 879 selected.push(d.key) 880 }); 881 $("#navigate").data("qi").setParamValue("selected", selected.join()); 882 renderDetail(nodes_sel); 883 884 } 885 781 886 renderGraph(); 782 783 // just need to highlight the selected nodes 784 d3.select(index_container_selector).selectAll("li").classed("highlight", function (d) { return d.selected }); 785 // renderIndex(); - this would be unnecessary and too expensive 887 888 // just need to highlight the selected nodes 889 d3.select(index_container_selector).selectAll("li").classed("highlight", function (d) { 890 return d.selected 891 }); 892 // renderIndex(); - this would be unnecessary and too expensive 786 893 } 787 894 788 895 789 896 /** Returns an event handler for highlighting the path of selected (mouseover) node. 790 */897 */ 791 898 function highlight() { 792 max_depth = parseInt(opt("depth-before")) + parseInt(opt("depth-after"));793 console.log("max_depth:" + max_depth);794 return function(d, i) {795 // console.log ("fade:" + d.key);796 //var connected_subgraph_in = neighboursWithLinks(data_show, d,'in', -1);797 //var connected_subgraph_out = neighboursWithLinks(data_show, d,'out', -1);798 799 var connected_subgraph_in = neighboursWithLinks(data_show, d,'in', max_depth);800 var connected_subgraph_out = neighboursWithLinks(data_show, d,'out', max_depth);801 var connected_subgraph = {"nodes": [], "links": []};899 max_depth = parseInt(opt("depth-before")) + parseInt(opt("depth-after")); 900 console.log("max_depth:" + max_depth); 901 return function (d, i) { 902 // console.log ("fade:" + d.key); 903 //var connected_subgraph_in = neighboursWithLinks(data_show, d,'in', -1); 904 //var connected_subgraph_out = neighboursWithLinks(data_show, d,'out', -1); 905 906 var connected_subgraph_in = neighboursWithLinks(data_show, d, 'in', max_depth); 907 var connected_subgraph_out = neighboursWithLinks(data_show, d, 'out', max_depth); 908 var connected_subgraph = {"nodes": [], "links": []}; 802 909 connected_subgraph.nodes = connected_subgraph.nodes.concat(connected_subgraph_in.nodes).concat(connected_subgraph_out.nodes); 803 910 connected_subgraph.links = connected_subgraph.links.concat(connected_subgraph_in.links).concat(connected_subgraph_out.links); 804 add_lookups(connected_subgraph); 805 svg.selectAll("path.link") 806 /* .filter( d.source.index != i && d.target.index != i; })*/ 807 /* .transition()*/ 808 .classed("highlight", function(p) { return connected_subgraph.links_index[p.source.key + ',' + p.target.key] }) 809 .classed("fade", function(p) { return !(connected_subgraph.links_index[p.source.key + ',' + p.target.key]) }); 810 811 connected = svg.selectAll("g.node").filter(function(d) { 812 return connected_subgraph.nodes_in[d.key] || connected_subgraph.nodes_out[d.key] 813 }) 911 add_lookups(connected_subgraph); 912 svg.selectAll("path.link") 913 /* .filter( d.source.index != i && d.target.index != i; })*/ 914 /* .transition()*/ 915 .classed("highlight", function (p) { 916 return connected_subgraph.links_index[p.source.key + ',' + p.target.key] 917 }) 918 .classed("fade", function (p) { 919 return !(connected_subgraph.links_index[p.source.key + ',' + p.target.key]) 920 }); 921 922 connected = svg.selectAll("g.node").filter(function (d) { 923 return connected_subgraph.nodes_in[d.key] || connected_subgraph.nodes_out[d.key] 924 }) 814 925 .classed("highlight", 1) 815 926 .classed("fade", 0); 816 817 connected.selectAll("text").classed("hide",0); 818 not_connected = svg.selectAll("g.node").filter(function(d) { 819 return !(connected_subgraph.nodes_in[d.key] || connected_subgraph.nodes_out[d.key]) 820 }) 821 .classed("highlight",0) 822 .classed("fade",1); 823 not_connected.selectAll("text").classed("hide",1); 824 825 /*svg.selectAll("circle") 826 /\* .filter( d.source.index != i && d.target.index != i; })*\/ 827 /\* .transition()*\/ 828 .classed("highlight", function(d) { return connected_subgraph.nodes_in[d.key] || connected_subgraph.nodes_out[d.key] }) 829 .classed("fade", function(d) { return !(connected_subgraph.nodes_in[d.key] || connected_subgraph.nodes_out[d.key]) });*/ 830 /* 831 if (opt("labels") =='show') { 832 gnodes.append("svg:text") 833 .attr("x", 8) 834 .attr("y", ".31em") 835 .attr("class", "shadow") 836 .text(function(d) { return d.name; }); 837 gnodes.append("svg:text") 838 .attr("x", 8) 839 .attr("y", ".31em") 840 .text(function(d) { return d.name; }); 927 928 connected.selectAll("text").classed("hide", 0); 929 not_connected = svg.selectAll("g.node").filter(function (d) { 930 return !(connected_subgraph.nodes_in[d.key] || connected_subgraph.nodes_out[d.key]) 931 }) 932 .classed("highlight", 0) 933 .classed("fade", 1); 934 not_connected.selectAll("text").classed("hide", 1); 935 936 /*svg.selectAll("circle") 937 /\* .filter( d.source.index != i && d.target.index != i; })*\/ 938 /\* .transition()*\/ 939 .classed("highlight", function(d) { return connected_subgraph.nodes_in[d.key] || connected_subgraph.nodes_out[d.key] }) 940 .classed("fade", function(d) { return !(connected_subgraph.nodes_in[d.key] || connected_subgraph.nodes_out[d.key]) });*/ 941 /* 942 if (opt("labels") =='show') { 943 gnodes.append("svg:text") 944 .attr("x", 8) 945 .attr("y", ".31em") 946 .attr("class", "shadow") 947 .text(function(d) { return d.name; }); 948 gnodes.append("svg:text") 949 .attr("x", 8) 950 .attr("y", ".31em") 951 .text(function(d) { return d.name; }); 952 } 953 */ 954 }; 955 } 956 957 function unhighlight() { 958 return function (d, i) { 959 960 svg.selectAll("path.link") 961 .classed("highlight", 0) 962 .classed("fade", 0); 963 964 var gnodes = svg.selectAll("g.node") 965 .classed("highlight", 0) 966 .classed("fade", 0); 967 968 gnodes.selectAll("text").classed("hide", function (d) { 969 return !d.selected && opt("labels") == 'hide' 970 }); 971 972 }; 973 } 974 975 976 /** generates the subset of data to display (based on selected nodes + options) 977 fills global variable: data_show ! 978 */ 979 function dataToShow(nodes) { 980 data_show = {}; 981 data_show.nodes = nodes; 982 var data_show_collect = {nodes: [], links: []}; 983 984 nodes.forEach(function (n) { 985 var data_add_in = neighboursWithLinks(data_all, n, 'in', opt("depth-before")); 986 var data_add_out = neighboursWithLinks(data_all, n, 'out', opt("depth-after")); 987 data_show_collect.nodes = data_show_collect.nodes.concat(data_add_in.nodes).concat(data_add_out.nodes); 988 data_show_collect.links = data_show_collect.links.concat(data_add_in.links).concat(data_add_out.links); 989 }); 990 991 /* deduplicate nodes and edges */ 992 data_show.nodes = unique_nodes(nodes.concat(data_show_collect.nodes)); 993 data_show.links = unique_links(data_show_collect.links); 994 995 // extend the object, with some lookup hashes on neighbourhood 996 add_lookups(data_show); 997 998 return data_show; 999 } 1000 1001 /** generate lookup hashes for neighbours; 1002 for faster/simpler neighborhood lookup 1003 from: http://stackoverflow.com/questions/8739072/highlight-selected-node-its-links-and-its-children-in-a-d3-js-force-directed-g 1004 */ 1005 function add_lookups(data) { 1006 1007 var links = data.links; 1008 var neighbours = {"links_index": {}, "nodes_index": {}, 1009 "nodes_in": {}, "nodes_out": {}, 1010 "links_in": {}, "links_out": {}, 1011 "roots": []}; 1012 1013 data.nodes.forEach(function (d) { 1014 neighbours.nodes_index[d.key] = d; 1015 }); 1016 1017 var targets = []; 1018 1019 links.forEach(function (d) { 1020 src_key = d.source.key; 1021 trg_key = d.target.key; 1022 1023 // generate lookup hashes for neighbours; 1024 neighbours.links_index[src_key + "," + trg_key] = d; 1025 if (d.source) { 1026 if (!neighbours.nodes_in[trg_key]) { 1027 neighbours.nodes_in[trg_key] = [d.source]; 1028 neighbours.links_in[trg_key] = [d]; 1029 } else { 1030 neighbours.nodes_in[trg_key].push(d.source); 1031 neighbours.links_in[trg_key].push(d); 1032 } 841 1033 } 842 */ 843 }; 844 } 845 846 function unhighlight() { 847 return function(d, i) { 848 849 svg.selectAll("path.link") 850 .classed("highlight", 0 ) 851 .classed("fade", 0 ); 852 853 var gnodes = svg.selectAll("g.node") 854 .classed("highlight", 0) 855 .classed("fade", 0); 856 857 gnodes.selectAll("text").classed("hide",function(d) { return !d.selected && opt("labels")=='hide'}); 858 859 }; 860 } 861 862 863 /** generates the subset of data to display (based on selected nodes + options) 864 fills global variable: data_show ! 865 */ 866 function dataToShow (nodes) { 867 data_show = {}; 868 data_show.nodes = nodes; 869 var data_show_collect = {nodes:[],links:[]}; 870 871 nodes.forEach(function(n) { 872 var data_add_in = neighboursWithLinks(data_all, n,'in', opt("depth-before")); 873 var data_add_out = neighboursWithLinks(data_all, n,'out', opt("depth-after")); 874 data_show_collect.nodes = data_show_collect.nodes.concat(data_add_in.nodes).concat(data_add_out.nodes); 875 data_show_collect.links = data_show_collect.links.concat(data_add_in.links).concat(data_add_out.links); 876 }); 877 878 /* deduplicate nodes and edges */ 879 data_show.nodes = unique_nodes(nodes.concat(data_show_collect.nodes)); 880 data_show.links = unique_links(data_show_collect.links); 881 882 // extend the object, with some lookup hashes on neighbourhood 883 add_lookups(data_show); 884 885 return data_show; 886 } 887 888 /** generate lookup hashes for neighbours; 889 for faster/simpler neighborhood lookup 890 from: http://stackoverflow.com/questions/8739072/highlight-selected-node-its-links-and-its-children-in-a-d3-js-force-directed-g 891 */ 892 function add_lookups(data) { 893 894 var links = data.links; 895 var neighbours = {"links_index": {}, "nodes_index": {}, 896 "nodes_in": {}, "nodes_out": {}, 897 "links_in": {}, "links_out": {}, 898 "roots": []}; 899 900 data.nodes.forEach(function(d){ 901 neighbours.nodes_index[d.key] = d; 902 }); 903 904 var targets=[]; 905 906 links.forEach(function(d) { 907 src_key = d.source.key; 908 trg_key = d.target.key; 909 910 // generate lookup hashes for neighbours; 911 neighbours.links_index[src_key + "," + trg_key] = d; 912 if (d.source) { 913 if (! neighbours.nodes_in[trg_key]) { 914 neighbours.nodes_in[trg_key] = [d.source]; 915 neighbours.links_in[trg_key] = [d]; 916 } else { 917 neighbours.nodes_in[trg_key].push(d.source); 918 neighbours.links_in[trg_key].push(d); 919 } 920 } 921 if (d.target) { 922 if (targets.indexOf(d.target.key) == -1 ) { targets.push(d.target.key); } 923 924 if (! neighbours.nodes_out[src_key]) { 925 neighbours.nodes_out[src_key] = [d.target]; 926 neighbours.links_out[src_key] = [d]; 927 } else { 928 neighbours.nodes_out[src_key].push(d.target); 929 neighbours.links_out[src_key].push(d) ; 930 } 931 } 932 }); 933 934 data.nodes.forEach(function(d){ 935 if (targets.indexOf(d.key) == -1) 936 { neighbours.roots.push(d.key); } 937 }); 938 939 1034 if (d.target) { 1035 if (targets.indexOf(d.target.key) == -1) { 1036 targets.push(d.target.key); 1037 } 1038 1039 if (!neighbours.nodes_out[src_key]) { 1040 neighbours.nodes_out[src_key] = [d.target]; 1041 neighbours.links_out[src_key] = [d]; 1042 } else { 1043 neighbours.nodes_out[src_key].push(d.target); 1044 neighbours.links_out[src_key].push(d); 1045 } 1046 } 1047 }); 1048 1049 data.nodes.forEach(function (d) { 1050 if (targets.indexOf(d.key) == -1) 1051 { 1052 neighbours.roots.push(d.key); 1053 } 1054 }); 1055 1056 940 1057 //if it is target, it is no root 941 942 943 1058 1059 1060 944 1061 data = $.extend(data, neighbours); 945 return data; 1062 return data; 946 1063 } 947 1064 … … 949 1066 950 1067 /* item_detail.text(function (d) { return "links_in: " + dataShowCount(d.key, "links_in") + "; links_out: " + dataShowCount(d.key, "links_out") ; 951 952 function dataShowCount(n_key, info_type) { 1068 })*/ 1069 function dataShowCount(n_key, info_type) { 953 1070 954 1071 if (data_show[info_type][n_key]) { 955 1072 return data_show[info_type][n_key].length; 956 1073 } else { 957 1074 return 0 958 1075 } 959 1076 } 960 1077 … … 964 1081 @returns array of [x_min, y_min, x_max, y_max, (x_max - x_min), (y_max - y_min)] 965 1082 */ 966 function graphBounds () { 967 968 var x_arr = [], y_arr =[]; 969 970 data_show.nodes.forEach(function(d,i){x_arr.push(d.x); y_arr.push(d.y)}) 1083 function graphBounds() { 1084 1085 var x_arr = [], y_arr = []; 1086 1087 data_show.nodes.forEach(function (d, i) { 1088 x_arr.push(d.x); 1089 y_arr.push(d.y) 1090 }) 971 1091 972 1092 x_min = d3.min(x_arr); … … 974 1094 y_min = d3.min(y_arr); 975 1095 y_max = d3.max(y_arr); 976 977 return {"x-min": x_min, "y-min": y_min, "x-max": x_max, "x-max": y_max, "width": (x_max - x_min), "height":(y_max - y_min)}978 } 979 1096 1097 return {"x-min": x_min, "y-min": y_min, "x-max": x_max, "x-max": y_max, "width": (x_max - x_min), "height": (y_max - y_min)} 1098 } 1099 980 1100 /** returns appropriate link 981 */1101 */ 982 1102 function neighbouring(a, b) { 983 1103 //console.log("neighbouring: " +a.key + "," + b.key ); 984 return data_all.links_index[a.key + "," + b.key];1104 return data_all.links_index[a.key + "," + b.key]; 985 1105 } 986 1106 987 1107 988 1108 /** access function to retrieve the neighbours from the hashes 989 @param data base data to search for links (default: data_all)990 @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)991 @param depth 0-n - go depth-levels; negative depth := no depth restriction = go to the end of the paths;992 @returns a sub-graph993 */994 function neighboursWithLinks 1109 @param data base data to search for links (default: data_all) 1110 @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) 1111 @param depth 0-n - go depth-levels; negative depth := no depth restriction = go to the end of the paths; 1112 @returns a sub-graph 1113 */ 1114 function neighboursWithLinks(data, n, dir, depth) { 995 1115 // setting defaults 996 997 1116 depth = typeof depth !== 'undefined' ? depth : 1; 1117 data = typeof data !== 'undefined' ? data : data_all; 998 1118 weight_threshold = parseInt(opt("weight")) / 100; 999 1119 //console.log("weight_threshold:" + weight_threshold + "; depth:" + depth + "; key: " + n.key); 1000 if (depth==0) { return {nodes:[], links:[]};} 1001 1002 /* don't filter at all */ 1003 if (weight_threshold == 1 | opt("weight")=="") { 1004 var n_in = data.nodes_in[n.key] ? data.nodes_in[n.key] : [] ; 1005 var n_out = data.nodes_out[n.key] ? data.nodes_out[n.key] : [] ; 1006 var l_in = data.links_in[n.key] ? data.links_in[n.key] : [] ; 1007 var l_out = data.links_out[n.key] ? data.links_out[n.key] : [] ; 1008 } else { 1009 var l_in = data.links_in[n.key] ? data.links_in[n.key].filter(function(d, i) { return d.weight>=weight_threshold }) : [] ; 1010 var l_out = data.links_out[n.key] ? data.links_out[n.key].filter(function(d, i) { return d.weight>=weight_threshold }) : [] ; 1011 var n_in = data.nodes_in[n.key] ? data.nodes_in[n.key].filter(function(d, i) { return neighbouring(d,n).weight>=weight_threshold }) : [] ; 1012 var n_out = data.nodes_out[n.key] ? data.nodes_out[n.key].filter(function(d, i) { return neighbouring(n,d).weight>=weight_threshold }) : [] ; 1013 } 1014 1015 var result_n = {nodes:[], links:[]}; 1016 if (dir == 'in' ) { result_n.nodes = n_in; result_n.links = l_in; } 1017 else if (dir == 'out' ) { result_n.nodes = n_out; result_n.links = l_out; } 1018 else { result_n.nodes = n_out.concat(n_in); result_n.links = l_out.concat(l_in); } 1019 var n_nextlevel = {nodes:[], links:[]}; 1020 if (depth > 0 || depth < 0) { 1021 result_n.nodes.forEach (function(n) 1022 { var n_neighbours = neighboursWithLinks(data, n, dir, depth - 1); 1023 n_nextlevel.nodes = n_nextlevel.nodes.concat(n_neighbours.nodes); 1024 n_nextlevel.links = n_nextlevel.links.concat(n_neighbours.links); 1025 }) 1026 } 1027 result_n.nodes = result_n.nodes.concat(n_nextlevel.nodes); 1028 result_n.links = result_n.links.concat(n_nextlevel.links); 1029 1030 return result_n; 1031 1120 if (depth == 0) { 1121 return {nodes: [], links: []}; 1122 } 1123 1124 /* don't filter at all */ 1125 if (weight_threshold == 1 | opt("weight") == "") { 1126 var n_in = data.nodes_in[n.key] ? data.nodes_in[n.key] : []; 1127 var n_out = data.nodes_out[n.key] ? data.nodes_out[n.key] : []; 1128 var l_in = data.links_in[n.key] ? data.links_in[n.key] : []; 1129 var l_out = data.links_out[n.key] ? data.links_out[n.key] : []; 1130 } else { 1131 var l_in = data.links_in[n.key] ? data.links_in[n.key].filter(function (d, i) { 1132 return d.weight >= weight_threshold 1133 }) : []; 1134 var l_out = data.links_out[n.key] ? data.links_out[n.key].filter(function (d, i) { 1135 return d.weight >= weight_threshold 1136 }) : []; 1137 var n_in = data.nodes_in[n.key] ? data.nodes_in[n.key].filter(function (d, i) { 1138 return neighbouring(d, n).weight >= weight_threshold 1139 }) : []; 1140 var n_out = data.nodes_out[n.key] ? data.nodes_out[n.key].filter(function (d, i) { 1141 return neighbouring(n, d).weight >= weight_threshold 1142 }) : []; 1143 } 1144 1145 var result_n = {nodes: [], links: []}; 1146 if (dir == 'in') { 1147 result_n.nodes = n_in; 1148 result_n.links = l_in; 1149 } else if (dir == 'out') { 1150 result_n.nodes = n_out; 1151 result_n.links = l_out; 1152 } else { 1153 result_n.nodes = n_out.concat(n_in); 1154 result_n.links = l_out.concat(l_in); 1155 } 1156 var n_nextlevel = {nodes: [], links: []}; 1157 if (depth > 0 || depth < 0) { 1158 result_n.nodes.forEach(function (n) 1159 { 1160 var n_neighbours = neighboursWithLinks(data, n, dir, depth - 1); 1161 n_nextlevel.nodes = n_nextlevel.nodes.concat(n_neighbours.nodes); 1162 n_nextlevel.links = n_nextlevel.links.concat(n_neighbours.links); 1163 }) 1164 } 1165 result_n.nodes = result_n.nodes.concat(n_nextlevel.nodes); 1166 result_n.links = result_n.links.concat(n_nextlevel.links); 1167 1168 return result_n; 1169 1032 1170 } 1033 1171 1034 1172 /** deduplicates based on index-property */ 1035 function unique_nodes(nodes) 1173 function unique_nodes(nodes) 1036 1174 { 1037 1175 var hash = {}, result = []; 1038 for ( var i = 0, l = nodes.length; i < l; ++i) {1039 1040 if ( !hash[n_key]) { //it works with objects! in FF, at least1176 for (var i = 0, l = nodes.length; i < l; ++i) { 1177 n_key = nodes[i].key; 1178 if (!hash[n_key]) { //it works with objects! in FF, at least 1041 1179 hash[ n_key ] = true; 1042 1180 result.push(nodes[i]); … … 1047 1185 1048 1186 /** deduplicates links (based on source-target-index 1049 based on: http://stackoverflow.com/questions/1890203/unique-for-arrays-in-javascript1050 */1051 function unique_links(links) 1187 based on: http://stackoverflow.com/questions/1890203/unique-for-arrays-in-javascript 1188 */ 1189 function unique_links(links) 1052 1190 { 1053 1191 var hash = {}, result = []; 1054 for ( var i = 0, l = links.length; i < l; ++i) {1055 1056 1057 1058 if ( !hash[key]) {1192 for (var i = 0, l = links.length; i < l; ++i) { 1193 src_key = links[i].source.key; 1194 trg_key = links[i].target.key; 1195 key = src_key + "," + trg_key; 1196 if (!hash[key]) { 1059 1197 hash[ key] = true; 1060 1198 result.push(links[i]); … … 1064 1202 } 1065 1203 1066 function notifyUser 1067 $("#notifylist").append(msg);1068 } 1204 function notifyUser(msg) { 1205 $("#notifylist").append(msg); 1206 }
Note: See TracChangeset
for help on using the changeset viewer.