Browse Source

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

Conflicts:
	HISTORY.md
	dist/vis.js
flowchartTest
Alex de Mulder 9 years ago
parent
commit
5dffc93de1
15 changed files with 119 additions and 118 deletions
  1. +9
    -1
      HISTORY.md
  2. +9
    -0
      docs/network/index.html
  3. +2
    -0
      docs/network/interaction.html
  4. +3
    -2
      docs/timeline/index.html
  5. +2
    -2
      examples/timeline/other/customTimeBars.html
  6. +5
    -4
      lib/network/Network.js
  7. +21
    -34
      lib/network/modules/Clustering.js
  8. +5
    -2
      lib/network/modules/EdgesHandler.js
  9. +22
    -9
      lib/network/modules/LayoutEngine.js
  10. +0
    -1
      lib/network/modules/ManipulationSystem.js
  11. +6
    -2
      lib/network/modules/NodesHandler.js
  12. +0
    -3
      lib/network/modules/components/NavigationHandler.js
  13. +4
    -1
      lib/shared/Configurator.js
  14. +3
    -3
      lib/timeline/component/CustomTime.js
  15. +28
    -54
      test/networkTest.html

+ 9
- 1
HISTORY.md View File

@ -11,11 +11,19 @@ http://visjs.org
- 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.
- Fixed bug with the moveTo and getViewPosition methods.
### Graph2d & Timeline
- Fixed #858, removed usage of deprictated unsubscribe from dataset.
- Fixed #858, #872, fixed usage of deprecated `unsubscribe` from DataSet.
- Fixed #869: add className with id to custom time bars
## 2015-05-22, version 4.0.0

+ 9
- 0
docs/network/index.html View File

@ -622,6 +622,15 @@ var locales = {
<td class="midMethods">Returns: Boolean</td>
<td>Returns true if the node whose ID has been supplied is a cluster.</td>
</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);">
<td colspan="2"><span parent="openCluster" class="right-caret"></span> openCluster(
<code>String nodeId</code>)

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

@ -91,6 +91,7 @@ var options = {
speed: {x: 10, y: 10, zoom: 0.02},
bindToWindow: true
},
multiselect: false,
navigationButtons: false,
selectable: 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.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><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>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>

+ 3
- 2
docs/timeline/index.html View File

@ -935,8 +935,9 @@ function (option, path) {
<td>
Add new vertical bar representing a custom time that can be dragged by the user.
Parameter <code>time</code> can be a Date, Number, or String, and is <code>new Date()</code> by default.
Parameter <code>id</code> can be Number or String and is <code>undefined</code> by default.<br>
Returns id of the created bar.
Parameter <code>id</code> can be Number or String and is <code>undefined</code> by default.
The <code>id</code>code> is added as CSS class name of the custom time bar, allowing to style multiple time bars differently.
The method returns id of the created bar.
</td>
</tr>

+ 2
- 2
examples/timeline/other/customTimeBars.html View File

@ -25,7 +25,7 @@
</p>
<p>
<input type="button" id="remove" value="Remove custom vertical bar">
<input type="text" id="barIndex" value="1" placeholder="custom bar ID">
<input type="text" id="barIndex" value="t1" placeholder="custom bar ID">
</p>
<p>
<code><strong>timechange</strong></code> event, index: <span id="timechangeBar"></span>, time: <span id="timechangeEvent"></span>
@ -49,7 +49,7 @@
// Set first time bar
customDate = new Date(customDate.getFullYear(), customDate.getMonth(), customDate.getDate() + 1);
timeline.addCustomTime(customDate, '1');
timeline.addCustomTime(customDate, 't1');
document.getElementById('add').onclick = function () {
try {

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

@ -204,8 +204,8 @@ Network.prototype.setOptions = function (options) {
if (options.clickToUse !== undefined) {
if (options.clickToUse === true) {
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 {
@ -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.openCluster = function() {return this.clustering.openCluster.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.clusterByHubsize = function() {return this.clustering.clusterByHubsize.apply(this.clustering,arguments);};
Network.prototype.clusterOutliers = function() {return this.clustering.clusterOutliers.apply(this.clustering,arguments);};
@ -443,7 +444,7 @@ Network.prototype.enableEditMode = function() {return this.manipulation.ena
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.editNode = function() {return this.manipulation.editNode.apply(this.manipulation,arguments);};
Network.prototype.editNodeMode = function() {console.log("please use editNode instead of editNodeMode"); 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.editEdgeMode = function() {return this.manipulation.editEdgeMode.apply(this.manipulation,arguments);};
Network.prototype.deleteSelected = function() {return this.manipulation.deleteSelected.apply(this.manipulation,arguments);};
@ -458,7 +459,7 @@ Network.prototype.getConnectedNodes = function(objectId) {
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.stopSimulation = function() {return this.physics.stopSimulation.apply(this.physics,arguments);};
Network.prototype.stabilize = function() {return this.physics.stabilize.apply(this.physics,arguments);};

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

@ -498,7 +498,6 @@ class ClusterEngine {
delete this.body.edges[edgeId];
}
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.
if (this.clusteredNodes[edge.fromId] !== undefined || this.clusteredNodes[edge.toId] !== undefined) {
let fromId, toId;
@ -507,17 +506,17 @@ class ClusterEngine {
let clusterNode = this.body.nodes[clusterId];
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 id = 'clusterEdge:' + util.randomUUID();
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() {
// this allows external modules to force all dynamic curves to turn static.
this.body.emitter.on("_forceDisableDynamicCurves", (type) => {
if (type === 'dynamic') {
type = 'continuous';
}
let emitChange = false;
for (let edgeId in this.body.edges) {
if (this.body.edges.hasOwnProperty(edgeId)) {
@ -106,12 +109,12 @@ class EdgesHandler {
if (edgeData !== undefined) {
let edgeOptions = edgeData.smooth;
if (edgeOptions !== undefined) {
if (edgeOptions.enabled === true && edgeOptions.dynamic === true) {
if (edgeOptions.enabled === true && edgeOptions.type === 'dynamic') {
if (type === undefined) {
edge.setOptions({smooth: false});
}
else {
edge.setOptions({smooth: {dynamic: false, type: type}});
edge.setOptions({smooth: {type: type}});
}
emitChange = true;
}

+ 22
- 9
lib/network/modules/LayoutEngine.js View File

@ -100,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.
if (allOptions.edges === undefined) {
this.optionsBackup.edges = {smooth:true, dynamic:true};
this.optionsBackup.edges = {smooth:{enabled:true, type:'dynamic'}};
allOptions.edges = {smooth: false};
}
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;
}
else {
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 {
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
}
}
}
@ -318,7 +331,7 @@ class LayoutEngine {
if (this.body.nodes.hasOwnProperty(nodeId)) {
node = this.body.nodes[nodeId];
if (node.edges.length === hubSize) {
this._setLevel(0, node);
this._setLevelByHubsize(0, node);
}
}
}
@ -334,7 +347,7 @@ class LayoutEngine {
* @param parentId
* @private
*/
_setLevel(level, node) {
_setLevelByHubsize(level, node) {
if (this.hierarchicalLevels[node.id] !== undefined)
return;
@ -347,7 +360,7 @@ class LayoutEngine {
else {
childNode = node.edges[i].to;
}
this._setLevel(level + 1, childNode);
this._setLevelByHubsize(level + 1, childNode);
}
}

+ 0
- 1
lib/network/modules/ManipulationSystem.js View File

@ -946,7 +946,6 @@ class ManipulationSystem {
physics: false,
smooth: {
enabled: true,
dynamic: false,
type: 'continuous',
roundness: 0.5
}

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

@ -400,7 +400,7 @@ class NodesHandler {
* @param nodeId
* @returns {*}
*/
getEdges(nodeId) {
getConnectedEdges(nodeId) {
let edgeList = [];
if (this.body.nodes[nodeId] !== undefined) {
let node = this.body.nodes[nodeId];
@ -408,7 +408,11 @@ class NodesHandler {
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;
}
}

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

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

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

@ -313,7 +313,10 @@ class Configurator {
range.step = step;
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;
}
if (value * 2 > max && max !== 1) {

+ 3
- 3
lib/timeline/component/CustomTime.js View File

@ -34,10 +34,10 @@ function CustomTime (body, options) {
this.eventParams = {}; // stores state parameters while dragging the bar
this.setOptions(options);
// create the DOM
this._create();
this.setOptions(options);
}
CustomTime.prototype = new Component();
@ -63,7 +63,7 @@ CustomTime.prototype.setOptions = function(options) {
CustomTime.prototype._create = function() {
var bar = document.createElement('div');
bar['custom-time'] = this;
bar.className = 'vis-custom-time';
bar.className = 'vis-custom-time ' + (this.options.id || '');
bar.style.position = 'absolute';
bar.style.top = '0px';
bar.style.height = '100%';

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


Loading…
Cancel
Save