diff --git a/HISTORY.md b/HISTORY.md index 5e2c3b1b..1a7d5378 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -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 diff --git a/docs/network/index.html b/docs/network/index.html index 14b0284c..e2470cde 100644 --- a/docs/network/index.html +++ b/docs/network/index.html @@ -622,6 +622,15 @@ var locales = {
String clusterNodeId
)
+ String nodeId
)
diff --git a/docs/network/interaction.html b/docs/network/interaction.html
index 54a306c4..bbd4f1ba 100644
--- a/docs/network/interaction.html
+++ b/docs/network/interaction.html
@@ -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);
1
0.02
true
false
false
true
true
time
can be a Date, Number, or String, and is new Date()
by default.
- Parameter id
can be Number or String and is undefined
by default.id
can be Number or String and is undefined
by default.
+ The id
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.
- +
timechange
event, index: , time:
@@ -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 {
diff --git a/lib/network/Network.js b/lib/network/Network.js
index 7cf529ce..662226cf 100644
--- a/lib/network/Network.js
+++ b/lib/network/Network.js
@@ -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);};
diff --git a/lib/network/modules/Clustering.js b/lib/network/modules/Clustering.js
index e68234cc..071215b2 100644
--- a/lib/network/modules/Clustering.js
+++ b/lib/network/modules/Clustering.js
@@ -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;
}
/**
diff --git a/lib/network/modules/EdgesHandler.js b/lib/network/modules/EdgesHandler.js
index 0eb18e6a..25f5a05d 100644
--- a/lib/network/modules/EdgesHandler.js
+++ b/lib/network/modules/EdgesHandler.js
@@ -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;
}
diff --git a/lib/network/modules/LayoutEngine.js b/lib/network/modules/LayoutEngine.js
index 9748834b..65b8f691 100644
--- a/lib/network/modules/LayoutEngine.js
+++ b/lib/network/modules/LayoutEngine.js
@@ -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);
}
}
diff --git a/lib/network/modules/ManipulationSystem.js b/lib/network/modules/ManipulationSystem.js
index 48f9e42b..16b855df 100644
--- a/lib/network/modules/ManipulationSystem.js
+++ b/lib/network/modules/ManipulationSystem.js
@@ -946,7 +946,6 @@ class ManipulationSystem {
physics: false,
smooth: {
enabled: true,
- dynamic: false,
type: 'continuous',
roundness: 0.5
}
diff --git a/lib/network/modules/NodesHandler.js b/lib/network/modules/NodesHandler.js
index 17459a57..70648a82 100644
--- a/lib/network/modules/NodesHandler.js
+++ b/lib/network/modules/NodesHandler.js
@@ -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;
}
}
diff --git a/lib/network/modules/components/NavigationHandler.js b/lib/network/modules/components/NavigationHandler.js
index 880c9cdb..1ef2fb72 100644
--- a/lib/network/modules/components/NavigationHandler.js
+++ b/lib/network/modules/components/NavigationHandler.js
@@ -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});
}
diff --git a/lib/shared/Configurator.js b/lib/shared/Configurator.js
index 2083ef7c..8401495d 100644
--- a/lib/shared/Configurator.js
+++ b/lib/shared/Configurator.js
@@ -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) {
diff --git a/lib/timeline/component/CustomTime.js b/lib/timeline/component/CustomTime.js
index 8efdb8ca..86aec043 100644
--- a/lib/timeline/component/CustomTime.js
+++ b/lib/timeline/component/CustomTime.js
@@ -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%';
diff --git a/test/networkTest.html b/test/networkTest.html
index 4d2005b3..792b9947 100644
--- a/test/networkTest.html
+++ b/test/networkTest.html
@@ -7,7 +7,7 @@