Browse Source

network works again!

flowchartTest
Alex de Mulder 9 years ago
parent
commit
1fbdf3b58e
11 changed files with 22125 additions and 21983 deletions
  1. +20770
    -20636
      dist/vis.js
  2. +3
    -3
      lib/network/Groups.js
  3. +2
    -95
      lib/network/Network.js
  4. +3
    -3
      lib/network/dotparser.js
  5. +1
    -1
      lib/network/modules/Clustering.js
  6. +31
    -55
      lib/network/modules/EdgesHandler.js
  7. +22
    -12
      lib/network/modules/NodesHandler.js
  8. +1276
    -1162
      lib/network/modules/components/edges/EdgeMain.js
  9. +15
    -14
      lib/network/modules/components/nodes/NodeMain.js
  10. +1
    -1
      lib/network/modules/components/physics/HierarchicalSpringSolver.js
  11. +1
    -1
      lib/network/modules/components/physics/SpringSolver.js

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


+ 3
- 3
lib/network/Groups.js View File

@ -2,7 +2,7 @@ var util = require('../util');
/** /**
* @class Groups * @class Groups
* This class can store groups and properties specific for groups.
* This class can store groups and options specific for groups.
*/ */
function Groups() { function Groups() {
this.clear(); this.clear();
@ -62,10 +62,10 @@ Groups.prototype.clear = function () {
/** /**
* get group properties of a groupname. If groupname is not found, a new group
* get group options of a groupname. If groupname is not found, a new group
* is added. * is added.
* @param {*} groupname Can be a number, string, Date, etc. * @param {*} groupname Can be a number, string, Date, etc.
* @return {Object} group The created group, containing all group properties
* @return {Object} group The created group, containing all group options
*/ */
Groups.prototype.get = function (groupname) { Groups.prototype.get = function (groupname) {
var group = this.groups[groupname]; var group = this.groups[groupname];

+ 2
- 95
lib/network/Network.js View File

@ -7,8 +7,6 @@ var dotparser = require('./dotparser');
var gephiParser = require('./gephiParser'); var gephiParser = require('./gephiParser');
var Groups = require('./Groups'); var Groups = require('./Groups');
var Images = require('./Images'); var Images = require('./Images');
var Node = require('./modules/components/nodes/NodeMain');
var Edge = require('./modules/components/edges/EdgeMain');
var Popup = require('./Popup'); var Popup = require('./Popup');
var Activator = require('../shared/Activator'); var Activator = require('../shared/Activator');
var locales = require('./locales'); var locales = require('./locales');
@ -73,8 +71,8 @@ function Network (container, data, options) {
edges: null // A DataSet or DataView edges: null // A DataSet or DataView
}, },
functions:{ functions:{
createNode: this._createNode.bind(this),
createEdge: this._createEdge.bind(this)
createNode: () => {},
createEdge: () => {}
}, },
emitter: { emitter: {
on: this.on.bind(this), on: this.on.bind(this),
@ -132,7 +130,6 @@ function Network (container, data, options) {
this._updateValueRange(this.body.edges); this._updateValueRange(this.body.edges);
// update edges // update edges
this._reconnectEdges(); this._reconnectEdges();
this.edgesHandler.createBezierNodes(params);
this._markAllEdgesAsDirty(); this._markAllEdgesAsDirty();
// start simulation (can be called safely, even if already running) // start simulation (can be called safely, even if already running)
this.body.emitter.emit("startSimulation"); this.body.emitter.emit("startSimulation");
@ -147,7 +144,6 @@ function Network (container, data, options) {
this._updateValueRange(this.body.edges); this._updateValueRange(this.body.edges);
// update edges // update edges
this._reconnectEdges(); this._reconnectEdges();
this.edgesHandler.createBezierNodes(params);
this._markAllEdgesAsDirty(); this._markAllEdgesAsDirty();
// start simulation (can be called safely, even if already running) // start simulation (can be called safely, even if already running)
this.body.emitter.emit("startSimulation"); this.body.emitter.emit("startSimulation");
@ -169,14 +165,6 @@ function Network (container, data, options) {
Emitter(Network.prototype); Emitter(Network.prototype);
Network.prototype._createNode = function(properties) {
return new Node(properties, this.images, this.groups, this.constants)
}
Network.prototype._createEdge = function(properties) {
return new Edge(properties, this.body, this.constants)
}
/** /**
* Update the this.body.nodeIndices with the most recent node index list * Update the this.body.nodeIndices with the most recent node index list
* @private * @private
@ -637,80 +625,6 @@ Network.prototype._getScale = function() {
}; };
/**
* Move the network according to the keyboard presses.
*
* @private
*/
Network.prototype._handleNavigation = function() {
if (this.xIncrement != 0 || this.yIncrement != 0) {
var translation = this._getTranslation();
this._setTranslation(translation.x+this.xIncrement, translation.y+this.yIncrement);
}
if (this.zoomIncrement != 0) {
var center = {
x: this.frame.canvas.clientWidth / 2,
y: this.frame.canvas.clientHeight / 2
};
this.zoom(this.scale*(1 + this.zoomIncrement), center);
}
};
/**
* Freeze the _animationStep
*/
Network.prototype.freezeSimulation = function(freeze) {
if (freeze == true) {
this.freezeSimulationEnabled = true;
this.moving = false;
}
else {
this.freezeSimulationEnabled = false;
this.moving = true;
this.start();
}
};
/**
* This function cleans the support nodes if they are not needed and adds them when they are.
*
* @param {boolean} [disableStart]
* @private
*/
Network.prototype._configureSmoothCurves = function(disableStart = true) {
if (this.constants.smoothCurves.enabled == true && this.constants.smoothCurves.dynamic == true) {
this._createBezierNodes();
// cleanup unused support nodes
for (let i = 0; i < this.body.supportNodeIndices.length; i++) {
let nodeId = this.body.supportNodeIndices[i];
// delete support nodes for edges that have been deleted
if (this.body.edges[this.body.supportNodes[nodeId].parentEdgeId] === undefined) {
delete this.body.supportNodes[nodeId];
}
}
}
else {
// delete the support nodes
this.body.supportNodes = {};
for (var edgeId in this.body.edges) {
if (this.body.edges.hasOwnProperty(edgeId)) {
this.body.edges[edgeId].via = null;
}
}
}
this._updateNodeIndexList();
this.physics._updateCalculationNodes();
if (!disableStart) {
this.moving = true;
this.start();
}
};
/** /**
* load the functions that load the mixins into the prototype. * load the functions that load the mixins into the prototype.
* *
@ -724,13 +638,6 @@ Network.prototype._initializeMixinLoaders = function () {
} }
}; };
/**
* Load the XY positions of the nodes into the dataset.
*/
Network.prototype.storePosition = function() {
console.log("storePosition is depricated: use .storePositions() from now on.")
this.storePositions();
};
/** /**
* Load the XY positions of the nodes into the dataset. * Load the XY positions of the nodes into the dataset.

+ 3
- 3
lib/network/dotparser.js View File

@ -81,7 +81,7 @@ function isAlphaNumeric(c) {
} }
/** /**
* Merge all properties of object b into object b
* Merge all options of object b into object b
* @param {Object} a * @param {Object} a
* @param {Object} b * @param {Object} b
* @return {Object} a * @return {Object} a
@ -414,7 +414,7 @@ function parseGraph() {
} }
getToken(); getToken();
// remove temporary default properties
// remove temporary default options
delete graph.node; delete graph.node;
delete graph.edge; delete graph.edge;
delete graph.graph; delete graph.graph;
@ -521,7 +521,7 @@ function parseSubgraph (graph) {
} }
getToken(); getToken();
// remove temporary default properties
// remove temporary default options
delete subgraph.node; delete subgraph.node;
delete subgraph.edge; delete subgraph.edge;
delete subgraph.graph; delete subgraph.graph;

+ 1
- 1
lib/network/modules/Clustering.js View File

@ -165,7 +165,7 @@ class ClusterEngine {
/** /**
* This returns a clone of the options or properties of the edge or node to be used for construction of new edges or check functions for new nodes.
* This returns a clone of the options or options of the edge or node to be used for construction of new edges or check functions for new nodes.
* @param objId * @param objId
* @param type * @param type
* @returns {{}} * @returns {{}}

+ 31
- 55
lib/network/modules/EdgesHandler.js View File

@ -14,25 +14,26 @@ class EdgesHandler {
this.images = images; this.images = images;
this.groups = groups; this.groups = groups;
// create the edge API in the body container
this.body.functions.createEdge = this.create.bind(this);
this.edgesListeners = { this.edgesListeners = {
'add': (event, params) => {this.add(params.items);}, 'add': (event, params) => {this.add(params.items);},
'update': (event, params) => {this.update(params.items);}, 'update': (event, params) => {this.update(params.items);},
'remove': (event, params) => {this.remove(params.items);} 'remove': (event, params) => {this.remove(params.items);}
}; };
var customScalingFunction = function (min,max,total,value) {
if (max == min) {
return 0.5;
}
else {
var scale = 1 / (max - min);
return Math.max(0,(value - min)*scale);
}
};
this.options = {}; this.options = {};
this.defaultOptions = { this.defaultOptions = {
customScalingFunction: customScalingFunction,
customScalingFunction: function (min,max,total,value) {
if (max == min) {
return 0.5;
}
else {
var scale = 1 / (max - min);
return Math.max(0,(value - min)*scale);
}
},
widthMin: 1, // widthMin: 1, //
widthMax: 15,// widthMax: 15,//
width: 1, width: 1,
@ -61,7 +62,7 @@ class EdgesHandler {
}, },
inheritColor: "from", // to, from, false, true (== from) inheritColor: "from", // to, from, false, true (== from)
useGradients: false, // release in 4.0 useGradients: false, // release in 4.0
smoothEdges: {
smooth: {
enabled: true, enabled: true,
dynamic: true, dynamic: true,
type: "continuous", type: "continuous",
@ -129,10 +130,10 @@ class EdgesHandler {
* @private * @private
*/ */
add(ids) { add(ids) {
var edges = this.body.edges,
edgesData = this.body.data.edges;
var edges = this.body.edges;
var edgesData = this.body.data.edges;
for (var i = 0; i < ids.length; i++) {
for (let i = 0; i < ids.length; i++) {
var id = ids[i]; var id = ids[i];
var oldEdge = edges[id]; var oldEdge = edges[id];
@ -141,7 +142,7 @@ class EdgesHandler {
} }
var data = edgesData.get(id, {"showInternalIds" : true}); var data = edgesData.get(id, {"showInternalIds" : true});
edges[id] = new Edge(data, this.body, this.options);
edges[id] = this.create(data);
} }
this.body.emitter.emit("_dataChanged"); this.body.emitter.emit("_dataChanged");
@ -157,24 +158,30 @@ class EdgesHandler {
update(ids) { update(ids) {
var edges = this.body.edges; var edges = this.body.edges;
var edgesData = this.body.data.edges; var edgesData = this.body.data.edges;
var dataChanged = false;
for (var i = 0; i < ids.length; i++) { for (var i = 0; i < ids.length; i++) {
var id = ids[i]; var id = ids[i];
var data = edgesData.get(id); var data = edgesData.get(id);
var edge = edges[id]; var edge = edges[id];
if (edge) {
if (edge === null) {
// update edge // update edge
edge.disconnect(); edge.disconnect();
edge.setProperties(data);
edge.setOptions(data);
edge.connect(); edge.connect();
} }
else { else {
// create edge // create edge
edge = new Edge(data, this.body, this.options);
this.body.edges[id] = edge;
this.body.edges[id] = this.create(data);
dataChanged = true;
} }
} }
this.body.emitter.emit("_dataUpdated")
if (dataChanged === true) {
this.body.emitter.emit("_dataChanged");
}
else {
this.body.emitter.emit("_dataUpdated");
}
} }
@ -201,41 +208,10 @@ class EdgesHandler {
this.body.emitter.emit("_dataChanged"); this.body.emitter.emit("_dataChanged");
} }
/**
* Bezier curves require an anchor point to calculate the smooth flow. These points are nodes. These nodes are invisible but
* are used for the force calculation.
*
* @private
*/
createBezierNodes(specificEdges = this.body.edges) {
var changedData = false;
if (this.options.smoothEdges.enabled == true && this.options.smoothEdges.dynamic == true) {
for (var edgeId in specificEdges) {
if (specificEdges.hasOwnProperty(edgeId)) {
var edge = specificEdges[edgeId];
if (edge.via == null) {
changedData = true;
// TODO: move to nodes
var nodeId = "edgeId:".concat(edge.id);
var node = new Node(
{id:nodeId,
mass:1,
shape:'circle',
image:"",
internalMultiplier:1
},{},{},this.constants);
this.body.supportNodes[nodeId] = node;
edge.via = node;
edge.via.parentEdgeId = edge.id;
edge.positionBezierNode();
}
}
}
}
if (changedData === true) {
this.body.emitter.emit("_dataChanged");
}
create(properties) {
return new Edge(properties, this.body, this.options)
} }
} }
export default EdgesHandler; export default EdgesHandler;

+ 22
- 12
lib/network/modules/NodesHandler.js View File

@ -15,25 +15,27 @@ class NodesHandler {
this.groups = groups; this.groups = groups;
this.layoutEngine = layoutEngine; this.layoutEngine = layoutEngine;
// create the node API in the body container
this.body.functions.createNode = this.create.bind(this);
this.nodesListeners = { this.nodesListeners = {
'add': (event, params) => {this.add(params.items);}, 'add': (event, params) => {this.add(params.items);},
'update': (event, params) => {this.update(params.items, params.data);}, 'update': (event, params) => {this.update(params.items, params.data);},
'remove': (event, params) => {this.remove(params.items);} 'remove': (event, params) => {this.remove(params.items);}
}; };
var customScalingFunction = function (min,max,total,value) {
if (max == min) {
return 0.5;
}
else {
var scale = 1 / (max - min);
return Math.max(0,(value - min)*scale);
}
};
this.options = {}; this.options = {};
this.defaultOptions = { this.defaultOptions = {
customScalingFunction: customScalingFunction,
customScalingFunction: function (min,max,total,value) {
if (max == min) {
return 0.5;
}
else {
var scale = 1 / (max - min);
return Math.max(0,(value - min)*scale);
}
},
mass: 1, mass: 1,
radiusMin: 10, radiusMin: 10,
radiusMax: 30, radiusMax: 30,
@ -162,7 +164,7 @@ class NodesHandler {
var data = changedData[i]; var data = changedData[i];
if (node !== undefined) { if (node !== undefined) {
// update node // update node
node.setProperties(data, this.constants);
node.setOptions(data, this.constants);
} }
else { else {
dataChanged = true; dataChanged = true;
@ -172,7 +174,7 @@ class NodesHandler {
} }
} }
if (dataChanged) {
if (dataChanged === true) {
this.body.emitter.emit("_dataChanged"); this.body.emitter.emit("_dataChanged");
} }
else { else {
@ -195,6 +197,14 @@ class NodesHandler {
this.body.emitter.emit("_dataChanged"); this.body.emitter.emit("_dataChanged");
} }
create(properties) {
return new Node(properties, this.images, this.groups, this.options)
}
} }
export default NodesHandler; export default NodesHandler;

+ 1276
- 1162
lib/network/modules/components/edges/EdgeMain.js
File diff suppressed because it is too large
View File


+ 15
- 14
lib/network/modules/components/nodes/NodeMain.js View File

@ -3,8 +3,8 @@ var util = require('../../../../util');
/** /**
* @class Node * @class Node
* A node. A node can be connected to other nodes via one or multiple edges. * A node. A node can be connected to other nodes via one or multiple edges.
* @param {object} properties An object containing properties for the node. All
* properties are optional, except for the id.
* @param {object} properties An object containing options for the node. All
* options are optional, except for the id.
* {number} id Id of the node. Required * {number} id Id of the node. Required
* {string} label Text label for the node * {string} label Text label for the node
* {number} x Horizontal position of the node * {number} x Horizontal position of the node
@ -20,7 +20,7 @@ var util = require('../../../../util');
* @param {Network.Images} imagelist A list with images. Only needed * @param {Network.Images} imagelist A list with images. Only needed
* when the node has an image * when the node has an image
* @param {Network.Groups} grouplist A list with groups. Needed for * @param {Network.Groups} grouplist A list with groups. Needed for
* retrieving group properties
* retrieving group options
* @param {Object} constants An object with default values for * @param {Object} constants An object with default values for
* example for the color * example for the color
* *
@ -33,7 +33,7 @@ function Node(properties, imagelist, grouplist, globalOptions) {
this.edges = []; // all edges connected to this node this.edges = []; // all edges connected to this node
// set defaults for the properties
// set defaults for the options
this.id = undefined; this.id = undefined;
this.allowedToMoveX = false; this.allowedToMoveX = false;
this.allowedToMoveY = false; this.allowedToMoveY = false;
@ -43,6 +43,7 @@ function Node(properties, imagelist, grouplist, globalOptions) {
this.verticalAlignTop = true; // these are for the navigation controls this.verticalAlignTop = true; // these are for the navigation controls
this.baseRadiusValue = this.options.radius; this.baseRadiusValue = this.options.radius;
this.radiusFixed = false; this.radiusFixed = false;
this.level = -1; this.level = -1;
this.preassignedLevel = false; this.preassignedLevel = false;
this.hierarchyEnumerated = false; this.hierarchyEnumerated = false;
@ -52,7 +53,7 @@ function Node(properties, imagelist, grouplist, globalOptions) {
this.imagelist = imagelist; this.imagelist = imagelist;
this.grouplist = grouplist; this.grouplist = grouplist;
// physics properties
// physics options
this.x = null; this.x = null;
this.y = null; this.y = null;
this.predefinedPosition = false; // used to check if initial zoomExtent should just take the range or approximate this.predefinedPosition = false; // used to check if initial zoomExtent should just take the range or approximate
@ -60,7 +61,7 @@ function Node(properties, imagelist, grouplist, globalOptions) {
this.fixedData = {x:null,y:null}; this.fixedData = {x:null,y:null};
// TODO: global options should not be needed here. // TODO: global options should not be needed here.
this.setProperties(properties, globalOptions);
this.setOptions(properties, globalOptions);
// variables to tell the node about the network. // variables to tell the node about the network.
this.networkScaleInv = 1; this.networkScaleInv = 1;
@ -94,11 +95,11 @@ Node.prototype.detachEdge = function(edge) {
/** /**
* Set or overwrite properties for the node
* @param {Object} properties an object with properties
* @param {Object} constants and object with default, global properties
* Set or overwrite options for the node
* @param {Object} properties an object with options
* @param {Object} constants and object with default, global options
*/ */
Node.prototype.setProperties = function(properties, constants) {
Node.prototype.setOptions = function(properties, constants) {
if (!properties) { if (!properties) {
return; return;
} }
@ -111,7 +112,7 @@ Node.prototype.setProperties = function(properties, constants) {
]; ];
util.selectiveDeepExtend(fields, this.options, properties); util.selectiveDeepExtend(fields, this.options, properties);
// basic properties
// basic options
if (properties.id !== undefined) {this.id = properties.id;} if (properties.id !== undefined) {this.id = properties.id;}
if (properties.label !== undefined) {this.label = properties.label; this.originalLabel = properties.label;} if (properties.label !== undefined) {this.label = properties.label; this.originalLabel = properties.label;}
if (properties.title !== undefined) {this.title = properties.title;} if (properties.title !== undefined) {this.title = properties.title;}
@ -120,7 +121,7 @@ Node.prototype.setProperties = function(properties, constants) {
if (properties.value !== undefined) {this.value = properties.value;} if (properties.value !== undefined) {this.value = properties.value;}
if (properties.level !== undefined) {this.level = properties.level; this.preassignedLevel = true;} if (properties.level !== undefined) {this.level = properties.level; this.preassignedLevel = true;}
// navigation controls properties
// navigation controls options
if (properties.horizontalAlignLeft !== undefined) {this.horizontalAlignLeft = properties.horizontalAlignLeft;} if (properties.horizontalAlignLeft !== undefined) {this.horizontalAlignLeft = properties.horizontalAlignLeft;}
if (properties.verticalAlignTop !== undefined) {this.verticalAlignTop = properties.verticalAlignTop;} if (properties.verticalAlignTop !== undefined) {this.verticalAlignTop = properties.verticalAlignTop;}
if (properties.triggerFunction !== undefined) {this.triggerFunction = properties.triggerFunction;} if (properties.triggerFunction !== undefined) {this.triggerFunction = properties.triggerFunction;}
@ -129,14 +130,14 @@ Node.prototype.setProperties = function(properties, constants) {
throw "Node must have an id"; throw "Node must have an id";
} }
// copy group properties
// copy group options
if (typeof properties.group === 'number' || (typeof properties.group === 'string' && properties.group != '')) { if (typeof properties.group === 'number' || (typeof properties.group === 'string' && properties.group != '')) {
var groupObj = this.grouplist.get(properties.group); var groupObj = this.grouplist.get(properties.group);
util.deepExtend(this.options, groupObj); util.deepExtend(this.options, groupObj);
// the color object needs to be completely defined. Since groups can partially overwrite the colors, we parse it again, just in case. // the color object needs to be completely defined. Since groups can partially overwrite the colors, we parse it again, just in case.
this.options.color = util.parseColor(this.options.color); this.options.color = util.parseColor(this.options.color);
} }
// individual shape properties
// individual shape options
if (properties.radius !== undefined) {this.baseRadiusValue = this.options.radius;} if (properties.radius !== undefined) {this.baseRadiusValue = this.options.radius;}
if (properties.color !== undefined) {this.options.color = util.parseColor(properties.color);} if (properties.color !== undefined) {this.options.color = util.parseColor(properties.color);}

+ 1
- 1
lib/network/modules/components/physics/HierarchicalSpringSolver.js View File

@ -39,7 +39,7 @@ class HierarchicalSpringSolver {
if (edges.hasOwnProperty(edgeId)) { if (edges.hasOwnProperty(edgeId)) {
edge = edges[edgeId]; edge = edges[edgeId];
if (edge.connected === true) { if (edge.connected === true) {
edgeLength = edge.properties.length === undefined ? this.options.springLength : edge.properties.length;
edgeLength = edge.options.length === undefined ? this.options.springLength : edge.options.length;
dx = (edge.from.x - edge.to.x); dx = (edge.from.x - edge.to.x);
dy = (edge.from.y - edge.to.y); dy = (edge.from.y - edge.to.y);

+ 1
- 1
lib/network/modules/components/physics/SpringSolver.js View File

@ -29,7 +29,7 @@ class SpringSolver {
if (edge.connected === true) { if (edge.connected === true) {
// only calculate forces if nodes are in the same sector // only calculate forces if nodes are in the same sector
if (this.body.nodes[edge.toId] !== undefined && this.body.nodes[edge.fromId] !== undefined) { if (this.body.nodes[edge.toId] !== undefined && this.body.nodes[edge.fromId] !== undefined) {
edgeLength = edge.properties.length === undefined ? this.options.springLength : edge.properties.length;
edgeLength = edge.options.length === undefined ? this.options.springLength : edge.options.length;
if (edge.via != null) { if (edge.via != null) {
var node1 = edge.to; var node1 = edge.to;
var node2 = edge.via; var node2 = edge.via;

Loading…
Cancel
Save