Browse Source

fixed another bug in hierarchical layout

codeClimate
Alex de Mulder 8 years ago
parent
commit
822243e02a
3 changed files with 317 additions and 356 deletions
  1. +90
    -78
      dist/vis.js
  2. +85
    -76
      lib/network/modules/LayoutEngine.js
  3. +142
    -202
      test/networkTest.html

+ 90
- 78
dist/vis.js View File

@ -5,7 +5,7 @@
* A dynamic, browser-based visualization library. * A dynamic, browser-based visualization library.
* *
* @version 4.14.0 * @version 4.14.0
* @date 2016-02-21
* @date 2016-02-23
* *
* @license * @license
* Copyright (C) 2011-2016 Almende B.V, http://almende.com * Copyright (C) 2011-2016 Almende B.V, http://almende.com
@ -41012,9 +41012,7 @@ return /******/ (function(modules) { // webpackBootstrap
pos = this._getPositionForHierarchy(nodeArray[i - 1]) + this.options.hierarchical.nodeSpacing; pos = this._getPositionForHierarchy(nodeArray[i - 1]) + this.options.hierarchical.nodeSpacing;
} }
this._setPositionForHierarchy(node, pos, level); this._setPositionForHierarchy(node, pos, level);
this.positionedNodes[node.id] = true;
this._placeBranchNodes(node.id, level);
this._validataPositionAndContinue(node, level, pos);
handledNodeCount++; handledNodeCount++;
} }
@ -41023,6 +41021,93 @@ return /******/ (function(modules) { // webpackBootstrap
} }
} }
/**
* This is a recursively called function to enumerate the branches from the largest hubs and place the nodes
* on a X position that ensures there will be no overlap.
*
* @param parentId
* @param parentLevel
* @private
*/
}, {
key: '_placeBranchNodes',
value: function _placeBranchNodes(parentId, parentLevel) {
// if this is not a parent, cancel the placing. This can happen with multiple parents to one child.
if (this.hierarchicalChildrenReference[parentId] === undefined) {
return;
}
// get a list of childNodes
var childNodes = [];
for (var i = 0; i < this.hierarchicalChildrenReference[parentId].length; i++) {
childNodes.push(this.body.nodes[this.hierarchicalChildrenReference[parentId][i]]);
}
// use the positions to order the nodes.
this._sortNodeArray(childNodes);
// position the childNodes
for (var i = 0; i < childNodes.length; i++) {
var childNode = childNodes[i];
var childNodeLevel = this.hierarchicalLevels[childNode.id];
// check if the child node is below the parent node and if it has already been positioned.
if (childNodeLevel > parentLevel && this.positionedNodes[childNode.id] === undefined) {
// get the amount of space required for this node. If parent the width is based on the amount of children.
var pos = undefined;
// we get the X or Y values we need and store them in pos and previousPos. The get and set make sure we get X or Y
if (i === 0) {
pos = this._getPositionForHierarchy(this.body.nodes[parentId]);
} else {
pos = this._getPositionForHierarchy(childNodes[i - 1]) + this.options.hierarchical.nodeSpacing;
}
this._setPositionForHierarchy(childNode, pos, childNodeLevel);
this._validataPositionAndContinue(childNode, childNodeLevel, pos);
} else {
return;
}
}
// center the parent nodes.
var minPos = 1e9;
var maxPos = -1e9;
for (var i = 0; i < childNodes.length; i++) {
var childNodeId = childNodes[i].id;
minPos = Math.min(minPos, this._getPositionForHierarchy(this.body.nodes[childNodeId]));
maxPos = Math.max(maxPos, this._getPositionForHierarchy(this.body.nodes[childNodeId]));
}
this._setPositionForHierarchy(this.body.nodes[parentId], 0.5 * (minPos + maxPos), parentLevel);
}
/**
* This method checks for overlap and if required shifts the branch. It also keeps records of positioned nodes.
* Finally it will call _placeBranchNodes to place the branch nodes.
* @param node
* @param level
* @param pos
* @private
*/
}, {
key: '_validataPositionAndContinue',
value: function _validataPositionAndContinue(node, level, pos) {
// if overlap has been detected, we shift the branch
if (this.lastNodeOnLevel[level] !== undefined) {
var previousPos = this._getPositionForHierarchy(this.body.nodes[this.lastNodeOnLevel[level]]);
if (pos - previousPos < this.options.hierarchical.nodeSpacing) {
var diff = previousPos + this.options.hierarchical.nodeSpacing - pos;
var sharedParent = this._findCommonParent(this.lastNodeOnLevel[level], node.id);
this._shiftBlock(sharedParent.withChild, diff);
}
}
// store change in position.
this.lastNodeOnLevel[level] = node.id;
this.positionedNodes[node.id] = true;
this._placeBranchNodes(node.id, level);
}
/** /**
* Receives an array with node indices and returns an array with the actual node references. Used for sorting based on * Receives an array with node indices and returns an array with the actual node references. Used for sorting based on
* node properties. * node properties.
@ -41308,80 +41393,6 @@ return /******/ (function(modules) { // webpackBootstrap
} }
} }
/**
* This is a recursively called function to enumerate the branches from the largest hubs and place the nodes
* on a X position that ensures there will be no overlap.
*
* @param parentId
* @param parentLevel
* @private
*/
}, {
key: '_placeBranchNodes',
value: function _placeBranchNodes(parentId, parentLevel) {
// if this is not a parent, cancel the placing. This can happen with multiple parents to one child.
if (this.hierarchicalChildrenReference[parentId] === undefined) {
return;
}
// get a list of childNodes
var childNodes = [];
for (var i = 0; i < this.hierarchicalChildrenReference[parentId].length; i++) {
childNodes.push(this.body.nodes[this.hierarchicalChildrenReference[parentId][i]]);
}
// use the positions to order the nodes.
this._sortNodeArray(childNodes);
// position the childNodes
for (var i = 0; i < childNodes.length; i++) {
var childNode = childNodes[i];
var childNodeLevel = this.hierarchicalLevels[childNode.id];
// check if the child node is below the parent node and if it has already been positioned.
if (childNodeLevel > parentLevel && this.positionedNodes[childNode.id] === undefined) {
// get the amount of space required for this node. If parent the width is based on the amount of children.
var pos = undefined;
// we get the X or Y values we need and store them in pos and previousPos. The get and set make sure we get X or Y
if (i === 0) {
pos = this._getPositionForHierarchy(this.body.nodes[parentId]);
} else {
pos = this._getPositionForHierarchy(childNodes[i - 1]) + this.options.hierarchical.nodeSpacing;
}
this._setPositionForHierarchy(childNode, pos, childNodeLevel);
// if overlap has been detected, we shift the branch
if (this.lastNodeOnLevel[childNodeLevel] !== undefined) {
var previousPos = this._getPositionForHierarchy(this.body.nodes[this.lastNodeOnLevel[childNodeLevel]]);
if (pos - previousPos < this.options.hierarchical.nodeSpacing) {
var diff = previousPos + this.options.hierarchical.nodeSpacing - pos;
var sharedParent = this._findCommonParent(this.lastNodeOnLevel[childNodeLevel], childNode.id);
this._shiftBlock(sharedParent.withChild, diff);
}
}
// store change in position.
this.lastNodeOnLevel[childNodeLevel] = childNode.id;
this.positionedNodes[childNode.id] = true;
this._placeBranchNodes(childNode.id, childNodeLevel);
} else {
return;
}
}
// center the parent nodes.
var minPos = 1e9;
var maxPos = -1e9;
for (var i = 0; i < childNodes.length; i++) {
var childNodeId = childNodes[i].id;
minPos = Math.min(minPos, this._getPositionForHierarchy(this.body.nodes[childNodeId]));
maxPos = Math.max(maxPos, this._getPositionForHierarchy(this.body.nodes[childNodeId]));
}
this._setPositionForHierarchy(this.body.nodes[parentId], 0.5 * (minPos + maxPos), parentLevel);
}
/** /**
* Shift a branch a certain distance * Shift a branch a certain distance
* @param parentId * @param parentId
@ -41457,6 +41468,7 @@ return /******/ (function(modules) { // webpackBootstrap
value: function _setPositionForHierarchy(node, position, level) { value: function _setPositionForHierarchy(node, position, level) {
var doNotUpdate = arguments.length <= 3 || arguments[3] === undefined ? false : arguments[3]; var doNotUpdate = arguments.length <= 3 || arguments[3] === undefined ? false : arguments[3];
//console.log('_setPositionForHierarchy',node.id, position)
if (doNotUpdate !== true) { if (doNotUpdate !== true) {
if (this.distributionOrdering[level] === undefined) { if (this.distributionOrdering[level] === undefined) {
this.distributionOrdering[level] = []; this.distributionOrdering[level] = [];

+ 85
- 76
lib/network/modules/LayoutEngine.js View File

@ -867,9 +867,7 @@ class LayoutEngine {
// we get the X or Y values we need and store them in pos and previousPos. The get and set make sure we get X or Y // we get the X or Y values we need and store them in pos and previousPos. The get and set make sure we get X or Y
if (handledNodeCount > 0) {pos = this._getPositionForHierarchy(nodeArray[i-1]) + this.options.hierarchical.nodeSpacing;} if (handledNodeCount > 0) {pos = this._getPositionForHierarchy(nodeArray[i-1]) + this.options.hierarchical.nodeSpacing;}
this._setPositionForHierarchy(node, pos, level); this._setPositionForHierarchy(node, pos, level);
this.positionedNodes[node.id] = true;
this._placeBranchNodes(node.id, level);
this._validataPositionAndContinue(node, level, pos);
handledNodeCount++; handledNodeCount++;
} }
@ -878,6 +876,89 @@ class LayoutEngine {
} }
} }
/**
* This is a recursively called function to enumerate the branches from the largest hubs and place the nodes
* on a X position that ensures there will be no overlap.
*
* @param parentId
* @param parentLevel
* @private
*/
_placeBranchNodes(parentId, parentLevel) {
// if this is not a parent, cancel the placing. This can happen with multiple parents to one child.
if (this.hierarchicalChildrenReference[parentId] === undefined) {
return;
}
// get a list of childNodes
let childNodes = [];
for (let i = 0; i < this.hierarchicalChildrenReference[parentId].length; i++) {
childNodes.push(this.body.nodes[this.hierarchicalChildrenReference[parentId][i]]);
}
// use the positions to order the nodes.
this._sortNodeArray(childNodes);
// position the childNodes
for (let i = 0; i < childNodes.length; i++) {
let childNode = childNodes[i];
let childNodeLevel = this.hierarchicalLevels[childNode.id];
// check if the child node is below the parent node and if it has already been positioned.
if (childNodeLevel > parentLevel && this.positionedNodes[childNode.id] === undefined) {
// get the amount of space required for this node. If parent the width is based on the amount of children.
let pos;
// we get the X or Y values we need and store them in pos and previousPos. The get and set make sure we get X or Y
if (i === 0) {pos = this._getPositionForHierarchy(this.body.nodes[parentId]);}
else {pos = this._getPositionForHierarchy(childNodes[i-1]) + this.options.hierarchical.nodeSpacing;}
this._setPositionForHierarchy(childNode, pos, childNodeLevel);
this._validataPositionAndContinue(childNode, childNodeLevel, pos);
}
else {
return;
}
}
// center the parent nodes.
let minPos = 1e9;
let maxPos = -1e9;
for (let i = 0; i < childNodes.length; i++) {
let childNodeId = childNodes[i].id;
minPos = Math.min(minPos, this._getPositionForHierarchy(this.body.nodes[childNodeId]));
maxPos = Math.max(maxPos, this._getPositionForHierarchy(this.body.nodes[childNodeId]));
}
this._setPositionForHierarchy(this.body.nodes[parentId], 0.5 * (minPos + maxPos), parentLevel);
}
/**
* This method checks for overlap and if required shifts the branch. It also keeps records of positioned nodes.
* Finally it will call _placeBranchNodes to place the branch nodes.
* @param node
* @param level
* @param pos
* @private
*/
_validataPositionAndContinue(node, level, pos) {
// if overlap has been detected, we shift the branch
if (this.lastNodeOnLevel[level] !== undefined) {
let previousPos = this._getPositionForHierarchy(this.body.nodes[this.lastNodeOnLevel[level]]);
if (pos - previousPos < this.options.hierarchical.nodeSpacing) {
let diff = (previousPos + this.options.hierarchical.nodeSpacing) - pos;
let sharedParent = this._findCommonParent(this.lastNodeOnLevel[level], node.id);
this._shiftBlock(sharedParent.withChild, diff);
}
}
// store change in position.
this.lastNodeOnLevel[level] = node.id;
this.positionedNodes[node.id] = true;
this._placeBranchNodes(node.id, level);
}
/** /**
* Receives an array with node indices and returns an array with the actual node references. Used for sorting based on * Receives an array with node indices and returns an array with the actual node references. Used for sorting based on
* node properties. * node properties.
@ -1146,79 +1227,6 @@ class LayoutEngine {
} }
/**
* This is a recursively called function to enumerate the branches from the largest hubs and place the nodes
* on a X position that ensures there will be no overlap.
*
* @param parentId
* @param parentLevel
* @private
*/
_placeBranchNodes(parentId, parentLevel) {
// if this is not a parent, cancel the placing. This can happen with multiple parents to one child.
if (this.hierarchicalChildrenReference[parentId] === undefined) {
return;
}
// get a list of childNodes
let childNodes = [];
for (let i = 0; i < this.hierarchicalChildrenReference[parentId].length; i++) {
childNodes.push(this.body.nodes[this.hierarchicalChildrenReference[parentId][i]]);
}
// use the positions to order the nodes.
this._sortNodeArray(childNodes);
// position the childNodes
for (let i = 0; i < childNodes.length; i++) {
let childNode = childNodes[i];
let childNodeLevel = this.hierarchicalLevels[childNode.id];
// check if the child node is below the parent node and if it has already been positioned.
if (childNodeLevel > parentLevel && this.positionedNodes[childNode.id] === undefined) {
// get the amount of space required for this node. If parent the width is based on the amount of children.
let pos;
// we get the X or Y values we need and store them in pos and previousPos. The get and set make sure we get X or Y
if (i === 0) {pos = this._getPositionForHierarchy(this.body.nodes[parentId]);}
else {pos = this._getPositionForHierarchy(childNodes[i-1]) + this.options.hierarchical.nodeSpacing;}
this._setPositionForHierarchy(childNode, pos, childNodeLevel);
// if overlap has been detected, we shift the branch
if (this.lastNodeOnLevel[childNodeLevel] !== undefined) {
let previousPos = this._getPositionForHierarchy(this.body.nodes[this.lastNodeOnLevel[childNodeLevel]]);
if (pos - previousPos < this.options.hierarchical.nodeSpacing) {
let diff = (previousPos + this.options.hierarchical.nodeSpacing) - pos;
let sharedParent = this._findCommonParent(this.lastNodeOnLevel[childNodeLevel], childNode.id);
this._shiftBlock(sharedParent.withChild, diff);
}
}
// store change in position.
this.lastNodeOnLevel[childNodeLevel] = childNode.id;
this.positionedNodes[childNode.id] = true;
this._placeBranchNodes(childNode.id, childNodeLevel);
}
else {
return;
}
}
// center the parent nodes.
let minPos = 1e9;
let maxPos = -1e9;
for (let i = 0; i < childNodes.length; i++) {
let childNodeId = childNodes[i].id;
minPos = Math.min(minPos, this._getPositionForHierarchy(this.body.nodes[childNodeId]));
maxPos = Math.max(maxPos, this._getPositionForHierarchy(this.body.nodes[childNodeId]));
}
this._setPositionForHierarchy(this.body.nodes[parentId], 0.5 * (minPos + maxPos), parentLevel);
}
/** /**
* Shift a branch a certain distance * Shift a branch a certain distance
* @param parentId * @param parentId
@ -1286,6 +1294,7 @@ class LayoutEngine {
* @private * @private
*/ */
_setPositionForHierarchy(node, position, level, doNotUpdate = false) { _setPositionForHierarchy(node, position, level, doNotUpdate = false) {
//console.log('_setPositionForHierarchy',node.id, position)
if (doNotUpdate !== true) { if (doNotUpdate !== true) {
if (this.distributionOrdering[level] === undefined) { if (this.distributionOrdering[level] === undefined) {
this.distributionOrdering[level] = []; this.distributionOrdering[level] = [];

+ 142
- 202
test/networkTest.html View File

@ -7,7 +7,7 @@
<link href="../dist/vis.css" rel="stylesheet" type="text/css"/> <link href="../dist/vis.css" rel="stylesheet" type="text/css"/>
<style type="text/css"> <style type="text/css">
#network{ #network{
width: 1900px;
width: 1200px;
height: 800px; height: 800px;
border: 1px solid lightgray; border: 1px solid lightgray;
} }
@ -18,228 +18,168 @@
<div id="network"></div> <div id="network"></div>
<script type="text/javascript"> <script type="text/javascript">
var allNodes;
var allEdges;
var pathActive = false;
var nodes = [{
id: 1,
label: 'test1'
}, {
id: 2,
label: 'test2'
}, {
id: 3,
label: 'test3'
}, {
id: 4,
label: 'test4'
}, {
id: 5,
label: 'test5'
}];
var edges = [{
from: 1,
to: 3
}, {
from: 1,
to: 2
}, {
from: 3,
to: 4
}, {
from: 2,
to: 4
}, {
from: 4,
to: 5
}]
var nodesDataset = new vis.DataSet(nodes);
var edgesDataset = new vis.DataSet(edges);
var container = document.getElementById('mynetwork');
// create a network
var container = document.getElementById('network');
var data = { var data = {
nodes: nodesDataset,
edges: edgesDataset
};
var options = {
autoResize: true,
height: '100%',
width: '100%',
nodes: {
shape: 'box'
},
edges: {
smooth: {
enabled: true,
type: "dynamic"
},
},
layout: {
hierarchical: {
levelSeparation: 220,
nodeSpacing: 120,
treeSpacing: 100,
direction: 'LR',
blockShifting: true,
sortMethod: 'directed',
edgeMinimization: false
}
},
physics: {
hierarchicalRepulsion: {
centralGravity: 0.5,
springLength: 300,
springConstant: 0.1,
nodeDistance: 150,
damping: 0.09
},
}
nodes: [{
"id": "59acc308-fc78-11e3-a451-005056967662_1",
"level": 1,
"shape": "box",
"label": "737464 (HALB)\nLenks\u00e4ule\n0 | M1182 - TK-PF\n0 | M2676 - TK-PF",
}, {
"id": "bc5ada61-e297-11e3-a03f-005056967662_2",
"level": 2,
"shape": "box",
"label": "578647 C (HALB)\nF\u00fchrungskasten komplett\n0000 | M2731 - TK-PF",
}, {
"id": "6f8a780a-e28e-11e3-a03f-005056967662_2",
"level": 2,
"shape": "box",
"label": "615430 C (HALB)\nF\u00fchrungskasten komplett\n0000 | M2781 - TK-PF\n0000 | M2788 - TK-PF",
}, {
"id": "49bb72b1-e2b2-11e3-a03f-005056967662_2",
"level": 2,
"shape": "box",
"label": "678478 D (HALB)\nF\u00fchrungskasten montiert\n0 | M1085 - TK-PFC",
}, {
"id": "e7bf7c7e-e28e-11e3-a03f-005056967662_2",
"level": 2,
"shape": "box",
"label": "727672 B (HALB)\nF\u00fchrungskasten komplett\n0 | M9999 - TK-PTH\n0000 | M1155 - TK-PTH",
}, {
"id": "623e8501-e2e2-11e3-a03f-005056967662_2",
"level": 2,
"shape": "box",
"label": "760550 A (HALB)\nF\u00fchrungskasten komplett\n0000 | M1556 - TK-PHS",
}, {
"id": "e7c6dcdf-e28e-11e3-a03f-005056967662_2",
"level": 2,
"shape": "box",
"label": "793641 A (HALB)\nF\u00fchrungskasten komplett\n0000 | M1155 - TK-PTH",
}, {
"id": "623edd04-e2e2-11e3-a03f-005056967662_2",
"level": 2,
"shape": "box",
"label": "802797 A (HALB)\nF\u00fchrungskasten komplett\n0 | M1556 - TK-PHS",
}, {
"id": "a986a9ab-fc82-11e3-a451-005056967662_2",
"level": 2,
"shape": "box",
"label": "821943 (HALB)\nF\u00fchrungskasten komplett\n0 | M2781 - TK-PF",
}, {
"id": "c22dda1e-fc84-11e3-a451-005056967662_2",
"level": 2,
"shape": "box",
"label": "821944 (HALB)\nF\u00fchrungskasten komplett\n0 | M2781 - TK-PF",
}, {
"id": "a05fcb83-29c6-11e4-9203-005056967662_2",
"level": 2,
"shape": "box",
"label": "828431 (HALB)\nF\u00fchrungskasten komplett",
}, {
"id": "eb9b67b7-6e3f-11e4-9203-005056967662_2",
"level": 2,
"shape": "box",
"label": "829382 A (HALB)\nF\u00fchrungskasten komplett\n0 | M1556 - TK-PHS",
}, {
"id": "084ec1e3-e447-11e3-a03f-005056967662_3",
"level": 3,
"shape": "box",
"color": "#00ff00",
"label": "310759 C (ROH)\nSchr\u00e4gkugellager",
}],
edges: [{
"from": "59acc308-fc78-11e3-a451-005056967662_1",
"to": "a986a9ab-fc82-11e3-a451-005056967662_2"
}, {
"from": "bc5ada61-e297-11e3-a03f-005056967662_2",
"to": "084ec1e3-e447-11e3-a03f-005056967662_3"
}, {
"from": "6f8a780a-e28e-11e3-a03f-005056967662_2",
"to": "084ec1e3-e447-11e3-a03f-005056967662_3"
}, {
"from": "49bb72b1-e2b2-11e3-a03f-005056967662_2",
"to": "084ec1e3-e447-11e3-a03f-005056967662_3"
}, {
"from": "e7bf7c7e-e28e-11e3-a03f-005056967662_2",
"to": "084ec1e3-e447-11e3-a03f-005056967662_3"
}, {
"from": "623e8501-e2e2-11e3-a03f-005056967662_2",
"to": "084ec1e3-e447-11e3-a03f-005056967662_3"
}, {
"from": "e7c6dcdf-e28e-11e3-a03f-005056967662_2",
"to": "084ec1e3-e447-11e3-a03f-005056967662_3"
}, {
"from": "623edd04-e2e2-11e3-a03f-005056967662_2",
"to": "084ec1e3-e447-11e3-a03f-005056967662_3"
}, {
"from": "a986a9ab-fc82-11e3-a451-005056967662_2",
"to": "084ec1e3-e447-11e3-a03f-005056967662_3"
}, {
"from": "c22dda1e-fc84-11e3-a451-005056967662_2",
"to": "084ec1e3-e447-11e3-a03f-005056967662_3"
}, {
"from": "a05fcb83-29c6-11e4-9203-005056967662_2",
"to": "084ec1e3-e447-11e3-a03f-005056967662_3"
}, {
"from": "eb9b67b7-6e3f-11e4-9203-005056967662_2",
"to": "084ec1e3-e447-11e3-a03f-005056967662_3"
}]
}; };
var ids = {};
var network = new vis.Network(container, data, options);
allNodes = nodesDataset.get({
returnType: "Object"
});
allEdges = edgesDataset.get({
returnType: "Object"
});
showPath();
showPath();
function getNodeId(nodeLabels) {
var resultArray = [];
var unmatchedNodesLabel = [];
for (var i = 0; i < nodeLabels.length; i++) {
for (var nodeId in allNodes) {
var matchflag = false;
if (nodeLabels[i].toUpperCase() === allNodes[nodeId].label.toUpperCase()) {
resultArray.push(allNodes[nodeId].id);
matchflag = true;
break;
}
}
if (!matchflag) {
console.log('An unmatched nodeLabel exists!' + nodeLabels[i]);
}
}
return resultArray;
for ( var i = 0; i < data.nodes.length; i++) {
ids[data.nodes[i].id] = i;
data.nodes[i].id = i
data.nodes[i].label = i
} }
function getLinkedEdge(fromNodeId, toNodeId) {
var result;
if (fromNodeId) {
var allLinkedEdges = network.getConnectedEdges(fromNodeId);
for (var i = 0; i < allLinkedEdges.length; i++) {
var linkedNodes = network.getConnectedNodes(allLinkedEdges[i]);
for (var j = 0; j < linkedNodes.length; j++) {
if (toNodeId === linkedNodes[j]) {
result = allLinkedEdges[i];
if (j == 0) {
if (allEdges[allLinkedEdges[i]].arrows === undefined) {
allEdges[allLinkedEdges[i]].arrows = 'from';
} else {
allEdges[allLinkedEdges[i]].arrows = 'to;from';
}
} else {
if (allEdges[allLinkedEdges[i]].arrows === undefined) {
allEdges[allLinkedEdges[i]].arrows = 'to';
} else {
allEdges[allLinkedEdges[i]].arrows = 'to;from';
}
}
break;
}
}
}
}
return result;
for ( var i = 0; i < data.edges.length; i++) {
data.edges[i].from = ids[data.edges[i].from]
data.edges[i].to = ids[data.edges[i].to]
} }
var options = {
function updateNodesEdges() {
// update nodes and edges
var updateNodes = [];
var updateEdges = [];
for (var nodeId in allNodes) {
if (allNodes.hasOwnProperty(nodeId)) {
updateNodes.push(allNodes[nodeId]);
}
}
layout: {
hierarchical: {
//enabled: true,
for (var edgeId in allEdges) {
if (allEdges.hasOwnProperty(edgeId)) {
updateEdges.push(allEdges[edgeId]);
}
}
nodeSpacing: 100,
nodesDataset.update(updateNodes);
edgesDataset.update(updateEdges);
}
//blockShifting: false,
//edgeMinimization: false,
function showPath() {
// Test values
var pathData = 'test1,test3,test4,test5';
var nodesOrder = pathData.split(',');
direction: 'UD',
sortMethod: 'directed'
var orderedNodeId = getNodeId(nodesOrder);
},
if (orderedNodeId.length > 0) {
pathActive = true;
},
// mark all nodes as hard to read
for (var nodeId in allNodes) {
allNodes[nodeId].color = 'rgba(200,200,200,0.5)';
}
interaction: {
dragNodes: true,
hover: true
},
// mark all edges as hard to read
for (var edgeId in allEdges) {
allEdges[edgeId].color = 'rgba(200,200,200,0.5)';
}
physics: {
enabled: false
}
// the selected nodes and edges get its own color and its label back.
for (var i = 0; i < orderedNodeId.length; i++) {
allNodes[orderedNodeId[i]].color = undefined;
};
var network = new vis.Network(container, data, options);
// linked edge
if (i < orderedNodeId.length) {
var linkedEdge = getLinkedEdge(orderedNodeId[i], orderedNodeId[i + 1]);
network.on('click', function(params) {
if (params.nodes !== undefined) {
var firstNode = params.nodes[0];
if (firstNode !== undefined) {
var splitted = firstNode.split('_');
if (linkedEdge) {
allEdges[linkedEdge].color = undefined;
}
}
Lisp.request.get('/dataStore/article/detail/id/' + splitted[0]);
} }
updateNodesEdges();
}
// reset all nodes
for (var nodeId in allNodes) {
allNodes[nodeId].color = undefined;
} }
});
// reset all edges <--- it does NOT work! although edge's color undfined!
for (var edgeId in allEdges) {
allEdges[edgeId].color = null;
allEdges[edgeId].arrows = null;
}
updateNodesEdges();
}
</script> </script>
</body> </body>

Loading…
Cancel
Save