Changeset 6846 for SMC


Ignore:
Timestamp:
11/25/15 13:01:31 (8 years ago)
Author:
mateusz.zoltak@oeaw.ac.at
Message:

Bunch of fixes making it easy to deploy a working instance:

  • JS libraries names in the repo now agree with URLs in src/web/index.html
  • sample data added - now data list and locations agree with the list set up in src/web/scripts/config.js
  • src/web/get.php generates allow-origin headers so you can query it with AJAX
  • static pages (examples, userdoc) added (copied from the clarin instance)
  • few fixes in smc.graph.js (most notably it can again read old graph jsons in which nodes in links are denoted by index and not by id)

(Probably) the last SVN commit, we are switching to git

Location:
SMC/trunk/SMC/src/web
Files:
55 added
6 edited

Legend:

Unmodified
Added
Removed
  • SMC/trunk/SMC/src/web/get.php

    r5304 r6846  
    11<?php
     2header('Access-Control-Allow-Origin: *');
     3header('Access-Control-Allow-Headers: X-Requested-With, Content-Type');
    24 
    35function 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;
    713}
    814
    9         $link = $_GET['link'];
    10         $content = file_get_contents_utf8($link);
     15$content = file_get_contents_utf8(@$_GET['link']);
     16echo($content);
    1117
    12   //$referer = $_SERVER['SERVER_NAME'];
    13   //echo($referer );
    14   echo($content);
    15  
    16    
    17 ?>
  • SMC/trunk/SMC/src/web/index.html

    r6834 r6846  
    88        <link href="scripts/style/smc-graph.css" media="screen" rel="stylesheet" type="text/css" />
    99
    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>
    1414        <script src="scripts/js/mdservice/mdservice_ui_helpers.js" type="text/javascript"></script>
    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>
     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>
    1717
    1818        <script src="scripts/js/config.js" type="text/javascript"></script>
     
    2626        <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>
    2727            <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>
    2935            <div id="notify" class="cmds-elem-plus note">
    3036                <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        
     1var 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
    1918};
    2019
    2120// 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             };
     21var 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  
    14301430
    14311431                                if ($C.is(":visible") && $C.innerHeight() < 2){
    1432                                         alert( lang.errContainerHeight.replace(/CONTAINER/, sC.ref) );
     1432                                        console.log( lang.errContainerHeight.replace(/CONTAINER/, sC.ref) );
    14331433                                }
    14341434
     
    17561756
    17571757                if ($Container.innerHeight() < 2){
    1758                         alert( lang.errContainerHeight.replace(/CONTAINER/, sC.ref) );
     1758                        console.log( lang.errContainerHeight.replace(/CONTAINER/, sC.ref) );
    17591759                }
    17601760               
  • SMC/trunk/SMC/src/web/scripts/js/main.js

    r6834 r6846  
    1010var navi_container_selector = '#navigate';
    1111var detail_container_selector = "#detail-container";
    12 var detail_info_holder_selector =  '#detail-info-holder';
     12var detail_info_holder_selector = '#detail-info-holder';
    1313var graph_container = null;
    14 var index_container = null; 
     14var index_container = null;
    1515
    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        
     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
    4141});
    4242
     
    4545 * @function
    4646 */
    47 function addFunctionality(){
    48        
     47function addFunctionality() {
     48
    4949//      $("#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
    5454    /*fillOpts(navi_container_selector);
    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                 );*/
     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     );*/
    6969
    7070    /*$('#input-link').live("mousedown", function(event) {
    71     console.log(this);
    72                 $(this).attr("target", "_blank");
    73                     $(this).attr("href", generateLink());
    74                    });
    75     */
    76    
     71     console.log(this);
     72     $(this).attr("target", "_blank");
     73     $(this).attr("href", generateLink());
     74     });
     75     */
     76
    7777    //$('#input-download').live("mousedown", genDownload);
    78     $( document ).on( "mousedown", '#input-download', genDownload);
    79    
     78    $(document).on("mousedown", '#input-download', genDownload);
     79
    8080// $(".detail-caller").live("click", function(event) {
    81  $( document ).on( "click", '.detail-caller', function(event) {
    82                 //console.log(this);
    83                 event.preventDefault();
    84                 $(this).parent().find('.detail').toggle();
    85               });
     81    $(document).on("click", '.detail-caller', function (event) {
     82        //console.log(this);
     83        event.preventDefault();
     84        $(this).parent().find('.detail').toggle();
     85    });
    8686
    8787// $(".node-item .detail a").live("click",
    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               });
     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    });
    9494
    9595//$("a.scan").live("click", function(event) {
    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               });
     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    });
    103103}
  • SMC/trunk/SMC/src/web/scripts/js/smc-graph.js

    r6834 r6846  
    33var item_li = null;
    44
    5 var svg  = null; // main svg-element
    6 var css; 
     5var svg = null; // main svg-element
     6var css;
    77var data_all = null; // global holder for all (input) data
    88var nodes_sel = []; // global holder for selected data (selected nodes)
    99var data_show = null; // global holder for data to show  closure over nodes_sel
    10 var nest = {}; 
     10var nest = {};
    1111var 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  
     12var mode = "static";   // dynamic or static (default)  static=load detail data all at once on init;
     13
    1414
    1515var input_prefix = "input-";
    1616var 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 ;
     17var first_level_margin = config.first_level_margin;
     18var base_font_size = config.base_font_size;
    1919var min_circle = config.min_circle;
    2020var max_circle = config.max_circle;
    2121
    2222var show_count = config.show_count;
    23  
     23
    2424
    2525//var detail_url = "http://localhost:8580/exist/apps/smc-browser/get.xql"; obsoleted by config
     
    3131/*var source_file = "../scripts/cmd-dep-graph-d3_all_svg.json"*/
    3232/*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 */
    3535/*
    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 */
    4141//now graph-param is used
    4242//var source_file = "/smc/smc-graph.d3";
     
    4949
    5050/** temporary helper function
    51 to easily get the param-data
    52 */
     51 to easily get the param-data
     52 */
    5353function 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
     58function currentOpts() {
     59    return $("#navigate").data("qi");
    6060}
    6161
     
    6464 * @function
    6565 */
    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                     });
     66function 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                    }
    7990                   
    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
    98107                // 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);
    121138                curr_params = $("#navigate").data("qi").params;
    122139                /* if weight is not used (all weight==1 deactivate the weight widget */
    123                 if (data_all.weight_min==1) {
    124                            
    125                            delete curr_params.weight;
    126 /*                           $("#navigate").init(curr_opts );*/
    127                         $("#navigate").QueryInput({params: curr_params,
    128                              onValueChanged: renderGraph
    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                    });
    130147                } else {
    131                       curr_params.weight = {"value":70, "min":1, "max":100, "widget":"slider" };
    132                       $("#navigate").QueryInput({params: curr_params,
    133                              onValueChanged: renderGraph
    134                       });
     148                    curr_params.weight = {"value": 70, "min": 1, "max": 100, "widget": "slider"};
     149                    $("#navigate").QueryInput({params: curr_params,
     150                        onValueChanged: renderGraph
     151                    });
    135152                }
    136                
    137                
     153
     154
    138155                notifyUser("count max: " + data_all.count_max + "; "
    139156                        + "node_size_ratio: " + data_all.node_size_ratio);
    140                  
    141                  // should be delivered by the data directly
    142                    data_all.nodes.forEach(function(d,i) {
    143                        d.x = d.init_x;
    144                        d.y = d.init_y;
    145                      });
    146 
    147                   // get selected nodes (if any) from param
    148                   selected_ids = opt("selected").split(",");
    149                   selectNodeByKey(selected_ids);
    150                   /*var selected_match = 0;
    151                     for (var i = 0; i < selected_ids.length; i++)
    152                     {  if (data_all.nodes_index[selected_ids[i]]) {
    153                              data_all.nodes_index[selected_ids[i]].selected = 1;
    154                              selected_match ++;
    155                        }
    156                     }   
    157                   // if something was selected, update and render Graph and Detail
    158                   if (selected_match) { updateSelected();}
    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            });
    164181}
    165182
    166183/** put grouped list of nodes into the target container*/
    167 function renderIndex (data, target_container_selector) {
     184function renderIndex(data, target_container_selector) {
    168185    data = typeof data !== 'undefined' ? data : data_all.nodes;
    169186    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);
    171188}
    172189
    173190
    174191/** generate the detail lists
    175     @param nodes
    176 */ 
    177 function renderDetail (nodes) {   
    178     renderNodeList (nodes, detail_container_selector);
     192 @param nodes
     193 */
     194function renderDetail(nodes) {
     195    renderNodeList(nodes, detail_container_selector);
    179196}
    180197
     
    182199
    183200/** generate a grouped (by type) list of nodes
    184     @param nodes - accepts an array of nodes (like in data.nodes)
    185 */ 
    186 function renderNodeList (nodes, target_container_selector) {
     201 @param nodes - accepts an array of nodes (like in data.nodes)
     202 */
     203function renderNodeList(nodes, target_container_selector) {
    187204
    188205    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
    193214    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
     317function renderItemText(d) {
    271318    if (show_count) {
    272         return d.name + ' |' + d.count + '|';
    273       }
    274     else {
     319        return d.name + ' |' + d.count + '|';
     320    } else {
    275321        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
     325function 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;
    283329    });
    284    
    285    renderIndex(filtered_index_nodes, index_container_selector);
     330
     331    renderIndex(filtered_index_nodes, index_container_selector);
    286332}
    287333
    288334
    289335/** render data (data_show) as graph  into target-container (graph_container) */
    290 function renderGraph (data, target_container) {
     336function renderGraph(data, target_container) {
    291337// setting defaults
    292338// for now, ignore the params, as they are always the same
    293    
     339
    294340    //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
    301350    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      } else {
    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") {
    314363        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);
    333384    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         // console.log (w + '-' + h);
    338      var force = d3.layout.force()
     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()
    339390            .nodes(data.nodes)
    340391            .links(data.links)
    341392            .size([w, h])
    342393
    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
    347398            .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)
    369425            .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
    378438//    console.log ("gravity: " + force.gravity() );             
    379  
    380        // remove old render:
    381           d3.select(graph_container_selector).selectAll("svg").remove();
    382                  
    383         svg = d3.select(graph_container_selector).append("svg:svg")
    384             .attr("width", w)        .attr("height", h);
    385        
    386         // Per-type markers, as they don't inherit styles.
    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) {
    389449        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         var path = svg.append("svg:g").selectAll("path")
     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")
    405465            .data(force.links())
    406466            .enter().append("svg:path")
    407 /*            .attr("class", function(d) { return "link uses"; })*/
     467            /*            .attr("class", function(d) { return "link uses"; })*/
    408468            .classed("link", 1)
    409469            .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') {
    525612            var offset = data_all.init_x_min;
    526613            /*data.links.forEach(function(d, i) {
    527               d.source.x = (d.source.init_x / 150 * link_distance_int) ;
    528               d.target.x = (d.target.init_x / 150 * link_distance_int);
    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;
    534621            });
    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;
    539626                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
    573668            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);
    577673                return "M" + d.source.x + "," + d.source.y + "A" + dr + "," + dr + " 0 0,1 " + d.target.x + "," + d.target.y;
    578             } else { 
    579             // or straight
     674            } else {
     675                // or straight
    580676                return "M" + d.source.x + "," + d.source.y + "L" + d.target.x + "," + d.target.y;
    581             } 
    582        });
    583          
    584          /*circle.attr("cx", function(d) {return d.x;})
    585                 .attr("cy", function(d) {return d.y;});*/
    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) {
    587683            return "translate(" + d.x + "," + d.y + ")";
    588        });
    589        
    590   /*     textgroup.attr("transform", function(d) {
    591             return "translate(" + d.x + "," + d.y + ")";
    592        });*/
    593     }
    594        
    595         // Highlight selected nodes using the quadtree.
    596         svg.on("mousedown", function() {
    597           var m0 = d3.mouse(this);
    598        
    599           var rect = d3.select(this).append("rect")
    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 () {
    604700            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                 // console.log("DEBUG: mousedown: " + (x1-x0) + ( y1-y0));       
    610                     selectNodes(data.nodes, x0, y0, x1, y1);                   
    611                     rect.attr("x", x0).attr("y", y0).attr("width", x1 - x0).attr("height", y1 - y0);
    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 () {
    616712            // only change selection, if the rectangle was big enough
    617713            // (mainly to prevent clearing of the graph on clicks that look like mousemoves to the system)
     
    621717            rect.remove();
    622718            d3.select(window).on("mousemove", null).on("mouseup", null);
    623           });
    624        
    625           d3.event.preventDefault();
    626         });
     719        });
     720
     721        d3.event.preventDefault();
     722    });
    627723}  // end renderGraph
    628724
    629725
    630726/** 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 */
     729function 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
     765function getDetailInfo(type, id, target, load_callback) {
    667766    //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    }
    683780    // notify(d);
    684    
     781
    685782}
    686783
    687784/** 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, PDF
    691 http://d3export.cancan.cshl.edu/
    692 called on mousedown of the download-link, so assumes the <a>-element as this
    693 */
    694 function genDownload (event) {
     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 */
     791function genDownload(event) {
    695792//console.log("genDownload:" + this);
    696793
     
    700797    var margin = 30;
    701798    var link_dist = parseInt(opt("link-distance"));
    702    
     799
    703800    var x, y, w, h;
    704     x = Math.floor(bounds["x-min"]) - margin 
     801    x = Math.floor(bounds["x-min"]) - margin
    705802    y = Math.floor(bounds["y-min"]) - margin
    706803    // 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;
    708805    h = (bounds["height"] > svg_h) ? bounds["height"] + 2 * margin : svg_h;
    709        
     806
    710807    var viewBox = x + " " + y + " " + w + " " + h;
    711808
    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         style.attr("type", 'text/css');
    720         style.text(css);
    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
    727824    //console.log(html);
    728825
    729826    $(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
    734831}
    735832
     
    737834/**  select the nodes within the specified rectangle. */
    738835function 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)) {
    743840            points.push(n);
    744841            n.selected = 1;
     
    746843            n.selected = 0;
    747844        }
    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;
    751848}
    752849
     
    754851
    755852    // 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
     867function updateSelected() {
    768868
    769869    // 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
    781886    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   
    786893}
    787894
    788895
    789896/** Returns an event handler for highlighting the path of selected (mouseover) node.
    790 */
     897 */
    791898function 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": []};
    802909        connected_subgraph.nodes = connected_subgraph.nodes.concat(connected_subgraph_in.nodes).concat(connected_subgraph_out.nodes);
    803910        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        })
    814925                .classed("highlight", 1)
    815926                .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
     957function 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 */
     979function 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 */
     1005function 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            }
    8411033        }
    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
    9401057    //if it is target, it is no root
    941                            
    942                            
    943                        
     1058
     1059
     1060
    9441061    data = $.extend(data, neighbours);
    945     return data; 
     1062    return data;
    9461063}
    9471064
     
    9491066
    9501067/*                        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 })*/
     1069function dataShowCount(n_key, info_type) {
    9531070
    9541071    if (data_show[info_type][n_key]) {
    9551072        return data_show[info_type][n_key].length;
    956        } else {
     1073    } else {
    9571074        return 0
    958        }
     1075    }
    9591076}
    9601077
     
    9641081 @returns array of [x_min, y_min, x_max, y_max, (x_max - x_min), (y_max - y_min)]
    9651082 */
    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)})
     1083function 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    })
    9711091
    9721092    x_min = d3.min(x_arr);
     
    9741094    y_min = d3.min(y_arr);
    9751095    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
    9801100/** returns appropriate link
    981 */
     1101 */
    9821102function neighbouring(a, b) {
    9831103//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];
    9851105}
    9861106
    9871107
    9881108/** 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-graph
    993 */
    994 function neighboursWithLinks (data, n, dir, depth) {
     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 */
     1114function neighboursWithLinks(data, n, dir, depth) {
    9951115// setting defaults
    996        depth = typeof depth !== 'undefined' ? depth : 1;
    997        data = typeof data !== 'undefined' ? data : data_all;
     1116    depth = typeof depth !== 'undefined' ? depth : 1;
     1117    data = typeof data !== 'undefined' ? data : data_all;
    9981118    weight_threshold = parseInt(opt("weight")) / 100;
    9991119//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
    10321170}
    10331171
    10341172/** deduplicates based on index-property */
    1035 function unique_nodes(nodes) 
     1173function unique_nodes(nodes)
    10361174{
    10371175    var hash = {}, result = [];
    1038     for ( var i = 0, l = nodes.length; i < l; ++i ) {
    1039            n_key = nodes[i].key;
    1040         if ( !hash[n_key] ) { //it works with objects! in FF, at least
     1176    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
    10411179            hash[ n_key ] = true;
    10421180            result.push(nodes[i]);
     
    10471185
    10481186/** deduplicates links (based on source-target-index
    1049 based on: http://stackoverflow.com/questions/1890203/unique-for-arrays-in-javascript
    1050 */
    1051 function unique_links(links) 
     1187 based on: http://stackoverflow.com/questions/1890203/unique-for-arrays-in-javascript
     1188 */
     1189function unique_links(links)
    10521190{
    10531191    var hash = {}, result = [];
    1054     for ( var i = 0, l = links.length; i < l; ++i ) {
    1055             src_key = links[i].source.key;
    1056             trg_key = links[i].target.key;
    1057             key = src_key + "," + trg_key;
    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]) {
    10591197            hash[ key] = true;
    10601198            result.push(links[i]);
     
    10641202}
    10651203
    1066 function notifyUser (msg) {
    1067   $("#notifylist").append(msg);
    1068 }
     1204function notifyUser(msg) {
     1205    $("#notifylist").append(msg);
     1206}
Note: See TracChangeset for help on using the changeset viewer.