Browse Source

Merge remote-tracking branch 'origin/develop' into develop

Conflicts:
	dist/vis-light.js
v3_develop
jos 10 years ago
parent
commit
cd2483bc88
10 changed files with 8889 additions and 8610 deletions
  1. +8
    -0
      HISTORY.md
  2. +8624
    -8537
      dist/vis.js
  3. +79
    -0
      docs/network.html
  4. +2
    -1
      examples/network/29_neighbourhood_highlight.html
  5. +122
    -43
      examples/network/30_importing_from_gephi.html
  6. +2
    -0
      examples/network/index.html
  7. +2
    -1
      index.js
  8. +18
    -6
      lib/network/Network.js
  9. +23
    -22
      lib/network/gephiParser.js
  10. +9
    -0
      lib/util.js

+ 8
- 0
HISTORY.md View File

@ -35,6 +35,14 @@ http://visjs.org
- Added borderWidth option for nodes.
- Implemented new Hierarchical view solver.
- Fixed an issue with selecting nodes when the web page is scrolled down.
- Added Gephi JSON parser
- Added Neighbour Highlight example
- Added Import From Gephi example
- Enabled color parsing for nodes when supplied with rgb(xxx,xxx,xxx) value.
### DataSet
- Added .get() returnType option to return as JSON object, Array or Google DataTable.

+ 8624
- 8537
dist/vis.js
File diff suppressed because it is too large
View File


+ 79
- 0
docs/network.html View File

@ -54,6 +54,7 @@
<li><a href="#Nodes">Nodes</a></li>
<li><a href="#Edges">Edges</a></li>
<li><a href="#DOT_language">DOT language</a></li>
<li><a href="#Gephi_import">Gephi import</a></li>
</ul>
</li>
<li>
@ -759,7 +760,85 @@ var data = {
var network = new vis.Network(container, data);
</pre>
<h3 id="Gephi_import">Gephi import (JSON)</h3>
<p>
network can import data straight from an exported json file from gephi. You can get the JSON exporter here:
<a href="https://marketplace.gephi.org/plugin/json-exporter/" target="_blank">https://marketplace.gephi.org/plugin/json-exporter/</a>.
An example exists showing how to get a JSON file into Vis: <a href="../examples/Network/30_importing_from_gephi.html">30_importing_from_gephi</a>.
</p>
<p>
Example usage:
</p>
<pre class="prettyprint lang-js">
// load the JSON file containing the Gephi network.
var gephiJSON = loadJSON("./data/WorldCup2014.json"); // code in example 30
// create a data object with the gephi key:
var data = {
gephi: gephiJSON
};
// create a network
var network = new vis.Network(container, data);
</pre>
Alternatively you can use the parser manually:
<pre class="prettyprint lang-js">
// load the JSON file containing the Gephi network.
var gephiJSON = loadJSON("./data/WorldCup2014.json"); // code in example 30
// parse the gephi file to receive an object
// containing nodes and edges in vis format.
var parsed = vis.network.gephiParser.parseGephi(gephiJSON);
// provide data in the normal fashion
var data = {
nodes: parsed.nodes,
edged: parsed.edges
};
// create a network
var network = new vis.Network(container, data);
</pre>
<h4>Gephi parser options</h4>
There are a few options you can use to tell Vis what to do with the data from Gephi.
<pre class="prettyprint lang-js">
var parserOptions = {
allowedToMove: false,
parseColor: false
}
var parsed = vis.network.gephiParser.parseGephi(gephiJSON, parserOptions);
</pre>
<table>
<tr>
<th>Name</th>
<th>Type</th>
<th>Default</th>
<th>Description</th>
</tr>
<tr>
<td>allowedToMove</td>
<td>Boolean</td>
<td>false</td>
<td>
If true, the nodes will move according to the physics model after import. If false, the nodes do not move at all.
</td>
</tr>
<tr>
<td>parseColor</td>
<td>Boolean</td>
<td>false</td>
<td>
If true, the color will be parsed by the vis parser, generating extra colors for the borders, highlighs and hover. If false, the node will be the supplied color.
</td>
</tr>
</table>
<h2 id="Configuration_options">Configuration options</h2>

+ 2
- 1
examples/network/29_neighbourhood_highlight.html View File

@ -18,10 +18,11 @@
<body>
<h2>Dynamic Data - Neighbourhood Highlight</h2>
<div style="width:700px; font-size:14px;">
<div style="width:800px; font-size:14px;">
This example shows the power of the DataSet. Once a node is clicked, all nodes are greyed out except for the first and second order connected nodes.
In this example we show how you can determine the order of connection per node as well as applying individual styling to the nodes based on whether or not
they are connected to the selected node. The code doing the highlighting only takes about 20ms, the rest of the time is the redrawing of the network (9200 edges..).
<br /><br />
</div>
<div id="mynetwork"></div>

+ 122
- 43
examples/network/30_importing_from_gephi.html View File

@ -1,8 +1,7 @@
<!DOCTYPE html>
<!-- saved from url=(0044)http://kenedict.com/networks/worldcup14/vis/ , thanks Andre!-->
<html><head><meta http-equiv="content-type" content="text/html; charset=UTF8">
<title>Network | Static smooth curves - World Cup Network</title>
<title>Dynamic Data - Importing from Gephi (JSON)</title>
<script type="text/javascript" src="../../dist/vis.js"></script>
<link type="text/css" rel="stylesheet" href="../../dist/vis.css">
@ -12,74 +11,154 @@
height: 800px;
border: 1px solid lightgray;
}
div.nodeContent {
position: relative;
border: 1px solid lightgray;
width:480px;
height:780px;
margin-top: -802px;
margin-left: 810px;
padding:10px;
}
pre {padding: 5px; margin: 5px; }
.string { color: green; }
.number { color: darkorange; }
.boolean { color: blue; }
.null { color: magenta; }
.key { color: red; }
</style>
</head>
<body>
<h2>Dynamic Data - Neighbourhood Highlight</h2>
<h2>Dynamic Data - Importing from Gephi (JSON)</h2>
<div style="width:700px; font-size:14px;">
This example shows the power of the DataSet. Once a node is clicked, all nodes are greyed out except for the first and second order connected nodes.
In this example we show how you can determine the order of connection per node as well as applying individual styling to the nodes based on whether or not
they are connected to the selected node. The code doing the highlighting only takes about 20ms, the rest of the time is the redrawing of the network (9200 edges..).
This example shows how to import a JSON file exported by Gephi. The two options available for the import are
available through the checkboxes. You can download the Gephi JSON exporter here:
<a href="https://marketplace.gephi.org/plugin/json-exporter/" target="_blank">https://marketplace.gephi.org/plugin/json-exporter/</a>.
All of Gephi's attributes are also contained within the node elements. This means you can access all of this data through the DataSet.
<br />
</div>
<input type="checkbox" id="allowedToMove">: Allow to move after import. <br/>
<input type="checkbox" id="parseColor">: Parse the color instead of copy (adds borders, highlights etc.)
<div id="mynetwork"></div>
<div class="nodeContent"><h4>Node Content:</h4> <pre id="nodeContent"></pre></div>
<script type="text/javascript">
var network;
var nodes = new vis.DataSet();
var edges = new vis.DataSet();
var gephiImported;
var allowedToMoveCheckbox = document.getElementById("allowedToMove");
allowedToMoveCheckbox.onchange = redrawAll;
var parseColorCheckbox = document.getElementById("parseColor");
parseColorCheckbox.onchange = redrawAll;
var nodeContent = document.getElementById("nodeContent");
loadJSON("./data/WorldCup2014.json",redrawAll);
var container = document.getElementById('mynetwork');
var data = {
nodes: nodes,
edges: edges
};
var options = {
nodes: {
shape: 'dot',
fontFace: "Tahoma"
},
edges: {
width: 0.15,
inheritColor: "from"
},
tooltip: {
delay: 200,
fontSize: 12,
color: {
background: "#fff"
}
},
smoothCurves: {dynamic:false, type: "continuous"},
stabilize: false,
physics: {barnesHut: {gravitationalConstant: -10000, springConstant: 0.002, springLength: 150}},
hideEdgesOnDrag: true
};
network = new vis.Network(container, data, options);
/**
* This function fills the DataSets. These DataSets will update the network.
*/
function redrawAll(gephiJSON) {
if (gephiJSON.nodes === undefined) {
gephiJSON = gephiImported;
}
else {
gephiImported = gephiJSON;
}
function redrawAll() {
nodes.clear();
edges.clear();
network = null;
// create an array with nodes
var allowedToMove = allowedToMoveCheckbox.checked;
var parseColor = parseColorCheckbox.checked;
var parsed = vis.network.gephiParser.parseGephi(gephiJSON, {allowedToMove:allowedToMove, parseColor:parseColor});
// add the parsed data to the DataSets.
nodes.add(parsed.nodes);
edges.add(parsed.edges);
var data = nodes.get(2); // get the data from node 2
nodeContent.innerHTML = syntaxHighlight(data); // show the data in the div
network.zoomExtent(); // zoom to fit
}
nodes.add(nodesData);
edges.add(edgesData);
// from http://stackoverflow.com/questions/4810841/how-can-i-pretty-print-json-using-javascript
function syntaxHighlight(json) {
if (typeof json != 'string') {
json = JSON.stringify(json, undefined, 2);
}
json = json.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
return json.replace(/("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)/g, function (match) {
var cls = 'number';
if (/^"/.test(match)) {
if (/:$/.test(match)) {
cls = 'key';
} else {
cls = 'string';
}
} else if (/true|false/.test(match)) {
cls = 'boolean';
} else if (/null/.test(match)) {
cls = 'null';
}
return '<span class="' + cls + '">' + match + '</span>';
});
}
var container = document.getElementById('mynetwork');
var data = {
nodes: nodes,
edges: edges
};
var options = {
nodes: {
shape: 'dot',
radiusMin: 10,
radiusMax: 30,
fontSize: 12,
fontFace: "Tahoma"
},
edges: {
width: 0.15,
inheritColor: "from"
},
tooltip: {
delay: 200,
fontSize: 12,
color: {
background: "#fff"
function loadJSON(path, success, error) {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
success(JSON.parse(xhr.responseText));
}
else {
error(xhr);
}
},
smoothCurves: {dynamic:false, type: "continuous"},
stabilize: false,
physics: {barnesHut: {gravitationalConstant: 0, centralGravity: 0, springConstant: 0}},
hideEdgesOnDrag: true
}
};
network = new vis.Network(container, data, options);
xhr.open("GET", path, true);
xhr.send();
}
redrawAll()
</script>

+ 2
- 0
examples/network/index.html View File

@ -40,6 +40,8 @@
<p><a href="26_staticSmoothCurves.html">26_staticSmoothCurves.html</a></p>
<p><a href="27_world_cup_network.html">27_world_cup_network.html</a></p>
<p><a href="28_world_cup_network_performance.html">28_world_cup_network_performance.html</a></p>
<p><a href="29_neighbourhood_highlight.html">29_neighbourhood_highlight.html</a></p>
<p><a href="30_importing_from_gephi.html">30_importing_from_gephi.html</a></p>
<p><a href="graphviz/graphviz_gallery.html">graphviz_gallery.html</a></p>
</div>

+ 2
- 1
index.js View File

@ -55,7 +55,8 @@ exports.network = {
Images: require('./lib/network/Images'),
Node: require('./lib/network/Node'),
Popup: require('./lib/network/Popup'),
dotparser: require('./lib/network/dotparser')
dotparser: require('./lib/network/dotparser'),
gephiParser: require('./lib/network/gephiParser')
};
// Deprecated since v3.0.0

+ 18
- 6
lib/network/Network.js View File

@ -6,6 +6,7 @@ var hammerUtil = require('../hammerUtil');
var DataSet = require('../DataSet');
var DataView = require('../DataView');
var dotparser = require('./dotparser');
var gephiParser = require('./gephiParser');
var Groups = require('./Groups');
var Images = require('./Images');
var Node = require('./Node');
@ -503,6 +504,7 @@ Network.prototype._updateNodeIndexList = function() {
* {Array | DataSet | DataView} [nodes] Array with nodes
* {Array | DataSet | DataView} [edges] Array with edges
* {String} [dot] String containing data in DOT format
* {String} [gephi] String containing data in gephi JSON format
* {Options} [options] Object with options
* @param {Boolean} [disableStart] | optional: disable the calling of the start function.
*/
@ -528,6 +530,14 @@ Network.prototype.setData = function(data, disableStart) {
return;
}
}
else if (data && data.gephi) {
// parse DOT file
if(data && data.gephi) {
var gephiData = gephiParser.parseGephi(data.gephi);
this.setData(gephiData);
return;
}
}
else {
this._setNodes(data && data.nodes);
this._setEdges(data && data.edges);
@ -1064,7 +1074,7 @@ Network.prototype._handleOnDrag = function(event) {
Network.prototype._onDragEnd = function () {
this.drag.dragging = false;
var selection = this.drag.selection;
if (selection) {
if (selection && selection.length) {
selection.forEach(function (s) {
// restore original xFixed and yFixed
s.node.xFixed = s.xFixed;
@ -1073,7 +1083,10 @@ Network.prototype._onDragEnd = function () {
this.moving = true;
this.start();
}
this._redraw();
else {
this._redraw();
}
};
/**
@ -2124,10 +2137,10 @@ Network.prototype._discreteStepNodes = function() {
*/
Network.prototype._physicsTick = function() {
if (!this.freezeSimulation) {
if (this.moving) {
if (this.moving == true) {
this._doInAllActiveSectors("_initializeForceCalculation");
this._doInAllActiveSectors("_discreteStepNodes");
if (this.constants.smoothCurves) {
if (this.constants.smoothCurves.enabled == true && this.constants.smoothCurves.dynamic == true) {
this._doInSupportSector("_discreteStepNodes");
}
this._findCenter(this._getRange())
@ -2161,7 +2174,6 @@ Network.prototype._animationStep = function() {
timeRequired = Date.now() - calculationTime;
maxSteps++;
}
// start the rendering process
var renderTime = Date.now();
this._redraw();
@ -2178,7 +2190,7 @@ if (typeof window !== 'undefined') {
* Schedule a animation step with the refreshrate interval.
*/
Network.prototype.start = function() {
if (this.moving || this.xIncrement != 0 || this.yIncrement != 0 || this.zoomIncrement != 0) {
if (this.moving == true || this.xIncrement != 0 || this.yIncrement != 0 || this.zoomIncrement != 0) {
if (!this.timer) {
var ua = navigator.userAgent.toLowerCase();

+ 23
- 22
lib/network/gephiParser.js View File

@ -4,52 +4,53 @@ function parseGephi(gephiJSON, options) {
var nodes = [];
this.options = {
edges: {
inheritColor: 'from'
inheritColor: true
},
nodes: {
allowedToMove: false,
parseColor: false
}
};
if (options !== undefined) {
this.options.edges['inheritColor'] = options.inheritColor | 'from';
this.options.nodes['allowedToMove'] = options.allowedToMove | false;
this.options.nodes['parseColor'] = options.parseColor | false;
this.options.edges['inheritColor'] = options.inheritColor | true;
}
var gEdges = gephiJSON.edges;
var gNodes = gephiJSON.nodes;
for (var i = 0; i < gEdges.length; i++) {
var edge = {};
edge['id'] = gEdges.id;
edge['from'] = gEdges.source;
edge['to'] = gEdges.target;
edge['attributes'] = gEdges.attributes;
edge['value'] = gEdges.attributes !== undefined ? gEdges.attributes.Weight : undefined;
edge['width'] = gEdges.size;
edge['color'] = gEdges.color;
var gEdge = gEdges[i];
edge['id'] = gEdge.id;
edge['from'] = gEdge.source;
edge['to'] = gEdge.target;
edge['attributes'] = gEdge.attributes;
// edge['value'] = gEdge.attributes !== undefined ? gEdge.attributes.Weight : undefined;
// edge['width'] = edge['value'] !== undefined ? undefined : edgegEdge.size;
edge['color'] = gEdge.color;
edge['inheritColor'] = edge['color'] !== undefined ? false : this.options.inheritColor;
edges.push(edge);
}
for (var i = 0; i < gNodes.length; i++) {
var node = {};
node['id'] = gNodes.id;
node['attributes'] = gNodes.attributes;
node['x'] = gNodes.x;
node['y'] = gNodes.y;
node['label'] = gNodes.label;
if (this.options.parseColor == true) {
node['color'] = gNodes.color;
var gNode = gNodes[i];
node['id'] = gNode.id;
node['attributes'] = gNode.attributes;
node['x'] = gNode.x;
node['y'] = gNode.y;
node['label'] = gNode.label;
if (this.options.nodes.parseColor == true) {
node['color'] = gNode.color;
}
else {
node['color'] = gNodes.color !== undefined ? {background:gNodes.color, border:gNodes.color} : undefined;
node['color'] = gNode.color !== undefined ? {background:gNode.color, border:gNode.color} : undefined;
}
node['radius'] = gNodes.size;
node['allowedToMoveX'] = this.options.allowedToMove;
node['allowedToMoveY'] = this.options.allowedToMove;
node['shape'] = 'dot'
node['radius'] = gNode.size;
node['allowedToMoveX'] = this.options.nodes.allowedToMove;
node['allowedToMoveY'] = this.options.nodes.allowedToMove;
nodes.push(node);
}

+ 9
- 0
lib/util.js View File

@ -753,6 +753,10 @@ exports.GiveHex = function(Dec) {
exports.parseColor = function(color) {
var c;
if (exports.isString(color)) {
if (exports.isValidRGB(color)) {
var rgb = color.substr(4).substr(0,color.length-5).split(',');
color = exports.RGBToHex(rgb[0],rgb[1],rgb[2]);
}
if (exports.isValidHex(color)) {
var hsv = exports.hexToHSV(color);
var lighterColorHSV = {h:hsv.h,s:hsv.s * 0.45,v:Math.min(1,hsv.v * 1.05)};
@ -930,6 +934,11 @@ exports.isValidHex = function(hex) {
return isOk;
};
exports.isValidRGB = function(rgb) {
rgb = rgb.replace(" ","");
var isOk = /rgb\((\d{1,3}),(\d{1,3}),(\d{1,3})\)/i.test(rgb);
return isOk;
}
/**
* This recursively redirects the prototype of JSON objects to the referenceObject

Loading…
Cancel
Save