Browse Source

fixed bugs, set all groups to reload if globally changed

flowchartTest
Alex de Mulder 10 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>
<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">
var nodes, edges, network;
@ -168,7 +168,7 @@
network = new vis.Network(container, data, options);
});
</script>
<script src="../googleAnalytics.js"></script>
<script src="../../../googleAnalytics.js"></script>
</head>
<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.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
//this.view.setOptions(options.view);
//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
this.body.emitter.on('refreshNodes', 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.nodesListeners.add;
delete this.nodesListeners.update;
@ -242,7 +242,7 @@ class NodesHandler {
let data = changedData[i];
if (node !== undefined) {
// update node
node.setOptions(data, this.constants);
node.setOptions(data);
}
else {
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) {
parentOptions.dashes = newOptions.dashes;
}
else if (allowDeletion === true) {
else if (allowDeletion === true && newOptions.dashes === null) {
parentOptions.dashes = undefined;
delete parentOptions.dashes;
}
@ -126,7 +126,7 @@ class Edge {
if (newOptions.scaling.max !== undefined) {parentOptions.scaling.max = newOptions.scaling.max;}
util.mergeOptions(parentOptions.scaling, newOptions.scaling, 'label');
}
else if (allowDeletion === true) {
else if (allowDeletion === true && newOptions.scaling === null) {
parentOptions.scaling = undefined;
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));
}
}
else if (allowDeletion === true) {
else if (allowDeletion === true && newOptions.arrows === null) {
parentOptions.arrows = undefined;
delete parentOptions.arrows;
}
@ -174,7 +174,7 @@ class Edge {
}
}
}
else if (allowDeletion === true) {
else if (allowDeletion === true && newOptions.color === null) {
parentOptions.color = undefined;
delete parentOptions.color;
}

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

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

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

@ -7,8 +7,6 @@ class SpringSolver {
setOptions(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
*/
_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.
let springForce = this.options.springConstant * (edgeLength - distance) / distance;

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

@ -238,7 +238,6 @@ let allOptions = {
springConstant: {number},
nodeDistance: {number},
damping: {number},
avoidOverlap: {number},
__type__: {object}
},
hierarchicalRepulsion: {
@ -446,8 +445,7 @@ let configureOptions = {
springLength: [200, 0, 500, 5],
springConstant: [0.05, 0, 5, 0.005],
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: {
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
* 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);
}
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];
}
else {
@ -257,7 +259,7 @@ exports.selectiveNotDeepExtend = function (props, a, b, allowDeletion = false) {
exports.deepExtend(a[prop], b[prop]);
}
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];
}
else {
@ -281,7 +283,7 @@ exports.selectiveNotDeepExtend = function (props, a, b, allowDeletion = false) {
* @param {Object} b
* @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)
* @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}
*/
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);
}
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];
}
else {
@ -1209,16 +1211,22 @@ exports.bridgeObject = function(referenceObject) {
* @param [String] option | this is the option key in the options argument
* @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