Browse Source

fixed bugs, set all groups to reload if globally changed

flowchartTest
Alex de Mulder 9 years ago
parent
commit
cbc4c8dce3
10 changed files with 1858 additions and 1785 deletions
  1. +1738
    -1741
      dist/vis.js
  2. +79
    -0
      examples/network/categories/data/datasets.html
  3. +3
    -3
      examples/network/categories/data/dynamic_data.html
  4. +4
    -0
      lib/network/Network.js
  5. +2
    -2
      lib/network/modules/NodesHandler.js
  6. +4
    -4
      lib/network/modules/components/Edge.js
  7. +2
    -3
      lib/network/modules/components/Node.js
  8. +3
    -15
      lib/network/modules/components/physics/SpringSolver.js
  9. +1
    -3
      lib/network/options.js
  10. +22
    -14
      lib/util.js

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


+ 79
- 0
examples/network/categories/data/datasets.html View File

@ -0,0 +1,79 @@
<!doctype html>
<html>
<head>
<title>Network | Basic usage</title>
<script type="text/javascript" src="../../../../dist/vis.js"></script>
<link href="../../../../dist/vis.css" rel="stylesheet" type="text/css" />
<style type="text/css">
#mynetwork {
width: 600px;
height: 400px;
border: 1px solid lightgray;
}
</style>
</head>
<body>
<p>
Create a simple network with some nodes and edges.
</p>
<input type="button" onclick="addNode()" value="add node dynamically">
<input type="button" onclick="changeNode1()" value="change node 1's color dynamically">
<input type="button" onclick="removeRandomNode()" value="remove a random Node">
<div id="mynetwork"></div>
<script type="text/javascript">
// this list is kept to remove a random node.. we do not add node 1 here because it's used for changes
var nodeIds = [2,3,4,5];
// create an array with nodes
var nodes = new vis.DataSet([
{id: 1, label: 'Node 1'},
{id: 2, label: 'Node 2'},
{id: 3, label: 'Node 3'},
{id: 4, label: 'Node 4'},
{id: 5, label: 'Node 5'}
]);
// create an array with edges
var edges = new vis.DataSet([
{from: 1, to: 3},
{from: 1, to: 2},
{from: 2, to: 4},
{from: 2, to: 5}
]);
// create a network
var container = document.getElementById('mynetwork');
var data = {
nodes: nodes,
edges: edges
};
var options = {};
var network = new vis.Network(container, data, options);
function addNode() {
var newId = (Math.random() * 1e7).toString(32);
nodes.add({id:newId, label:"I'm new!"});
nodeIds.push(newId);
}
function changeNode1() {
var newColor = '#' + Math.floor((Math.random() * 255 * 255 * 255)).toString(16);
nodes.update([{id:1, color:{background:newColor}}]);
}
function removeRandomNode() {
var randomNodeId = nodeIds[Math.floor(Math.random() * nodeIds.length)];
nodes.remove({id:randomNodeId});
var index = nodeIds.indexOf(randomNodeId);
nodeIds.splice(index,1);
}
</script>
<script src="../../../googleAnalytics.js"></script>
</body>
</html>

+ 3
- 3
examples/network/categories/data/dynamic_data.html View File

@ -53,8 +53,8 @@
</style> </style>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js"></script> <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js"></script>
<script type="text/javascript" src="../../dist/vis.js"></script>
<link href="../../dist/vis.css" rel="stylesheet" type="text/css" />
<script type="text/javascript" src="../../../../dist/vis.js"></script>
<link href="../../../../dist/vis.css" rel="stylesheet" type="text/css" />
<script type="text/javascript"> <script type="text/javascript">
var nodes, edges, network; var nodes, edges, network;
@ -168,7 +168,7 @@
network = new vis.Network(container, data, options); network = new vis.Network(container, data, options);
}); });
</script> </script>
<script src="../googleAnalytics.js"></script>
<script src="../../../googleAnalytics.js"></script>
</head> </head>
<body> <body>

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

@ -169,6 +169,10 @@ Network.prototype.setOptions = function (options) {
this.renderer.setOptions(options.interaction); // options for rendering are in interaction this.renderer.setOptions(options.interaction); // options for rendering are in interaction
this.selectionHandler.setOptions(options.interaction); // options for selection are in interaction this.selectionHandler.setOptions(options.interaction); // options for selection are in interaction
// reload the settings of the nodes to apply changes in groups that are not referenced by pointer.
if (options.groups !== undefined) {
this.body.emitter.emit("refreshNodes");
}
// these two do not have options at the moment, here for completeness // these two do not have options at the moment, here for completeness
//this.view.setOptions(options.view); //this.view.setOptions(options.view);
//this.clustering.setOptions(options.clustering); //this.clustering.setOptions(options.clustering);

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

@ -106,7 +106,7 @@ class NodesHandler {
// refresh the nodes. Used when reverting from hierarchical layout // refresh the nodes. Used when reverting from hierarchical layout
this.body.emitter.on('refreshNodes', this.refresh.bind(this)); this.body.emitter.on('refreshNodes', this.refresh.bind(this));
this.body.emitter.on('refresh', this.refresh.bind(this)); this.body.emitter.on('refresh', this.refresh.bind(this));
this.body.emitter.on("destroy", () => {
this.body.emitter.on('destroy', () => {
delete this.body.functions.createNode; delete this.body.functions.createNode;
delete this.nodesListeners.add; delete this.nodesListeners.add;
delete this.nodesListeners.update; delete this.nodesListeners.update;
@ -242,7 +242,7 @@ class NodesHandler {
let data = changedData[i]; let data = changedData[i];
if (node !== undefined) { if (node !== undefined) {
// update node // update node
node.setOptions(data, this.constants);
node.setOptions(data);
} }
else { else {
dataChanged = true; dataChanged = true;

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

@ -115,7 +115,7 @@ class Edge {
if (newOptions.dashes !== undefined && newOptions.dashes !== null) { if (newOptions.dashes !== undefined && newOptions.dashes !== null) {
parentOptions.dashes = newOptions.dashes; parentOptions.dashes = newOptions.dashes;
} }
else if (allowDeletion === true) {
else if (allowDeletion === true && newOptions.dashes === null) {
parentOptions.dashes = undefined; parentOptions.dashes = undefined;
delete parentOptions.dashes; delete parentOptions.dashes;
} }
@ -126,7 +126,7 @@ class Edge {
if (newOptions.scaling.max !== undefined) {parentOptions.scaling.max = newOptions.scaling.max;} if (newOptions.scaling.max !== undefined) {parentOptions.scaling.max = newOptions.scaling.max;}
util.mergeOptions(parentOptions.scaling, newOptions.scaling, 'label'); util.mergeOptions(parentOptions.scaling, newOptions.scaling, 'label');
} }
else if (allowDeletion === true) {
else if (allowDeletion === true && newOptions.scaling === null) {
parentOptions.scaling = undefined; parentOptions.scaling = undefined;
delete parentOptions.scaling; delete parentOptions.scaling;
} }
@ -148,7 +148,7 @@ class Edge {
throw new Error("The arrow newOptions can only be an object or a string. Refer to the documentation. You used:" + JSON.stringify(newOptions.arrows)); throw new Error("The arrow newOptions can only be an object or a string. Refer to the documentation. You used:" + JSON.stringify(newOptions.arrows));
} }
} }
else if (allowDeletion === true) {
else if (allowDeletion === true && newOptions.arrows === null) {
parentOptions.arrows = undefined; parentOptions.arrows = undefined;
delete parentOptions.arrows; delete parentOptions.arrows;
} }
@ -174,7 +174,7 @@ class Edge {
} }
} }
} }
else if (allowDeletion === true) {
else if (allowDeletion === true && newOptions.color === null) {
parentOptions.color = undefined; parentOptions.color = undefined;
delete parentOptions.color; delete parentOptions.color;
} }

+ 2
- 3
lib/network/modules/components/Node.js View File

@ -111,7 +111,6 @@ class Node {
if (!options) { if (!options) {
return; return;
} }
// basic options // basic options
if (options.id !== undefined) {this.id = options.id;} if (options.id !== undefined) {this.id = options.id;}
@ -166,7 +165,7 @@ class Node {
'fixed', 'fixed',
'shadow' 'shadow'
]; ];
util.selectiveNotDeepExtend(fields, parentOptions, newOptions);
util.selectiveNotDeepExtend(fields, parentOptions, newOptions, allowDeletion);
// merge the shadow options into the parent. // merge the shadow options into the parent.
util.mergeOptions(parentOptions, newOptions, 'shadow'); util.mergeOptions(parentOptions, newOptions, 'shadow');
@ -176,7 +175,7 @@ class Node {
let parsedColor = util.parseColor(newOptions.color); let parsedColor = util.parseColor(newOptions.color);
util.fillIfDefined(parentOptions.color, parsedColor); util.fillIfDefined(parentOptions.color, parsedColor);
} }
else if (allowDeletion === true) {
else if (allowDeletion === true && newOptions.color === null) {
parentOptions.color = undefined; parentOptions.color = undefined;
delete parentOptions.color; delete parentOptions.color;
} }

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

@ -7,8 +7,6 @@ class SpringSolver {
setOptions(options) { setOptions(options) {
this.options = options; this.options = options;
this.overlapAvoidanceFactor = 1 - Math.max(0, Math.min(1,this.options.avoidOverlap)); // if 1 then min distance = 0.5, if 0.5 then min distance = 0.5 + 0.5*node.shape.radius
} }
/** /**
@ -58,19 +56,9 @@ class SpringSolver {
* @private * @private
*/ */
_calculateSpringForce(node1, node2, edgeLength) { _calculateSpringForce(node1, node2, edgeLength) {
let dx,dy;
if (this.overlapAvoidanceFactor < 1) {
let nodesWidth = this.overlapAvoidanceFactor * (node1.shape.radius + node2.shape.radius);
dx = (node1.x - node2.x) - nodesWidth;
dy = (node1.y - node2.y) - nodesWidth;
}
else {
dx = (node1.x - node2.x);
dy = (node1.y - node2.y);
}
let distance = Math.sqrt(dx * dx + dy * dy);
distance = distance === 0 ? 0.01 : distance;
let dx = (node1.x - node2.x);
let dy = (node1.y - node2.y);
let distance = Math.max(Math.sqrt(dx * dx + dy * dy),0.01);
// the 1/distance is so the fx and fy can be calculated without sine or cosine. // the 1/distance is so the fx and fy can be calculated without sine or cosine.
let springForce = this.options.springConstant * (edgeLength - distance) / distance; let springForce = this.options.springConstant * (edgeLength - distance) / distance;

+ 1
- 3
lib/network/options.js View File

@ -238,7 +238,6 @@ let allOptions = {
springConstant: {number}, springConstant: {number},
nodeDistance: {number}, nodeDistance: {number},
damping: {number}, damping: {number},
avoidOverlap: {number},
__type__: {object} __type__: {object}
}, },
hierarchicalRepulsion: { hierarchicalRepulsion: {
@ -446,8 +445,7 @@ let configureOptions = {
springLength: [200, 0, 500, 5], springLength: [200, 0, 500, 5],
springConstant: [0.05, 0, 5, 0.005], springConstant: [0.05, 0, 5, 0.005],
nodeDistance: [100, 0, 500, 5], nodeDistance: [100, 0, 500, 5],
damping: [0.09, 0, 1, 0.01],
avoidOverlap: [0, 0, 1, 0.01]
damping: [0.09, 0, 1, 0.01]
}, },
hierarchicalRepulsion: { hierarchicalRepulsion: {
centralGravity: [0.2, 0, 10, 0.05], centralGravity: [0.2, 0, 10, 0.05],

+ 22
- 14
lib/util.js View File

@ -126,6 +126,8 @@ exports.fillIfDefined = function (a, b, allowDeletion = false) {
} }
} }
/** /**
* Extend object a with the properties of object b or a series of objects * Extend object a with the properties of object b or a series of objects
* Only properties with defined values are copied * Only properties with defined values are copied
@ -214,7 +216,7 @@ exports.selectiveDeepExtend = function (props, a, b, allowDeletion = false) {
exports.deepExtend(a[prop], b[prop], false, allowDeletion); exports.deepExtend(a[prop], b[prop], false, allowDeletion);
} }
else { else {
if ((b[prop] === undefined || b[prop] === null) && a[prop] !== undefined && allowDeletion === true) {
if ((b[prop] === null) && a[prop] !== undefined && allowDeletion === true) {
delete a[prop]; delete a[prop];
} }
else { else {
@ -257,7 +259,7 @@ exports.selectiveNotDeepExtend = function (props, a, b, allowDeletion = false) {
exports.deepExtend(a[prop], b[prop]); exports.deepExtend(a[prop], b[prop]);
} }
else { else {
if ((b[prop] === undefined || b[prop] === null) && a[prop] !== undefined && allowDeletion === true) {
if ((b[prop] === null) && a[prop] !== undefined && allowDeletion === true) {
delete a[prop]; delete a[prop];
} }
else { else {
@ -281,7 +283,7 @@ exports.selectiveNotDeepExtend = function (props, a, b, allowDeletion = false) {
* @param {Object} b * @param {Object} b
* @param [Boolean] protoExtend --> optional parameter. If true, the prototype values will also be extended. * @param [Boolean] protoExtend --> optional parameter. If true, the prototype values will also be extended.
* (ie. the options objects that inherit from others will also get the inherited options) * (ie. the options objects that inherit from others will also get the inherited options)
* @param [Boolean] global --> optional parameter. If true, the values of fields that are undefined or null will not deleted
* @param [Boolean] global --> optional parameter. If true, the values of fields that are null will not deleted
* @returns {Object} * @returns {Object}
*/ */
exports.deepExtend = function(a, b, protoExtend, allowDeletion) { exports.deepExtend = function(a, b, protoExtend, allowDeletion) {
@ -295,7 +297,7 @@ exports.deepExtend = function(a, b, protoExtend, allowDeletion) {
exports.deepExtend(a[prop], b[prop], protoExtend); exports.deepExtend(a[prop], b[prop], protoExtend);
} }
else { else {
if ((b[prop] === undefined || b[prop] === null) && a[prop] !== undefined && allowDeletion === true) {
if ((b[prop] === null) && a[prop] !== undefined && allowDeletion === true) {
delete a[prop]; delete a[prop];
} }
else { else {
@ -1209,16 +1211,22 @@ exports.bridgeObject = function(referenceObject) {
* @param [String] option | this is the option key in the options argument * @param [String] option | this is the option key in the options argument
* @private * @private
*/ */
exports.mergeOptions = function (mergeTarget, options, option) {
if (options[option] !== undefined) {
if (typeof options[option] == 'boolean') {
mergeTarget[option].enabled = options[option];
}
else {
mergeTarget[option].enabled = true;
for (var prop in options[option]) {
if (options[option].hasOwnProperty(prop)) {
mergeTarget[option][prop] = options[option][prop];
exports.mergeOptions = function (mergeTarget, options, option, allowDeletion = false) {
if (options[option] === null) {
mergeTarget[option] = undefined;
delete mergeTarget[option];
}
else {
if (options[option] !== undefined) {
if (typeof options[option] == 'boolean') {
mergeTarget[option].enabled = options[option];
}
else {
mergeTarget[option].enabled = true;
for (var prop in options[option]) {
if (options[option].hasOwnProperty(prop)) {
mergeTarget[option][prop] = options[option][prop];
}
} }
} }
} }

Loading…
Cancel
Save