Skip to content

Commit

Permalink
add doc
Browse files Browse the repository at this point in the history
  • Loading branch information
data2GBR committed Jun 27, 2017
1 parent 6667609 commit bb97a6b
Show file tree
Hide file tree
Showing 3 changed files with 309 additions and 39 deletions.
52 changes: 40 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,18 +1,46 @@
# Viaz: graph visualization with D3.js
# Graphexp: graph explorer with D3.js

The HTML files contains Javascript code to visualize a graph together with meta-data associated to the nodes. The program uses:
* the D3.js library to visualize a graph in an interactive manner
* an ajax request (with Jquery) that query a graph database (Gremin Tinkerpop)
Graphexp is a javascript interface to explore and display a graph stored in the Gremlin graphdatabase via the Gremlin server. Graphexp is under the Apache 2.0 licence.

## Configuration

## D3.js Resources
To use graph Explorer, you need a [Gremlin server](http://tinkerpop.apache.org/) running with REST protocol and a *recent* web browser to display the visualization.
On your web browser, just access the file `graphexp.html`.

* [API Reference](https://github.com/d3/d3/blob/master/API.md)
* [Release Notes](https://github.com/d3/d3/releases)
* [Gallery](https://github.com/d3/d3/wiki/Gallery)
* [Examples](http://bl.ocks.org/mbostock)
* [Wiki](https://github.com/d3/d3/wiki)
If the access to the Gremlin server is not `localhost:8182`, the address can be configured in `graphConf.js`.

## Font Awesome Resources
## Getting started

If you do not have your own Gremlin server, you may use a docker container with a server ready to use.

To display a node, type in a property name and value, then click on the search button.
Leaving a blank field and keyword will display the full graph.
The node and edge properties can be automatically retrieved using the `get graph info` button. Pushing this button will also display some graph properties on the left side of the page.

When a node of the visualization is clicked, it will become 'active' with a circle surround it and its information will be display on the right side of the page. Moreover, this action will trigger the display of its neighbors.
Clicking on an edge will show its properties (without highlighting the edge).

When appearing for the first time the nodes will be positioned following a force layout. Drag and drop can be used to pin them in a particular position. Once dragged the nodes will stay at their position. Drag and drop is allowed only for the nodes on the active layer (most recent layer) with no connection with nodes in other layers. See "Visualization concepts" section for more information on the layers.

## Visualization concept

The visualization is based on a concept of layers of visualisation. The idea is to progress in the graph as in a jungle. The clicked node will show its neighbors, opening new paths for the exploration. If not clicked, the other displayed nodes will vanish little by little as we progress in the exploration. Coming back in the exploration paths allowed. Before it completely disappears, a node can be clicked and it will become active again. As in a jungle, you can not see the full jungle and there are so many things that you must focus on your direction and what is in front of you if you do not want to get lost.

During your exploration you can set up milestones by clicking on the small circle on the upper right side of a node. This will pin the node in time, preventing it to disappear.

You may also freeze the exploration, by ticking the appropriate checkbox. The evolution of the exploration will stop, allowing to gather information on the nodes displayed, without displaying their neighbors.

## Node and edge information

The Id and label of each node can be displayed by hovering the cursor over the node. The full information on the properties are displayed on the right of the page when clicking on the node or edges. Once the `get graph info` button has been clicked, a choice of properties to display appear on the left side.

## Node color

If a node property called 'color' exists in the node properties with an hexadecimal color code (string), it will be displayed automatically on the graph. Otherwise, the default node color can be set in the `graphConf.js` file. The node color can be set interactively after the `get graph info` button has been pressed. A select tab appears on the left side bar allowing to set the color according to one of the property values present in the graph.

## Program description

The program uses:
* the D3.js library to visualize a graph in an interactive manner, [API Reference](https://github.com/d3/d3/blob/master/API.md),
* an ajax request (with Jquery) that query the graph database (Gremlin Tinkerpop via REST).

* [List of symbols](http://fontawesome.io/cheatsheet/)
27 changes: 0 additions & 27 deletions graph_viz.js
Original file line number Diff line number Diff line change
Expand Up @@ -190,33 +190,6 @@ var graph_viz = (function(){
return array1.concat(arraytmp);
}

////////////////////////////////////////////////////////////////////////////
//update lines of array1 with the ones of array2 when the elements' id match
// and add elements of array2 to array1 when they do not exist in array1
function updateAdd2(array1,array2){
var arraytmp = array2.slice(0);
var removeValFromIndex = [];
array1.forEach(function(d,index,thearray){
for(var i=0;i<arraytmp.length;i++){
if (d.id == arraytmp[i].id){
//console.log(d.id);
thearray[index] = arraytmp[i];
removeValFromIndex.push(i);
//console.log('Found existing one!')
}
}
});
// remove the already updated values (in reverse order, not to mess up the indices)
removeValFromIndex.sort();
//console.log('nb to remove: '+removeValFromIndex.length);
//console.log(removeValFromIndex);
for (var i = removeValFromIndex.length -1; i >= 0; i--){
arraytmp.splice(removeValFromIndex[i],1);
//console.log(i,removeValFromIndex[i]);
}
//console.log('nb of new nodes: '+ arraytmp.length)
return array1.concat(arraytmp);
}

///////////////////////////////////////////////////////////////////
function find_active_links(list_of_links,active_nodes){
Expand Down
269 changes: 269 additions & 0 deletions viaz.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,269 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Graphexp, graph explorer</title>
<head>
<link rel="stylesheet" href="css/graphStyle.css">
<link rel="stylesheet" href="css/styles.css">
<!--<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css">
<script src="http://code.jquery.com/jquery-1.11.1.min.js"></script>-->
<link rel="stylesheet" href="font-awesome-4.7.0/css/font-awesome.min.css">
<!--<script src="jquery-1.11.3.min.js"></script>-->
<script src="jquery-3.2.1.min.js"></script>
<!-- <link rel="stylesheet" href="68eddd94.main.css">-->

<!--<script src="http://d3js.org/d3.v3.min.js"></script>-->
<script src="d3/d3.min.js"></script>
<script src="graphConf.js"></script>
<script src="graphShapes.js"></script>
<script src="infobox.js"></script>
<script src="graph_viz.js"></script>
<script src="graphioGremlin.js"></script>

<script type="text/javascript">

///////////////////////////////////////////////
function search_query(){
//if (typeof graph_viz.simulation!=='undefined') {graph_viz.simulation.stop(); console.log('Simulation stopped!');}
graphioGremlin.search_query();
}

function get_graph_info(){
graphioGremlin.get_graph_info();
}
</script>
<!-- ------------------------------------------------- -->



</head>
<body>
<div class="header">
<div class="container">
<h1 class="header-heading">Graph Explorer v 0.4</h1>
</div>
</div>
<div class="nav-bar">
<div class="container" id="nav_bar">
<ul class="nav">
<li>
Enter a field: <span id="prop_choice"><input name="search_field" id="search_field" value="" /></span>
</li>
<li>
Enter a Keyword/value: <input name="search_value" id="search_value" value="" />
</li>
<li><button name="search query" onclick="search_query();">Search</button></li>
<li><button name="clear" onclick="graph_viz.clear();">Clear</button></li>
<li><input type="checkbox" name="Freeze" id="freeze-in" />Freeze exploration</li>
<li>
<input type="checkbox" name="showName_box" id="showName" onclick="graphShapes.show_names()"/>Show labels
</li>
<li><input type="number" id="nbLayers" min="1" max="128" onclick="set_nb_layers()"> Nb of layers.
</li>
</ul>
</div>
</div>
<div class="content">
<div class="main" id="main">
<svg></svg>
</div>

<div class="aside left_bar" style="background-color:transparent;pointer-events:none;">
<div id="graphInfoBar" style="background-color:transparent;pointer-events:auto;">
<button name="graphInfo" onclick="get_graph_info();">Get graph info</button>
</div>
<div id="graphInfo" style="background-color:transparent;pointer-events:none;">
</div>
</div>

<div class="aside right_bar" id="details" style="background-color:transparent;pointer-events:none;">
<div id="messageArea"></div><div id="outputArea"></div>
<div id="nodeInfo" style="background-color:transparent;pointer-events:none;">
</div>
</div>
<!--
<div class="aside" id="ImageInfo" style="background-color:transparent;">
<center><svg width="100" height="100"></svg></center>
</div>
-->
</div>
<div class="footer">
<div class="container">
<a href="http://www.github.com/bricaud/graphexp">About</a>
</div>
</div>
<!-- INITIALIZATION -->
<script type="text/javascript">

init_property_bar();
// Create the graph canvas in the chosen div element
graph_viz.init("#main");
// Add the zoom layer to the graph
//var svg_graph =
graph_viz.addzoom();
//graph_viz.layers.set_nb_layers(4);

// Create the info box for node details
infobox.create("#graphInfo","#nodeInfo"); // from module in infobox.js

//console.log(graph_viz.graph_events.ev);
//graph_viz.graph_events.test();


function init_property_bar(){
document.getElementById('nbLayers').value = default_nb_of_layers;
}

function change_nav_bar(node_data,edge_data){
var nav_bar = d3.select("#prop_choice");
nav_bar.select("input").remove();
//nav_choices = nav_bar.append("ul");
//nav_choices.append("li").append("button").attr("onclick",search_query).text("Search")
var select = d3.select('#prop_choice')
.append('select').attr('class','select').attr('id','search_field')

var select_node = select.append('optgroup').attr('label','Nodes')
//.on('change',onchange)

var select_edge = select.append('optgroup').attr('label','Edges')

var node_options = select_node
.selectAll('option')
.data(node_data).enter()
.append('option')
.text(function (d) { return d; });

var edge_options = select_edge
.selectAll('option')
.data(edge_data).enter()
.append('option')
.text(function (d) { return d; });

}

function display_properties_bar(prop_list,item,text){
var nav_bar = d3.select("#graphInfoBar");
var property_bar = nav_bar.append("div").attr("id","property_bar_"+item);
property_bar.append('text').text(text).style("font-weight","bold");
//d3.select('#property_bar').append('text').text('hello')
var property_label = property_bar.selectAll('input').append("ul")
.data(prop_list).enter().append("li");
//.append('label');


property_label.append('input').attr('type','checkbox').attr('id',function (d) { return item+"_"+d; })
.attr('id_nb',function (d) { return prop_list.indexOf(d); })
//.attr('onchange',function(d){display_prop(d);});
.attr('onchange','display_prop(this)');

property_label.append('label').text(function (d) { return d; });


}

function display_color_choice(prop_list,item,text){
prop_list = ['none','label'].concat(prop_list);
var nav_bar = d3.select("#graphInfoBar");
var color_bar = nav_bar.append("div").attr("id","color_choice_"+item);
color_bar.append("text").text(text).style("font-weight","bold");
color_bar.append("select").attr("class","select").attr("id","color_select_"+item)
.attr("onchange","colorize(this)")
.selectAll("option")
.data(prop_list).enter()
.append("option")
.text(function (d) { return d; });
}

function colorize(selection){
var value = selection.value;
console.log(value);
graphShapes.colorize(value);

}

function display_prop(prop){
var prop_id = prop.id;
var prop_id_nb = prop.getAttribute('id_nb');
var text_base_offset = 10;
var text_offset = 10;
var prop_name = prop_id.slice(prop_id.indexOf("_")+1);
var item = prop_id.slice(0,prop_id.indexOf("_"));
if(d3.select("#"+prop_id).property("checked")){
if (item=='nodes'){
var elements_text = d3.selectAll('.node');
}
else if (item=='edges'){
var elements_text = d3.selectAll('.edgelabel');
}
attach_property(elements_text,prop_name,prop_id_nb,item)
}
else{
if (item=='nodes'){
d3.selectAll('.node').select('.'+prop_id).remove();
}
else if (item=='edges'){
d3.selectAll('.edgelabel').select('.'+prop_id).remove();
}

}
}


function attach_property(graph_objects,prop_name,prop_id_nb,item){
var text_base_offset = 10;
var text_offset = 10;
var prop_id = item+"_"+prop_name;
if (item=='nodes'){
elements_text = graph_objects.append("text").style("pointer-events", "none");
}
else if (item=='edges'){
var elements_text = graph_objects.append("textPath")
.attr('class','edge_text')
.attr('href', function (d, i) {return '#edgepath' + d.id})
.style("text-anchor", "middle")
.style("pointer-events", "none")
.attr("startOffset", "70%");
//.text(function (d) {return d.label});
prop_id_nb = prop_id_nb + 1;
}
else { console.log('Bad item name.'); return 1;}
elements_text.classed("prop_details",true).classed(prop_id,true)
//.attr("x", 12)
.attr("dy",function(d){return graphShapes.node_size(d)+text_base_offset+text_offset*parseInt(prop_id_nb);})
//.attr("y", ".31em")
.text(function(d){return get_prop_value(d,prop_name,item);});
}


function get_prop_value(d,prop_name,item){
if (prop_name in d.properties){
if (item=='nodes'){
return d.properties[prop_name][0].value;
}
else if (item=='edges'){
console.log(d.properties[prop_name])
return d.properties[prop_name];
}
}
else {
return "";
}
}

function set_nb_layers(){
var nb_layers = parseInt(document.getElementById('nbLayers').value);
//var nb_layers = parseInt(layer_input.getAttribute("value"));
console.log(nb_layers)
graph_viz.layers.set_nb_layers(nb_layers);

}




</script>

</body>
</html>

0 comments on commit bb97a6b

Please sign in to comment.