Browse Source

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

flowchartTest
jos 9 years ago
parent
commit
520971d86f
24 changed files with 1907 additions and 1736 deletions
  1. +22
    -0
      HISTORY.md
  2. +1
    -0
      dist/vis.css
  3. +1684
    -1633
      dist/vis.js
  4. +1
    -1
      dist/vis.min.css
  5. +13
    -4
      docs/network/index.html
  6. +2
    -0
      docs/network/interaction.html
  7. +6
    -4
      lib/network/Network.js
  8. +1
    -0
      lib/network/css/network-tooltip.css
  9. +21
    -34
      lib/network/modules/Clustering.js
  10. +5
    -2
      lib/network/modules/EdgesHandler.js
  11. +3
    -3
      lib/network/modules/InteractionHandler.js
  12. +28
    -13
      lib/network/modules/LayoutEngine.js
  13. +7
    -8
      lib/network/modules/ManipulationSystem.js
  14. +6
    -2
      lib/network/modules/NodesHandler.js
  15. +5
    -3
      lib/network/modules/components/Edge.js
  16. +0
    -3
      lib/network/modules/components/NavigationHandler.js
  17. +13
    -5
      lib/network/modules/components/edges/BezierEdgeDynamic.js
  18. +0
    -3
      lib/network/modules/components/edges/BezierEdgeStatic.js
  19. +0
    -3
      lib/network/modules/components/edges/StraightEdge.js
  20. +8
    -5
      lib/network/modules/components/edges/util/EdgeBase.js
  21. +19
    -2
      lib/network/modules/components/nodes/util/CircleImageBase.js
  22. +4
    -1
      lib/shared/Configurator.js
  23. +9
    -3
      lib/util.js
  24. +49
    -4
      test/networkTest.html

+ 22
- 0
HISTORY.md View File

@ -1,6 +1,28 @@
# vis.js history # vis.js history
http://visjs.org http://visjs.org
## UNRELEASED, version 4.0.1
### Network
- Fixed #866, manipulation can now be set to false without crashing.
- Fixed #860, edit node mode now works as it should.
- Fixed #859, images now resize again when they are loaded.
- Fixed dynamic edges not correctly handling non-existent nodes.
- Accepted pull from @killerDJO for fixing selected and hover colors for edges.
- Fixed bug with rightmouse button, scroll center and popup positions using the wrong coordinates.
- Fixed click to use.
- Fixed getConnectedEdges method.
- Fixed clustering bug.
- Added getNodesInCluster method.
- Renamed editNodeMode to editNode, editNodeMode now give a deprication log message.
- Added multiselect to the docs.
- Removed depricated dynamic entree, allow any smooth curve style for hierarchical layout.
### Graph2d & Timeline
- Fixed #858, removed usage of deprictated unsubscribe from dataset.
## not yet released, version 4.0.1-SNAPSHOT ## not yet released, version 4.0.1-SNAPSHOT

+ 1
- 0
dist/vis.css View File

@ -825,6 +825,7 @@ div.vis-network-tooltip {
border: 1px solid #808074; border: 1px solid #808074;
box-shadow: 3px 3px 10px rgba(0, 0, 0, 0.2); box-shadow: 3px 3px 10px rgba(0, 0, 0, 0.2);
pointer-events: none;
} }
div.vis-network-configuration { div.vis-network-configuration {
position:relative; position:relative;

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


+ 1
- 1
dist/vis.min.css
File diff suppressed because it is too large
View File


+ 13
- 4
docs/network/index.html View File

@ -622,6 +622,15 @@ var locales = {
<td class="midMethods">Returns: Boolean</td> <td class="midMethods">Returns: Boolean</td>
<td>Returns true if the node whose ID has been supplied is a cluster.</td> <td>Returns true if the node whose ID has been supplied is a cluster.</td>
</tr> </tr>
<tr class="collapsible toggle" onclick="toggleTable('methodTable','getNodesInCluster', this);">
<td colspan="2"><span parent="getNodesInCluster" class="right-caret"></span> getNodesInCluster(
<code>String clusterNodeId</code>)
</tr>
<tr class="hidden" parent="getNodesInCluster">
<td class="midMethods">Returns: Array</td>
<td>Returns an array of all nodeIds of the nodes that would be released if you open the cluster.
</td>
</tr>
<tr class="collapsible toggle" onclick="toggleTable('methodTable','openCluster', this);"> <tr class="collapsible toggle" onclick="toggleTable('methodTable','openCluster', this);">
<td colspan="2"><span parent="openCluster" class="right-caret"></span> openCluster( <td colspan="2"><span parent="openCluster" class="right-caret"></span> openCluster(
<code>String nodeId</code>) <code>String nodeId</code>)
@ -681,12 +690,12 @@ var locales = {
<code>enabled</code> to false. <code>enabled</code> to false.
</td> </td>
</tr> </tr>
<tr class="collapsible toggle" onclick="toggleTable('methodTable','editNodeMode', this);">
<td colspan="2"><span parent="editNodeMode" class="right-caret"></span> editNodeMode()</td>
<tr class="collapsible toggle" onclick="toggleTable('methodTable','editNode', this);">
<td colspan="2"><span parent="editNode" class="right-caret"></span> editNode()</td>
</tr> </tr>
<tr class="hidden" parent="editNodeMode">
<tr class="hidden" parent="editNode">
<td class="midMethods">Returns: none</td> <td class="midMethods">Returns: none</td>
<td>Go into editNode mode. The explaination from <code>addNodeMode</code> applies here as well.</td>
<td>Edit the selected node. The explaination from <code>addNodeMode</code> applies here as well.</td>
</tr> </tr>
<tr class="collapsible toggle" onclick="toggleTable('methodTable','addEdgeMode', this);"> <tr class="collapsible toggle" onclick="toggleTable('methodTable','addEdgeMode', this);">
<td colspan="2"><span parent="addEdgeMode" class="right-caret"></span> addEdgeMode()</td> <td colspan="2"><span parent="addEdgeMode" class="right-caret"></span> addEdgeMode()</td>

+ 2
- 0
docs/network/interaction.html View File

@ -91,6 +91,7 @@ var options = {
speed: {x: 10, y: 10, zoom: 0.02}, speed: {x: 10, y: 10, zoom: 0.02},
bindToWindow: true bindToWindow: true
}, },
multiselect: false,
navigationButtons: false, navigationButtons: false,
selectable: true, selectable: true,
selectConnectedEdges: true, selectConnectedEdges: true,
@ -127,6 +128,7 @@ network.setOptions(options);
<tr parent="keyboard" class="hidden"><td class="indent">keyboard.speed.y</td> <td>Number</td> <td><code>1</code></td> <td>The speed at which the view moves in the y direction on pressing a key or pressing a navigation button.</td></tr> <tr parent="keyboard" class="hidden"><td class="indent">keyboard.speed.y</td> <td>Number</td> <td><code>1</code></td> <td>The speed at which the view moves in the y direction on pressing a key or pressing a navigation button.</td></tr>
<tr parent="keyboard" class="hidden"><td class="indent">keyboard.speed.zoom</td> <td>Number</td> <td><code>0.02</code></td> <td>The speed at which the view zooms in or out pressing a key or pressing a navigation button.</td></tr> <tr parent="keyboard" class="hidden"><td class="indent">keyboard.speed.zoom</td> <td>Number</td> <td><code>0.02</code></td> <td>The speed at which the view zooms in or out pressing a key or pressing a navigation button.</td></tr>
<tr parent="keyboard" class="hidden"><td class="indent">keyboard.bindToWindow</td> <td>Boolean</td> <td><code>true</code></td> <td>When binding the keyboard shortcuts to the window, they will work regardless of which DOM object has the focus. If you have multiple networks on your page, you could set this to false, making sure the keyboard shortcuts only work on the network that has the focus.</td></tr> <tr parent="keyboard" class="hidden"><td class="indent">keyboard.bindToWindow</td> <td>Boolean</td> <td><code>true</code></td> <td>When binding the keyboard shortcuts to the window, they will work regardless of which DOM object has the focus. If you have multiple networks on your page, you could set this to false, making sure the keyboard shortcuts only work on the network that has the focus.</td></tr>
<tr><td>multiselect</td> <td>Boolean</td> <td><code>false</code></td> <td>When true, a longheld click (or touch) as well as a control-click will add to the selection.</td></tr>
<tr><td>navigationButtons</td> <td>Boolean</td> <td><code>false</code></td> <td>When true, navigation buttons are drawn on the network canvas. These are HTML buttons and can be completely customized using CSS.</td></tr> <tr><td>navigationButtons</td> <td>Boolean</td> <td><code>false</code></td> <td>When true, navigation buttons are drawn on the network canvas. These are HTML buttons and can be completely customized using CSS.</td></tr>
<tr><td>selectable</td> <td>Boolean</td><td><code>true</code></td><td>When true, the nodes and edges can be selected by the user.</td></tr> <tr><td>selectable</td> <td>Boolean</td><td><code>true</code></td><td>When true, the nodes and edges can be selected by the user.</td></tr>
<tr><td>selectConnectedEdges</td> <td>Boolean</td><td><code>true</code></td><td>When true, on selecting a node, its connecting edges are highlighted.</td></tr> <tr><td>selectConnectedEdges</td> <td>Boolean</td><td><code>true</code></td><td>When true, on selecting a node, its connecting edges are highlighted.</td></tr>

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

@ -204,8 +204,8 @@ Network.prototype.setOptions = function (options) {
if (options.clickToUse !== undefined) { if (options.clickToUse !== undefined) {
if (options.clickToUse === true) { if (options.clickToUse === true) {
if (this.activator === undefined) { if (this.activator === undefined) {
this.activator = new Activator(this.frame);
this.activator.on('change', this._createKeyBinds.bind(this));
this.activator = new Activator(this.canvas.frame);
this.activator.on('change', () => {this.body.emitter.emit("activate")});
} }
} }
else { else {
@ -435,6 +435,7 @@ Network.prototype.findNode = function() {return this.clustering.findN
Network.prototype.isCluster = function() {return this.clustering.isCluster.apply(this.clustering,arguments);}; Network.prototype.isCluster = function() {return this.clustering.isCluster.apply(this.clustering,arguments);};
Network.prototype.openCluster = function() {return this.clustering.openCluster.apply(this.clustering,arguments);}; Network.prototype.openCluster = function() {return this.clustering.openCluster.apply(this.clustering,arguments);};
Network.prototype.cluster = function() {return this.clustering.cluster.apply(this.clustering,arguments);}; Network.prototype.cluster = function() {return this.clustering.cluster.apply(this.clustering,arguments);};
Network.prototype.getNodesInCluster = function() {return this.clustering.getNodesInCluster.apply(this.clustering,arguments);};
Network.prototype.clusterByConnection = function() {return this.clustering.clusterByConnection.apply(this.clustering,arguments);}; Network.prototype.clusterByConnection = function() {return this.clustering.clusterByConnection.apply(this.clustering,arguments);};
Network.prototype.clusterByHubsize = function() {return this.clustering.clusterByHubsize.apply(this.clustering,arguments);}; Network.prototype.clusterByHubsize = function() {return this.clustering.clusterByHubsize.apply(this.clustering,arguments);};
Network.prototype.clusterOutliers = function() {return this.clustering.clusterOutliers.apply(this.clustering,arguments);}; Network.prototype.clusterOutliers = function() {return this.clustering.clusterOutliers.apply(this.clustering,arguments);};
@ -442,7 +443,8 @@ Network.prototype.getSeed = function() {return this.layoutEngine.get
Network.prototype.enableEditMode = function() {return this.manipulation.enableEditMode.apply(this.manipulation,arguments);}; Network.prototype.enableEditMode = function() {return this.manipulation.enableEditMode.apply(this.manipulation,arguments);};
Network.prototype.disableEditMode = function() {return this.manipulation.disableEditMode.apply(this.manipulation,arguments);}; Network.prototype.disableEditMode = function() {return this.manipulation.disableEditMode.apply(this.manipulation,arguments);};
Network.prototype.addNodeMode = function() {return this.manipulation.addNodeMode.apply(this.manipulation,arguments);}; Network.prototype.addNodeMode = function() {return this.manipulation.addNodeMode.apply(this.manipulation,arguments);};
Network.prototype.editNodeMode = function() {return this.manipulation.editNodeMode.apply(this.manipulation,arguments);};
Network.prototype.editNode = function() {return this.manipulation.editNode.apply(this.manipulation,arguments);};
Network.prototype.editNodeMode = function() {console.log("Depricated: Please use editNode instead of editNodeMode."); return this.manipulation.editNode.apply(this.manipulation,arguments);};
Network.prototype.addEdgeMode = function() {return this.manipulation.addEdgeMode.apply(this.manipulation,arguments);}; Network.prototype.addEdgeMode = function() {return this.manipulation.addEdgeMode.apply(this.manipulation,arguments);};
Network.prototype.editEdgeMode = function() {return this.manipulation.editEdgeMode.apply(this.manipulation,arguments);}; Network.prototype.editEdgeMode = function() {return this.manipulation.editEdgeMode.apply(this.manipulation,arguments);};
Network.prototype.deleteSelected = function() {return this.manipulation.deleteSelected.apply(this.manipulation,arguments);}; Network.prototype.deleteSelected = function() {return this.manipulation.deleteSelected.apply(this.manipulation,arguments);};
@ -457,7 +459,7 @@ Network.prototype.getConnectedNodes = function(objectId) {
return this.edgesHandler.getConnectedNodes.apply(this.edgesHandler,arguments); return this.edgesHandler.getConnectedNodes.apply(this.edgesHandler,arguments);
} }
}; };
Network.prototype.getEdges = function() {return this.nodesHandler.getEdges.apply(this.nodesHandler,arguments);};
Network.prototype.getConnectedEdges = function() {return this.nodesHandler.getConnectedEdges.apply(this.nodesHandler,arguments);};
Network.prototype.startSimulation = function() {return this.physics.startSimulation.apply(this.physics,arguments);}; Network.prototype.startSimulation = function() {return this.physics.startSimulation.apply(this.physics,arguments);};
Network.prototype.stopSimulation = function() {return this.physics.stopSimulation.apply(this.physics,arguments);}; Network.prototype.stopSimulation = function() {return this.physics.stopSimulation.apply(this.physics,arguments);};
Network.prototype.stabilize = function() {return this.physics.stabilize.apply(this.physics,arguments);}; Network.prototype.stabilize = function() {return this.physics.stabilize.apply(this.physics,arguments);};

+ 1
- 0
lib/network/css/network-tooltip.css View File

@ -15,4 +15,5 @@ div.vis-network-tooltip {
border: 1px solid #808074; border: 1px solid #808074;
box-shadow: 3px 3px 10px rgba(0, 0, 0, 0.2); box-shadow: 3px 3px 10px rgba(0, 0, 0, 0.2);
pointer-events: none;
} }

+ 21
- 34
lib/network/modules/Clustering.js View File

@ -498,7 +498,6 @@ class ClusterEngine {
delete this.body.edges[edgeId]; delete this.body.edges[edgeId];
} }
else { else {
// one of the nodes connected to this edge is in a cluster. We give the edge to that cluster so it will be released when that cluster is opened. // one of the nodes connected to this edge is in a cluster. We give the edge to that cluster so it will be released when that cluster is opened.
if (this.clusteredNodes[edge.fromId] !== undefined || this.clusteredNodes[edge.toId] !== undefined) { if (this.clusteredNodes[edge.fromId] !== undefined || this.clusteredNodes[edge.toId] !== undefined) {
let fromId, toId; let fromId, toId;
@ -507,17 +506,17 @@ class ClusterEngine {
let clusterNode = this.body.nodes[clusterId]; let clusterNode = this.body.nodes[clusterId];
clusterNode.containedEdges[edgeId] = edge; clusterNode.containedEdges[edgeId] = edge;
// if both from and to nodes are visible, we create a new temporary edge
if (edge.from.options.hidden !== true && edge.to.options.hidden !== true) {
if (this.clusteredNodes[edge.fromId] !== undefined) {
fromId = clusterId;
toId = edge.toId;
}
else {
fromId = edge.fromId;
toId = clusterId;
}
if (this.clusteredNodes[edge.fromId] !== undefined) {
fromId = clusterId;
toId = edge.toId;
}
else {
fromId = edge.fromId;
toId = clusterId;
}
// if both from and to nodes are visible, we create a new temporary edge
if (this.body.nodes[fromId].options.hidden !== true && this.body.nodes[toId].options.hidden !== true) {
let clonedOptions = this._cloneOptions(edge, 'edge'); let clonedOptions = this._cloneOptions(edge, 'edge');
let id = 'clusterEdge:' + util.randomUUID(); let id = 'clusterEdge:' + util.randomUUID();
util.deepExtend(clonedOptions, clusterNode.clusterEdgeProperties); util.deepExtend(clonedOptions, clusterNode.clusterEdgeProperties);
@ -553,30 +552,18 @@ class ClusterEngine {
} }
} }
/**
* Connect an edge that was previously contained from cluster A to cluster B if the node that it was originally connected to
* is currently residing in cluster B
* @param edge
* @param nodeId
* @param from
* @private
*/
_connectEdge(edge, nodeId, from) {
let clusterStack = this.findNode(nodeId);
if (from === true) {
edge.from = clusterStack[clusterStack.length - 1];
edge.fromId = clusterStack[clusterStack.length - 1].id;
clusterStack.pop();
edge.fromArray = clusterStack;
}
else {
edge.to = clusterStack[clusterStack.length - 1];
edge.toId = clusterStack[clusterStack.length - 1].id;
clusterStack.pop();
edge.toArray = clusterStack;
getNodesInCluster(clusterId) {
let nodesArray = []
if (this.isCluster(clusterId) === true) {
let containedNodes = this.body.nodes[clusterId].containedNodes;
for (let nodeId in containedNodes) {
if (containedNodes.hasOwnProperty(nodeId)) {
nodesArray.push(nodeId)
}
}
} }
edge.connect();
return nodesArray;
} }
/** /**

+ 5
- 2
lib/network/modules/EdgesHandler.js View File

@ -95,6 +95,9 @@ class EdgesHandler {
bindEventListeners() { bindEventListeners() {
// this allows external modules to force all dynamic curves to turn static. // this allows external modules to force all dynamic curves to turn static.
this.body.emitter.on("_forceDisableDynamicCurves", (type) => { this.body.emitter.on("_forceDisableDynamicCurves", (type) => {
if (type === 'dynamic') {
type = 'continuous';
}
let emitChange = false; let emitChange = false;
for (let edgeId in this.body.edges) { for (let edgeId in this.body.edges) {
if (this.body.edges.hasOwnProperty(edgeId)) { if (this.body.edges.hasOwnProperty(edgeId)) {
@ -106,12 +109,12 @@ class EdgesHandler {
if (edgeData !== undefined) { if (edgeData !== undefined) {
let edgeOptions = edgeData.smooth; let edgeOptions = edgeData.smooth;
if (edgeOptions !== undefined) { if (edgeOptions !== undefined) {
if (edgeOptions.enabled === true && edgeOptions.dynamic === true) {
if (edgeOptions.enabled === true && edgeOptions.type === 'dynamic') {
if (type === undefined) { if (type === undefined) {
edge.setOptions({smooth: false}); edge.setOptions({smooth: false});
} }
else { else {
edge.setOptions({smooth: {dynamic: false, type: type}});
edge.setOptions({smooth: {type: type}});
} }
emitChange = true; emitChange = true;
} }

+ 3
- 3
lib/network/modules/InteractionHandler.js View File

@ -163,7 +163,7 @@ class InteractionHandler {
} }
onContext(event) { onContext(event) {
let pointer = this.getPointer({x:event.pageX, y:event.pageY});
let pointer = this.getPointer({x:event.clientX, y:event.clientY});
this.selectionHandler._generateClickEvent('oncontext', event, pointer); this.selectionHandler._generateClickEvent('oncontext', event, pointer);
} }
@ -448,7 +448,7 @@ class InteractionHandler {
scale *= (1 + zoom); scale *= (1 + zoom);
// calculate the pointer location // calculate the pointer location
let pointer = this.getPointer({x:event.pageX, y:event.pageY});
let pointer = this.getPointer({x:event.clientX, y:event.clientY});
// apply the new scale // apply the new scale
this.zoom(scale, pointer); this.zoom(scale, pointer);
@ -465,7 +465,7 @@ class InteractionHandler {
* @private * @private
*/ */
onMouseMove(event) { onMouseMove(event) {
let pointer = this.getPointer({x:event.pageX, y:event.pageY});
let pointer = this.getPointer({x:event.clientX, y:event.clientY});
let popupVisible = false; let popupVisible = false;
// check if the previously selected node is still selected // check if the previously selected node is still selected

+ 28
- 13
lib/network/modules/LayoutEngine.js View File

@ -1,3 +1,5 @@
'use strict'
var util = require('../../util'); var util = require('../../util');
class LayoutEngine { class LayoutEngine {
@ -78,14 +80,14 @@ class LayoutEngine {
allOptions.physics = {solver: 'hierarchicalRepulsion'}; allOptions.physics = {solver: 'hierarchicalRepulsion'};
this.optionsBackup.physics = {solver:'barnesHut'}; this.optionsBackup.physics = {solver:'barnesHut'};
} }
else if (typeof options.physics === 'object') {
else if (typeof allOptions.physics === 'object') {
this.optionsBackup.physics = {solver:'barnesHut'}; this.optionsBackup.physics = {solver:'barnesHut'};
if (options.physics.solver !== undefined) {
this.optionsBackup.physics = {solver:options.physics.solver};
if (allOptions.physics.solver !== undefined) {
this.optionsBackup.physics = {solver:allOptions.physics.solver};
} }
allOptions.physics['solver'] = 'hierarchicalRepulsion'; allOptions.physics['solver'] = 'hierarchicalRepulsion';
} }
else if (options.physics !== false) {
else if (allOptions.physics !== false) {
this.optionsBackup.physics = {solver:'barnesHut'}; this.optionsBackup.physics = {solver:'barnesHut'};
allOptions.physics['solver'] = 'hierarchicalRepulsion'; allOptions.physics['solver'] = 'hierarchicalRepulsion';
} }
@ -98,21 +100,34 @@ class LayoutEngine {
// disable smooth curves if nothing is defined. If smooth curves have been turned on, turn them into static smooth curves. // disable smooth curves if nothing is defined. If smooth curves have been turned on, turn them into static smooth curves.
if (allOptions.edges === undefined) { if (allOptions.edges === undefined) {
this.optionsBackup.edges = {smooth:true, dynamic:true};
this.optionsBackup.edges = {smooth:{enabled:true, type:'dynamic'}};
allOptions.edges = {smooth: false}; allOptions.edges = {smooth: false};
} }
else if (allOptions.edges.smooth === undefined) { else if (allOptions.edges.smooth === undefined) {
this.optionsBackup.edges = {smooth:true, dynamic:true};
this.optionsBackup.edges = {smooth:{enabled:true, type:'dynamic'}};
allOptions.edges.smooth = false; allOptions.edges.smooth = false;
} }
else { else {
if (typeof allOptions.edges.smooth === 'boolean') { if (typeof allOptions.edges.smooth === 'boolean') {
this.optionsBackup.edges = {smooth:allOptions.edges.smooth, dynamic:true};
allOptions.edges.smooth = {enabled: allOptions.edges.smooth, dynamic: false, type:type}
this.optionsBackup.edges = {smooth:allOptions.edges.smooth};
allOptions.edges.smooth = {enabled: allOptions.edges.smooth, type:type}
} }
else { else {
this.optionsBackup.edges = {smooth: allOptions.edges.smooth.enabled === undefined ? true : allOptions.edges.smooth.enabled, dynamic:true};
allOptions.edges.smooth = {enabled: allOptions.edges.smooth.enabled === undefined ? true : allOptions.edges.smooth.enabled, dynamic: false, type:type}
// allow custom types except for dynamic
if (allOptions.edges.smooth.type !== undefined && allOptions.edges.smooth.type !== 'dynamic') {
type = allOptions.edges.smooth.type;
}
this.optionsBackup.edges = {
smooth: allOptions.edges.smooth.enabled === undefined ? true : allOptions.edges.smooth.enabled,
type:allOptions.edges.smooth.type === undefined ? 'dynamic' : allOptions.edges.smooth.type,
roundness: allOptions.edges.smooth.roundness === undefined ? 0.5 : allOptions.edges.smooth.roundness
};
allOptions.edges.smooth = {
enabled: allOptions.edges.smooth.enabled === undefined ? true : allOptions.edges.smooth.enabled,
type:type,
roundness: allOptions.edges.smooth.roundness === undefined ? 0.5 : allOptions.edges.smooth.roundness
}
} }
} }
@ -316,7 +331,7 @@ class LayoutEngine {
if (this.body.nodes.hasOwnProperty(nodeId)) { if (this.body.nodes.hasOwnProperty(nodeId)) {
node = this.body.nodes[nodeId]; node = this.body.nodes[nodeId];
if (node.edges.length === hubSize) { if (node.edges.length === hubSize) {
this._setLevel(0, node);
this._setLevelByHubsize(0, node);
} }
} }
} }
@ -332,7 +347,7 @@ class LayoutEngine {
* @param parentId * @param parentId
* @private * @private
*/ */
_setLevel(level, node) {
_setLevelByHubsize(level, node) {
if (this.hierarchicalLevels[node.id] !== undefined) if (this.hierarchicalLevels[node.id] !== undefined)
return; return;
@ -345,7 +360,7 @@ class LayoutEngine {
else { else {
childNode = node.edges[i].to; childNode = node.edges[i].to;
} }
this._setLevel(level + 1, childNode);
this._setLevelByHubsize(level + 1, childNode);
} }
} }

+ 7
- 8
lib/network/modules/ManipulationSystem.js View File

@ -253,7 +253,7 @@ class ManipulationSystem {
* *
* @private * @private
*/ */
editNodeMode() {
editNode() {
// when using the gui, enable edit mode if it wasnt already. // when using the gui, enable edit mode if it wasnt already.
if (this.editMode !== true) { if (this.editMode !== true) {
this.enableEditMode(); this.enableEditMode();
@ -272,7 +272,7 @@ class ManipulationSystem {
if (this.options.editNode.length === 2) { if (this.options.editNode.length === 2) {
this.options.editNode(data, (finalizedData) => { this.options.editNode(data, (finalizedData) => {
if (finalizedData !== null && finalizedData !== undefined && this.inMode === 'delete') { // if for whatever reason the mode has changes (due to dataset change) disregard the callback) {
if (finalizedData !== null && finalizedData !== undefined && this.inMode === 'editNode') { // if for whatever reason the mode has changes (due to dataset change) disregard the callback) {
this.body.data.nodes.update(finalizedData); this.body.data.nodes.update(finalizedData);
this.showManipulatorToolbar(); this.showManipulatorToolbar();
} }
@ -632,9 +632,9 @@ class ManipulationSystem {
util.recursiveDOMDelete(this.closeDiv); util.recursiveDOMDelete(this.closeDiv);
// remove the manipulation divs // remove the manipulation divs
this.canvas.frame.removeChild(this.manipulationDiv);
this.canvas.frame.removeChild(this.editModeDiv);
this.canvas.frame.removeChild(this.closeDiv);
if (this.manipulationDiv) {this.canvas.frame.removeChild(this.manipulationDiv);}
if (this.editModeDiv) {this.canvas.frame.removeChild(this.editModeDiv);}
if (this.closeDiv) {this.canvas.frame.removeChild(this.manipulationDiv);}
// set the references to undefined // set the references to undefined
this.manipulationDiv = undefined; this.manipulationDiv = undefined;
@ -669,9 +669,9 @@ class ManipulationSystem {
} }
_createEditNodeButton(locale) { _createEditNodeButton(locale) {
let button = this._createButton('editNodeMode', 'vis-button vis-edit', locale['editNode'] || this.options.locales['en']['editNode']);
let button = this._createButton('editNode', 'vis-button vis-edit', locale['editNode'] || this.options.locales['en']['editNode']);
this.manipulationDiv.appendChild(button); this.manipulationDiv.appendChild(button);
this._bindHammerToDiv(button, this.editNodeMode.bind(this));
this._bindHammerToDiv(button, this.editNode.bind(this));
} }
_createEditEdgeButton(locale) { _createEditEdgeButton(locale) {
@ -946,7 +946,6 @@ class ManipulationSystem {
physics: false, physics: false,
smooth: { smooth: {
enabled: true, enabled: true,
dynamic: false,
type: 'continuous', type: 'continuous',
roundness: 0.5 roundness: 0.5
} }

+ 6
- 2
lib/network/modules/NodesHandler.js View File

@ -400,7 +400,7 @@ class NodesHandler {
* @param nodeId * @param nodeId
* @returns {*} * @returns {*}
*/ */
getEdges(nodeId) {
getConnectedEdges(nodeId) {
let edgeList = []; let edgeList = [];
if (this.body.nodes[nodeId] !== undefined) { if (this.body.nodes[nodeId] !== undefined) {
let node = this.body.nodes[nodeId]; let node = this.body.nodes[nodeId];
@ -408,7 +408,11 @@ class NodesHandler {
edgeList.push(node.edges[i].id) edgeList.push(node.edges[i].id)
} }
} }
return nodeList;
else {
console.log("NodeId provided for getConnectedEdges does not exist. Provided: ", nodeId)
}
console.log(edgeList)
return edgeList;
} }
} }

+ 5
- 3
lib/network/modules/components/Edge.js View File

@ -73,9 +73,6 @@ class Edge {
if (options.value !== undefined) {options.value = parseInt(options.value);} if (options.value !== undefined) {options.value = parseInt(options.value);}
// A node is connected when it has a from and to node that both exist in the network.body.nodes.
this.connect();
// update label Module // update label Module
this.updateLabelModule(); this.updateLabelModule();
@ -84,6 +81,9 @@ class Edge {
// if anything has been updates, reset the selection width and the hover width // if anything has been updates, reset the selection width and the hover width
this._setInteractionWidths(); this._setInteractionWidths();
// A node is connected when it has a from and to node that both exist in the network.body.nodes.
this.connect();
return dataChanged; return dataChanged;
} }
@ -267,6 +267,8 @@ class Edge {
this.to.detachEdge(this); this.to.detachEdge(this);
} }
} }
this.edgeType.connect();
} }

+ 0
- 3
lib/network/modules/components/NavigationHandler.js View File

@ -52,8 +52,6 @@ class NavigationHandler {
this.navigationHammers = []; this.navigationHammers = [];
} }
this._navigationReleaseOverload = function() {};
// clean up previous navigation items // clean up previous navigation items
if (this.navigationDOM && this.navigationDOM['wrapper'] && this.navigationDOM['wrapper'].parentNode) { if (this.navigationDOM && this.navigationDOM['wrapper'] && this.navigationDOM['wrapper'].parentNode) {
this.navigationDOM['wrapper'].parentNode.removeChild(this.navigationDOM['wrapper']); this.navigationDOM['wrapper'].parentNode.removeChild(this.navigationDOM['wrapper']);
@ -160,7 +158,6 @@ class NavigationHandler {
} }
if (this.options.keyboard.enabled === true) { if (this.options.keyboard.enabled === true) {
if (this.options.keyboard.bindToWindow === true) { if (this.options.keyboard.bindToWindow === true) {
this.keycharm = keycharm({container: window, preventDefault: true}); this.keycharm = keycharm({container: window, preventDefault: true});
} }

+ 13
- 5
lib/network/modules/components/edges/BezierEdgeDynamic.js View File

@ -8,17 +8,25 @@ class BezierEdgeDynamic extends BezierEdgeBase {
setOptions(options) { setOptions(options) {
this.options = options; this.options = options;
this.from = this.body.nodes[this.options.from];
this.to = this.body.nodes[this.options.to];
this.id = this.options.id; this.id = this.options.id;
this.setupSupportNode(); this.setupSupportNode();
this.connect();
}
// fix weird behaviour
if (this.from.id === this.to.id) {
connect() {
this.from = this.body.nodes[this.options.from];
this.to = this.body.nodes[this.options.to];
if (this.from === undefined || this.to === undefined) {
this.via.setOptions({physics:false}) this.via.setOptions({physics:false})
} }
else { else {
this.via.setOptions({physics:true})
// fix weird behaviour where a selfreferencing node has physics enabled
if (this.from.id === this.to.id) {
this.via.setOptions({physics: false})
}
else {
this.via.setOptions({physics: true})
}
} }
} }

+ 0
- 3
lib/network/modules/components/edges/BezierEdgeStatic.js View File

@ -5,9 +5,6 @@ class BezierEdgeStatic extends BezierEdgeBase {
super(options, body, labelModule); super(options, body, labelModule);
} }
cleanup() {
return false;
}
/** /**
* Draw a line between two nodes * Draw a line between two nodes
* @param {CanvasRenderingContext2D} ctx * @param {CanvasRenderingContext2D} ctx

+ 0
- 3
lib/network/modules/components/edges/StraightEdge.js View File

@ -5,9 +5,6 @@ class StraightEdge extends EdgeBase {
super(options, body, labelModule); super(options, body, labelModule);
} }
cleanup() {
return false;
}
/** /**
* Draw a line between two nodes * Draw a line between two nodes
* @param {CanvasRenderingContext2D} ctx * @param {CanvasRenderingContext2D} ctx

+ 8
- 5
lib/network/modules/components/edges/util/EdgeBase.js View File

@ -11,6 +11,9 @@ class EdgeBase {
this.hoverWidth = 1.5; this.hoverWidth = 1.5;
} }
connect() {}
cleanup() {return false}
setOptions(options) { setOptions(options) {
this.options = options; this.options = options;
this.from = this.body.nodes[this.options.from]; this.from = this.body.nodes[this.options.from];
@ -33,7 +36,7 @@ class EdgeBase {
*/ */
drawLine(ctx, selected, hover) { drawLine(ctx, selected, hover) {
// set style // set style
ctx.strokeStyle = this.getColor(ctx);
ctx.strokeStyle = this.getColor(ctx, selected, hover);
ctx.lineWidth = this.getLineWidth(selected, hover); ctx.lineWidth = this.getLineWidth(selected, hover);
let via = undefined; let via = undefined;
if (this.options.dashes !== false) { if (this.options.dashes !== false) {
@ -256,7 +259,7 @@ class EdgeBase {
} }
getColor(ctx) {
getColor(ctx, selected, hover) {
let colorOptions = this.options.color; let colorOptions = this.options.color;
if (colorOptions.inherit !== false) { if (colorOptions.inherit !== false) {
// when this is a loop edge, just use the 'from' method // when this is a loop edge, just use the 'from' method
@ -306,10 +309,10 @@ class EdgeBase {
this.colorDirty = false; this.colorDirty = false;
if (this.selected === true) {
if (selected === true) {
return this.color.highlight; return this.color.highlight;
} }
else if (this.hover === true) {
else if (hover === true) {
return this.color.hover; return this.color.hover;
} }
else { else {
@ -409,7 +412,7 @@ class EdgeBase {
*/ */
drawArrowHead(ctx, position, viaNode, selected, hover) { drawArrowHead(ctx, position, viaNode, selected, hover) {
// set style // set style
ctx.strokeStyle = this.getColor(ctx);
ctx.strokeStyle = this.getColor(ctx, selected, hover);
ctx.fillStyle = ctx.strokeStyle; ctx.fillStyle = ctx.strokeStyle;
ctx.lineWidth = this.getLineWidth(selected, hover); ctx.lineWidth = this.getLineWidth(selected, hover);

+ 19
- 2
lib/network/modules/components/nodes/util/CircleImageBase.js View File

@ -4,12 +4,27 @@ class CircleImageBase extends NodeBase {
constructor(options, body, labelModule) { constructor(options, body, labelModule) {
super(options, body, labelModule); super(options, body, labelModule);
this.labelOffset = 0; this.labelOffset = 0;
this.imageLoaded = false;
} }
/**
* This function resizes the image by the options size when the image has not yet loaded. If the image has loaded, we
* force the update of the size again.
*
* @private
*/
_resizeImage() { _resizeImage() {
if (!this.width || !this.height) { // undefined or 0
var width, height, ratio;
let force = false;
if (!this.imageObj.width || !this.imageObj.height) { // undefined or 0
this.imageLoaded = false;
}
else if (this.imageLoaded === false) {
this.imageLoaded = true;
force = true;
}
if (!this.width || !this.height || force === true) { // undefined or 0
var width, height, ratio;
if (this.imageObj.width && this.imageObj.height) { // not undefined or 0 if (this.imageObj.width && this.imageObj.height) { // not undefined or 0
width = 0; width = 0;
height = 0; height = 0;
@ -33,6 +48,7 @@ class CircleImageBase extends NodeBase {
this.height = height; this.height = height;
this.radius = 0.5*this.width; this.radius = 0.5*this.width;
} }
} }
_drawRawCircle(ctx, x, y, selected, hover, size) { _drawRawCircle(ctx, x, y, selected, hover, size) {
@ -59,6 +75,7 @@ class CircleImageBase extends NodeBase {
} }
_drawImageAtPosition(ctx) { _drawImageAtPosition(ctx) {
console.log(this.options.label, this.imageObj.width)
if (this.imageObj.width != 0) { if (this.imageObj.width != 0) {
// draw the image // draw the image
ctx.globalAlpha = 1.0; ctx.globalAlpha = 1.0;

+ 4
- 1
lib/shared/Configurator.js View File

@ -313,7 +313,10 @@ class Configurator {
range.step = step; range.step = step;
if (value !== undefined) { if (value !== undefined) {
if (value * 0.1 < min) {
if (value < 0 && value * 2 < min) {
range.min = value*2;
}
else if (value * 0.1 < min) {
range.min = value / 10; range.min = value / 10;
} }
if (value * 2 > max && max !== 1) { if (value * 2 > max && max !== 1) {

+ 9
- 3
lib/util.js View File

@ -17,10 +17,16 @@ exports.isNumber = function(object) {
}; };
/**
* Remove everything in the DOM object
* @param DOMobject
*/
exports.recursiveDOMDelete = function(DOMobject) { exports.recursiveDOMDelete = function(DOMobject) {
while (DOMobject.hasChildNodes() == true) {
exports.recursiveDOMDelete(DOMobject.firstChild);
DOMobject.removeChild(DOMobject.firstChild);
if (DOMobject) {
while (DOMobject.hasChildNodes() === true) {
exports.recursiveDOMDelete(DOMobject.firstChild);
DOMobject.removeChild(DOMobject.firstChild);
}
} }
}; };

+ 49
- 4
test/networkTest.html
File diff suppressed because it is too large
View File


Loading…
Cancel
Save