Browse Source

- Added #1138, enable the user to define the color of the shadows for nodes and edges.

- Fixed #1528, #1278, avoided ID's being cast to string for methods that return ID's as well as storePositions casting to string.
codeClimate
Alex de Mulder 10 years ago
parent
commit
11888f255d
19 changed files with 128 additions and 161 deletions
  1. +3
    -1
      HISTORY.md
  2. +39
    -34
      dist/vis.js
  3. +7
    -0
      docs/network/edges.html
  4. +7
    -0
      docs/network/nodes.html
  5. +1
    -1
      examples/network/nodeStyles/shadows.html
  6. +2
    -2
      lib/network/Network.js
  7. +4
    -4
      lib/network/modules/Clustering.js
  8. +3
    -2
      lib/network/modules/EdgesHandler.js
  9. +4
    -3
      lib/network/modules/NodesHandler.js
  10. +5
    -5
      lib/network/modules/PhysicsEngine.js
  11. +2
    -2
      lib/network/modules/SelectionHandler.js
  12. +2
    -2
      lib/network/modules/components/Edge.js
  13. +2
    -0
      lib/network/modules/components/Node.js
  14. +1
    -1
      lib/network/modules/components/edges/BezierEdgeDynamic.js
  15. +1
    -1
      lib/network/modules/components/edges/util/EdgeBase.js
  16. +1
    -1
      lib/network/modules/components/nodes/util/NodeBase.js
  17. +2
    -0
      lib/network/options.js
  18. +0
    -1
      lib/util.js
  19. +42
    -101
      test/networkTest.html

+ 3
- 1
HISTORY.md View File

@ -11,11 +11,13 @@ http://visjs.org
### Network ### Network
- Fixed #1531 , #1335: border distances for arrow positioning
- Fixed #1531, #1335: border distances for arrow positioning
- Fixed findNode method. It now does not return internal objects anymore. - Fixed findNode method. It now does not return internal objects anymore.
- Fixed #1529, clustering and declustering now respects the original settings of the edges for physics and hidden. - Fixed #1529, clustering and declustering now respects the original settings of the edges for physics and hidden.
- Fixed #1406, control nodes are now drawn immediately without a second redraw. - Fixed #1406, control nodes are now drawn immediately without a second redraw.
- Fixed #1404, made the array returned by findNode match the docs. - Fixed #1404, made the array returned by findNode match the docs.
- Added #1138, enable the user to define the color of the shadows for nodes and edges.
- Fixed #1528, #1278, avoided ID's being cast to string for methods that return ID's as well as storePositions casting to string.
## 2015-12-18, version 4.11.0 ## 2015-12-18, version 4.11.0

+ 39
- 34
dist/vis.js View File

@ -1384,7 +1384,6 @@ return /******/ (function(modules) { // webpackBootstrap
* @param [object] mergeTarget | this is either this.options or the options used for the groups. * @param [object] mergeTarget | this is either this.options or the options used for the groups.
* @param [object] options | options * @param [object] options | options
* @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
*/ */
exports.mergeOptions = function (mergeTarget, options, option) { exports.mergeOptions = function (mergeTarget, options, option) {
var allowDeletion = arguments.length <= 3 || arguments[3] === undefined ? false : arguments[3]; var allowDeletion = arguments.length <= 3 || arguments[3] === undefined ? false : arguments[3];
@ -27861,7 +27860,7 @@ return /******/ (function(modules) { // webpackBootstrap
for (var nodeId in nodes) { for (var nodeId in nodes) {
if (nodes.hasOwnProperty(nodeId)) { if (nodes.hasOwnProperty(nodeId)) {
if (nodes[nodeId].options.hidden === false) { if (nodes[nodeId].options.hidden === false) {
this.body.nodeIndices.push(nodeId);
this.body.nodeIndices.push(nodes[nodeId].id);
} }
} }
} }
@ -27869,7 +27868,7 @@ return /******/ (function(modules) { // webpackBootstrap
for (var edgeId in edges) { for (var edgeId in edges) {
if (edges.hasOwnProperty(edgeId)) { if (edges.hasOwnProperty(edgeId)) {
if (edges[edgeId].options.hidden === false) { if (edges[edgeId].options.hidden === false) {
this.body.edgeIndices.push(edgeId);
this.body.edgeIndices.push(edges[edgeId].id);
} }
} }
} }
@ -28455,6 +28454,7 @@ return /******/ (function(modules) { // webpackBootstrap
}, },
shadow: { shadow: {
enabled: false, enabled: false,
color: 'rgba(0,0,0,0.5)',
size: 10, size: 10,
x: 5, x: 5,
y: 5 y: 5
@ -28745,7 +28745,7 @@ return /******/ (function(modules) { // webpackBootstrap
if (dataset._data.hasOwnProperty(nodeId)) { if (dataset._data.hasOwnProperty(nodeId)) {
var node = this.body.nodes[nodeId]; var node = this.body.nodes[nodeId];
if (dataset._data[nodeId].x != Math.round(node.x) || dataset._data[nodeId].y != Math.round(node.y)) { if (dataset._data[nodeId].x != Math.round(node.x) || dataset._data[nodeId].y != Math.round(node.y)) {
dataArray.push({ id: nodeId, x: Math.round(node.x), y: Math.round(node.y) });
dataArray.push({ id: node.id, x: Math.round(node.x), y: Math.round(node.y) });
} }
} }
} }
@ -28779,13 +28779,13 @@ return /******/ (function(modules) { // webpackBootstrap
var nodeObj = {}; // used to quickly check if node already exists var nodeObj = {}; // used to quickly check if node already exists
for (var i = 0; i < node.edges.length; i++) { for (var i = 0; i < node.edges.length; i++) {
var edge = node.edges[i]; var edge = node.edges[i];
if (edge.toId == nodeId) {
if (edge.toId == node.id) {
// these are double equals since ids can be numeric or string // these are double equals since ids can be numeric or string
if (nodeObj[edge.fromId] === undefined) { if (nodeObj[edge.fromId] === undefined) {
nodeList.push(edge.fromId); nodeList.push(edge.fromId);
nodeObj[edge.fromId] = true; nodeObj[edge.fromId] = true;
} }
} else if (edge.fromId == nodeId) {
} else if (edge.fromId == node.id) {
// these are double equals since ids can be numeric or string // these are double equals since ids can be numeric or string
if (nodeObj[edge.toId] === undefined) { if (nodeObj[edge.toId] === undefined) {
nodeList.push(edge.toId); nodeList.push(edge.toId);
@ -29086,6 +29086,8 @@ return /******/ (function(modules) { // webpackBootstrap
* Static so it can also be used by the handler. * Static so it can also be used by the handler.
* @param parentOptions * @param parentOptions
* @param newOptions * @param newOptions
* @param allowDeletion
* @param globalOptions
*/ */
}, { }, {
key: 'updateLabelModule', key: 'updateLabelModule',
@ -29809,15 +29811,15 @@ return /******/ (function(modules) { // webpackBootstrap
/* 64 */ /* 64 */
/***/ function(module, exports) { /***/ function(module, exports) {
'use strict';
"use strict";
Object.defineProperty(exports, '__esModule', {
Object.defineProperty(exports, "__esModule", {
value: true value: true
}); });
var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var NodeBase = (function () { var NodeBase = (function () {
function NodeBase(options, body, labelModule) { function NodeBase(options, body, labelModule) {
@ -29835,29 +29837,29 @@ return /******/ (function(modules) { // webpackBootstrap
} }
_createClass(NodeBase, [{ _createClass(NodeBase, [{
key: 'setOptions',
key: "setOptions",
value: function setOptions(options) { value: function setOptions(options) {
this.options = options; this.options = options;
} }
}, { }, {
key: '_distanceToBorder',
key: "_distanceToBorder",
value: function _distanceToBorder(ctx, angle) { value: function _distanceToBorder(ctx, angle) {
var borderWidth = this.options.borderWidth; var borderWidth = this.options.borderWidth;
this.resize(ctx); this.resize(ctx);
return Math.min(Math.abs(this.width / 2 / Math.cos(angle)), Math.abs(this.height / 2 / Math.sin(angle))) + borderWidth; return Math.min(Math.abs(this.width / 2 / Math.cos(angle)), Math.abs(this.height / 2 / Math.sin(angle))) + borderWidth;
} }
}, { }, {
key: 'enableShadow',
key: "enableShadow",
value: function enableShadow(ctx) { value: function enableShadow(ctx) {
if (this.options.shadow.enabled === true) { if (this.options.shadow.enabled === true) {
ctx.shadowColor = 'rgba(0,0,0,0.5)';
ctx.shadowColor = this.options.shadow.color;
ctx.shadowBlur = this.options.shadow.size; ctx.shadowBlur = this.options.shadow.size;
ctx.shadowOffsetX = this.options.shadow.x; ctx.shadowOffsetX = this.options.shadow.x;
ctx.shadowOffsetY = this.options.shadow.y; ctx.shadowOffsetY = this.options.shadow.y;
} }
} }
}, { }, {
key: 'disableShadow',
key: "disableShadow",
value: function disableShadow(ctx) { value: function disableShadow(ctx) {
if (this.options.shadow.enabled === true) { if (this.options.shadow.enabled === true) {
ctx.shadowColor = 'rgba(0,0,0,0)'; ctx.shadowColor = 'rgba(0,0,0,0)';
@ -29867,7 +29869,7 @@ return /******/ (function(modules) { // webpackBootstrap
} }
} }
}, { }, {
key: 'enableBorderDashes',
key: "enableBorderDashes",
value: function enableBorderDashes(ctx) { value: function enableBorderDashes(ctx) {
if (this.options.shapeProperties.borderDashes !== false) { if (this.options.shapeProperties.borderDashes !== false) {
if (ctx.setLineDash !== undefined) { if (ctx.setLineDash !== undefined) {
@ -29883,7 +29885,7 @@ return /******/ (function(modules) { // webpackBootstrap
} }
} }
}, { }, {
key: 'disableBorderDashes',
key: "disableBorderDashes",
value: function disableBorderDashes(ctx) { value: function disableBorderDashes(ctx) {
if (this.options.shapeProperties.borderDashes !== false) { if (this.options.shapeProperties.borderDashes !== false) {
if (ctx.setLineDash !== undefined) { if (ctx.setLineDash !== undefined) {
@ -29899,8 +29901,8 @@ return /******/ (function(modules) { // webpackBootstrap
return NodeBase; return NodeBase;
})(); })();
exports['default'] = NodeBase;
module.exports = exports['default'];
exports["default"] = NodeBase;
module.exports = exports["default"];
/***/ }, /***/ },
/* 65 */ /* 65 */
@ -31359,6 +31361,7 @@ return /******/ (function(modules) { // webpackBootstrap
selfReferenceSize: 20, selfReferenceSize: 20,
shadow: { shadow: {
enabled: false, enabled: false,
color: 'rgba(0,0,0,0.5)',
size: 10, size: 10,
x: 5, x: 5,
y: 5 y: 5
@ -31395,7 +31398,7 @@ return /******/ (function(modules) { // webpackBootstrap
var edge = _this2.body.edges[edgeId]; var edge = _this2.body.edges[edgeId];
var edgeData = _this2.body.data.edges._data[edgeId]; var edgeData = _this2.body.data.edges._data[edgeId];
// only forcilby remove the smooth curve if the data has been set of the edge has the smooth curves defined.
// only forcibly remove the smooth curve if the data has been set of the edge has the smooth curves defined.
// this is because a change in the global would not affect these curves. // this is because a change in the global would not affect these curves.
if (edgeData !== undefined) { if (edgeData !== undefined) {
var edgeOptions = edgeData.smooth; var edgeOptions = edgeData.smooth;
@ -31441,7 +31444,7 @@ return /******/ (function(modules) { // webpackBootstrap
// use the parser from the Edge class to fill in all shorthand notations // use the parser from the Edge class to fill in all shorthand notations
_componentsEdge2['default'].parseOptions(this.options, options); _componentsEdge2['default'].parseOptions(this.options, options);
// hanlde multiple input cases for color
// handle multiple input cases for color
if (options.color !== undefined) { if (options.color !== undefined) {
this.markAllEdgesAsDirty(); this.markAllEdgesAsDirty();
} }
@ -32192,7 +32195,7 @@ return /******/ (function(modules) { // webpackBootstrap
parentOptions.scaling = Object.create(globalOptions.scaling); // this sets the pointer of the option back to the global option. parentOptions.scaling = Object.create(globalOptions.scaling); // this sets the pointer of the option back to the global option.
} }
// hanlde multiple input cases for arrows
// handle multiple input cases for arrows
if (newOptions.arrows !== undefined && newOptions.arrows !== null) { if (newOptions.arrows !== undefined && newOptions.arrows !== null) {
if (typeof newOptions.arrows === 'string') { if (typeof newOptions.arrows === 'string') {
var arrows = newOptions.arrows.toLowerCase(); var arrows = newOptions.arrows.toLowerCase();
@ -32216,7 +32219,7 @@ return /******/ (function(modules) { // webpackBootstrap
parentOptions.arrows = Object.create(globalOptions.arrows); // this sets the pointer of the option back to the global option. parentOptions.arrows = Object.create(globalOptions.arrows); // this sets the pointer of the option back to the global option.
} }
// hanlde multiple input cases for color
// handle multiple input cases for color
if (newOptions.color !== undefined && newOptions.color !== null) { if (newOptions.color !== undefined && newOptions.color !== null) {
// make a copy of the parent object in case this is referring to the global one (due to object create once, then update) // make a copy of the parent object in case this is referring to the global one (due to object create once, then update)
parentOptions.color = util.deepExtend({}, parentOptions.color, true); parentOptions.color = util.deepExtend({}, parentOptions.color, true);
@ -33213,7 +33216,7 @@ return /******/ (function(modules) { // webpackBootstrap
key: 'enableShadow', key: 'enableShadow',
value: function enableShadow(ctx) { value: function enableShadow(ctx) {
if (this.options.shadow.enabled === true) { if (this.options.shadow.enabled === true) {
ctx.shadowColor = 'rgba(0,0,0,0.5)';
ctx.shadowColor = this.options.shadow.color;
ctx.shadowBlur = this.options.shadow.size; ctx.shadowBlur = this.options.shadow.size;
ctx.shadowOffsetX = this.options.shadow.x; ctx.shadowOffsetX = this.options.shadow.x;
ctx.shadowOffsetY = this.options.shadow.y; ctx.shadowOffsetY = this.options.shadow.y;
@ -33310,7 +33313,7 @@ return /******/ (function(modules) { // webpackBootstrap
if (this.from === undefined || this.to === undefined || this.options.physics === false) { if (this.from === undefined || this.to === undefined || this.options.physics === false) {
this.via.setOptions({ physics: false }); this.via.setOptions({ physics: false });
} else { } else {
// fix weird behaviour where a selfreferencing node has physics enabled
// fix weird behaviour where a self referencing node has physics enabled
if (this.from.id === this.to.id) { if (this.from.id === this.to.id) {
this.via.setOptions({ physics: false }); this.via.setOptions({ physics: false });
} else { } else {
@ -34100,7 +34103,7 @@ return /******/ (function(modules) { // webpackBootstrap
} }
/** /**
* The viewFunction inserts this step into each renderloop. It calls the physics tick and handles the cleanup at stabilized.
* The viewFunction inserts this step into each render loop. It calls the physics tick and handles the cleanup at stabilized.
* *
*/ */
}, { }, {
@ -34240,7 +34243,7 @@ return /******/ (function(modules) { // webpackBootstrap
for (var nodeId in nodes) { for (var nodeId in nodes) {
if (nodes.hasOwnProperty(nodeId)) { if (nodes.hasOwnProperty(nodeId)) {
if (nodes[nodeId].options.physics === true) { if (nodes[nodeId].options.physics === true) {
this.physicsBody.physicsNodeIndices.push(nodeId);
this.physicsBody.physicsNodeIndices.push(nodes[nodeId].id);
} }
} }
} }
@ -34249,7 +34252,7 @@ return /******/ (function(modules) { // webpackBootstrap
for (var edgeId in edges) { for (var edgeId in edges) {
if (edges.hasOwnProperty(edgeId)) { if (edges.hasOwnProperty(edgeId)) {
if (edges[edgeId].options.physics === true) { if (edges[edgeId].options.physics === true) {
this.physicsBody.physicsEdgeIndices.push(edgeId);
this.physicsBody.physicsEdgeIndices.push(edges[edgeId].id);
} }
} }
} }
@ -34331,7 +34334,7 @@ return /******/ (function(modules) { // webpackBootstrap
} }
/** /**
* move the nodes one timestap and check if they are stabilized
* move the nodes one timestep and check if they are stabilized
* @returns {boolean} * @returns {boolean}
*/ */
}, { }, {
@ -36474,7 +36477,7 @@ return /******/ (function(modules) { // webpackBootstrap
var containedNodes = this.body.nodes[clusterId].containedNodes; var containedNodes = this.body.nodes[clusterId].containedNodes;
for (var nodeId in containedNodes) { for (var nodeId in containedNodes) {
if (containedNodes.hasOwnProperty(nodeId)) { if (containedNodes.hasOwnProperty(nodeId)) {
nodesArray.push(nodeId);
nodesArray.push(this.body.nodes[nodeId].id);
} }
} }
} }
@ -36495,11 +36498,11 @@ return /******/ (function(modules) { // webpackBootstrap
var counter = 0; var counter = 0;
while (this.clusteredNodes[nodeId] !== undefined && counter < max) { while (this.clusteredNodes[nodeId] !== undefined && counter < max) {
stack.push(nodeId);
stack.push(this.body.nodes[nodeId].id);
nodeId = this.clusteredNodes[nodeId].clusterId; nodeId = this.clusteredNodes[nodeId].clusterId;
counter++; counter++;
} }
stack.push(nodeId);
stack.push(this.body.nodes[nodeId].id);
stack.reverse(); stack.reverse();
return stack; return stack;
@ -39745,7 +39748,7 @@ return /******/ (function(modules) { // webpackBootstrap
if (this.options.selectable === true) { if (this.options.selectable === true) {
for (var nodeId in this.selectionObj.nodes) { for (var nodeId in this.selectionObj.nodes) {
if (this.selectionObj.nodes.hasOwnProperty(nodeId)) { if (this.selectionObj.nodes.hasOwnProperty(nodeId)) {
idArray.push(nodeId);
idArray.push(this.selectionObj.nodes[nodeId].id);
} }
} }
} }
@ -39765,7 +39768,7 @@ return /******/ (function(modules) { // webpackBootstrap
if (this.options.selectable === true) { if (this.options.selectable === true) {
for (var edgeId in this.selectionObj.edges) { for (var edgeId in this.selectionObj.edges) {
if (this.selectionObj.edges.hasOwnProperty(edgeId)) { if (this.selectionObj.edges.hasOwnProperty(edgeId)) {
idArray.push(edgeId);
idArray.push(this.selectionObj.edges[edgeId].id);
} }
} }
} }
@ -42042,6 +42045,7 @@ return /******/ (function(modules) { // webpackBootstrap
selfReferenceSize: { number: number }, selfReferenceSize: { number: number },
shadow: { shadow: {
enabled: { boolean: boolean }, enabled: { boolean: boolean },
color: { string: string },
size: { number: number }, size: { number: number },
x: { number: number }, x: { number: number },
y: { number: number }, y: { number: number },
@ -42174,6 +42178,7 @@ return /******/ (function(modules) { // webpackBootstrap
}, },
shadow: { shadow: {
enabled: { boolean: boolean }, enabled: { boolean: boolean },
color: { string: string },
size: { number: number }, size: { number: number },
x: { number: number }, x: { number: number },
y: { number: number }, y: { number: number },

+ 7
- 0
docs/network/edges.html View File

@ -166,6 +166,7 @@ var options = {
selfReferenceSize:20, selfReferenceSize:20,
shadow:{ shadow:{
enabled: false, enabled: false,
color: 'rgba(0,0,0,0.5)',
size:10, size:10,
x:5, x:5,
y:5 y:5
@ -581,6 +582,12 @@ var options: {
in this object are defined. in this object are defined.
</td> </td>
</tr> </tr>
<tr parent="shadow" class="hidden">
<td class="indent">shadow.color</td>
<td>String</td>
<td><code>'rgba(0,0,0,0.5)'</code></td>
<td>The color size of the shadow as a string. Supported formats are 'rgb(255,255,255)', 'rgba(255,255,255,1)' and '#FFFFFF'.</td>
</tr>
<tr parent="shadow" class="hidden"> <tr parent="shadow" class="hidden">
<td class="indent">shadow.size</td> <td class="indent">shadow.size</td>
<td>Number</td> <td>Number</td>

+ 7
- 0
docs/network/nodes.html View File

@ -171,6 +171,7 @@ var options = {
}, },
shadow:{ shadow:{
enabled: false, enabled: false,
color: 'rgba(0,0,0,0.5)',
size:10, size:10,
x:5, x:5,
y:5 y:5
@ -585,6 +586,12 @@ mySize = minSize + diff * scale;
in this object are defined. in this object are defined.
</td> </td>
</tr> </tr>
<tr parent="shadow" class="hidden">
<td class="indent">shadow.color</td>
<td>String</td>
<td><code>'rgba(0,0,0,0.5)'</code></td>
<td>The color size of the shadow as a string. Supported formats are 'rgb(255,255,255)', 'rgba(255,255,255,1)' and '#FFFFFF'.</td>
</tr>
<tr parent="shadow" class="hidden"> <tr parent="shadow" class="hidden">
<td class="indent">shadow.size</td> <td class="indent">shadow.size</td>
<td>Number</td> <td>Number</td>

+ 1
- 1
examples/network/nodeStyles/shadows.html View File

@ -87,7 +87,7 @@
{from: 25, to: 24}, {from: 25, to: 24},
{from: 26, to: 25}, {from: 26, to: 25},
{from: 25, to: 7}, {from: 25, to: 7},
{from: 28, to: 27},
{from: 28, to: 27, shadow:{color:'rgb(0,255,0)'}},
{from: 29, to: 28}, {from: 29, to: 28},
{from: 28, to: 0} {from: 28, to: 0}
] ]

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

@ -247,7 +247,7 @@ Network.prototype._updateVisibleIndices = function () {
for (let nodeId in nodes) { for (let nodeId in nodes) {
if (nodes.hasOwnProperty(nodeId)) { if (nodes.hasOwnProperty(nodeId)) {
if (nodes[nodeId].options.hidden === false) { if (nodes[nodeId].options.hidden === false) {
this.body.nodeIndices.push(nodeId);
this.body.nodeIndices.push(nodes[nodeId].id);
} }
} }
} }
@ -255,7 +255,7 @@ Network.prototype._updateVisibleIndices = function () {
for (let edgeId in edges) { for (let edgeId in edges) {
if (edges.hasOwnProperty(edgeId)) { if (edges.hasOwnProperty(edgeId)) {
if (edges[edgeId].options.hidden === false) { if (edges[edgeId].options.hidden === false) {
this.body.edgeIndices.push(edgeId);
this.body.edgeIndices.push(edges[edgeId].id);
} }
} }
} }

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

@ -662,12 +662,12 @@ class ClusterEngine {
} }
getNodesInCluster(clusterId) { getNodesInCluster(clusterId) {
let nodesArray = []
let nodesArray = [];
if (this.isCluster(clusterId) === true) { if (this.isCluster(clusterId) === true) {
let containedNodes = this.body.nodes[clusterId].containedNodes; let containedNodes = this.body.nodes[clusterId].containedNodes;
for (let nodeId in containedNodes) { for (let nodeId in containedNodes) {
if (containedNodes.hasOwnProperty(nodeId)) { if (containedNodes.hasOwnProperty(nodeId)) {
nodesArray.push(nodeId)
nodesArray.push(this.body.nodes[nodeId].id)
} }
} }
} }
@ -686,11 +686,11 @@ class ClusterEngine {
let counter = 0; let counter = 0;
while (this.clusteredNodes[nodeId] !== undefined && counter < max) { while (this.clusteredNodes[nodeId] !== undefined && counter < max) {
stack.push(nodeId);
stack.push(this.body.nodes[nodeId].id);
nodeId = this.clusteredNodes[nodeId].clusterId; nodeId = this.clusteredNodes[nodeId].clusterId;
counter++; counter++;
} }
stack.push(nodeId);
stack.push(this.body.nodes[nodeId].id);
stack.reverse(); stack.reverse();
return stack; return stack;

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

@ -74,6 +74,7 @@ class EdgesHandler {
selfReferenceSize:20, selfReferenceSize:20,
shadow:{ shadow:{
enabled: false, enabled: false,
color: 'rgba(0,0,0,0.5)',
size:10, size:10,
x:5, x:5,
y:5 y:5
@ -106,7 +107,7 @@ class EdgesHandler {
let edge = this.body.edges[edgeId]; let edge = this.body.edges[edgeId];
let edgeData = this.body.data.edges._data[edgeId]; let edgeData = this.body.data.edges._data[edgeId];
// only forcilby remove the smooth curve if the data has been set of the edge has the smooth curves defined.
// only forcibly remove the smooth curve if the data has been set of the edge has the smooth curves defined.
// this is because a change in the global would not affect these curves. // this is because a change in the global would not affect these curves.
if (edgeData !== undefined) { if (edgeData !== undefined) {
let edgeOptions = edgeData.smooth; let edgeOptions = edgeData.smooth;
@ -153,7 +154,7 @@ class EdgesHandler {
// use the parser from the Edge class to fill in all shorthand notations // use the parser from the Edge class to fill in all shorthand notations
Edge.parseOptions(this.options, options); Edge.parseOptions(this.options, options);
// hanlde multiple input cases for color
// handle multiple input cases for color
if (options.color !== undefined) { if (options.color !== undefined) {
this.markAllEdgesAsDirty(); this.markAllEdgesAsDirty();
} }

+ 4
- 3
lib/network/modules/NodesHandler.js View File

@ -87,6 +87,7 @@ class NodesHandler {
}, },
shadow: { shadow: {
enabled: false, enabled: false,
color: 'rgba(0,0,0,0.5)',
size: 10, size: 10,
x: 5, x: 5,
y: 5 y: 5
@ -356,7 +357,7 @@ class NodesHandler {
if (dataset._data.hasOwnProperty(nodeId)) { if (dataset._data.hasOwnProperty(nodeId)) {
let node = this.body.nodes[nodeId]; let node = this.body.nodes[nodeId];
if (dataset._data[nodeId].x != Math.round(node.x) || dataset._data[nodeId].y != Math.round(node.y)) { if (dataset._data[nodeId].x != Math.round(node.x) || dataset._data[nodeId].y != Math.round(node.y)) {
dataArray.push({ id: nodeId, x: Math.round(node.x), y: Math.round(node.y) });
dataArray.push({ id: node.id, x: Math.round(node.x), y: Math.round(node.y) });
} }
} }
} }
@ -387,13 +388,13 @@ class NodesHandler {
let nodeObj = {}; // used to quickly check if node already exists let nodeObj = {}; // used to quickly check if node already exists
for (let i = 0; i < node.edges.length; i++) { for (let i = 0; i < node.edges.length; i++) {
let edge = node.edges[i]; let edge = node.edges[i];
if (edge.toId == nodeId) { // these are double equals since ids can be numeric or string
if (edge.toId == node.id) { // these are double equals since ids can be numeric or string
if (nodeObj[edge.fromId] === undefined) { if (nodeObj[edge.fromId] === undefined) {
nodeList.push(edge.fromId); nodeList.push(edge.fromId);
nodeObj[edge.fromId] = true; nodeObj[edge.fromId] = true;
} }
} }
else if (edge.fromId == nodeId) { // these are double equals since ids can be numeric or string
else if (edge.fromId == node.id) { // these are double equals since ids can be numeric or string
if (nodeObj[edge.toId] === undefined) { if (nodeObj[edge.toId] === undefined) {
nodeList.push(edge.toId); nodeList.push(edge.toId);
nodeObj[edge.toId] = true; nodeObj[edge.toId] = true;

+ 5
- 5
lib/network/modules/PhysicsEngine.js View File

@ -137,7 +137,7 @@ class PhysicsEngine {
else { else {
this.physicsEnabled = true; this.physicsEnabled = true;
util.selectiveNotDeepExtend(['stabilization'], this.options, options); util.selectiveNotDeepExtend(['stabilization'], this.options, options);
util.mergeOptions(this.options, options, 'stabilization')
util.mergeOptions(this.options, options, 'stabilization');
if (options.enabled === undefined) { if (options.enabled === undefined) {
this.options.enabled = true; this.options.enabled = true;
@ -254,7 +254,7 @@ class PhysicsEngine {
/** /**
* The viewFunction inserts this step into each renderloop. It calls the physics tick and handles the cleanup at stabilized.
* The viewFunction inserts this step into each render loop. It calls the physics tick and handles the cleanup at stabilized.
* *
*/ */
simulationStep() { simulationStep() {
@ -386,7 +386,7 @@ class PhysicsEngine {
for (let nodeId in nodes) { for (let nodeId in nodes) {
if (nodes.hasOwnProperty(nodeId)) { if (nodes.hasOwnProperty(nodeId)) {
if (nodes[nodeId].options.physics === true) { if (nodes[nodeId].options.physics === true) {
this.physicsBody.physicsNodeIndices.push(nodeId);
this.physicsBody.physicsNodeIndices.push(nodes[nodeId].id);
} }
} }
} }
@ -395,7 +395,7 @@ class PhysicsEngine {
for (let edgeId in edges) { for (let edgeId in edges) {
if (edges.hasOwnProperty(edgeId)) { if (edges.hasOwnProperty(edgeId)) {
if (edges[edgeId].options.physics === true) { if (edges[edgeId].options.physics === true) {
this.physicsBody.physicsEdgeIndices.push(edgeId);
this.physicsBody.physicsEdgeIndices.push(edges[edgeId].id);
} }
} }
} }
@ -473,7 +473,7 @@ class PhysicsEngine {
} }
/** /**
* move the nodes one timestap and check if they are stabilized
* move the nodes one timestep and check if they are stabilized
* @returns {boolean} * @returns {boolean}
*/ */
moveNodes() { moveNodes() {

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

@ -572,7 +572,7 @@ class SelectionHandler {
if (this.options.selectable === true) { if (this.options.selectable === true) {
for (let nodeId in this.selectionObj.nodes) { for (let nodeId in this.selectionObj.nodes) {
if (this.selectionObj.nodes.hasOwnProperty(nodeId)) { if (this.selectionObj.nodes.hasOwnProperty(nodeId)) {
idArray.push(nodeId);
idArray.push(this.selectionObj.nodes[nodeId].id);
} }
} }
} }
@ -590,7 +590,7 @@ class SelectionHandler {
if (this.options.selectable === true) { if (this.options.selectable === true) {
for (let edgeId in this.selectionObj.edges) { for (let edgeId in this.selectionObj.edges) {
if (this.selectionObj.edges.hasOwnProperty(edgeId)) { if (this.selectionObj.edges.hasOwnProperty(edgeId)) {
idArray.push(edgeId);
idArray.push(this.selectionObj.edges[edgeId].id);
} }
} }
} }

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

@ -137,7 +137,7 @@ class Edge {
parentOptions.scaling = Object.create(globalOptions.scaling); // this sets the pointer of the option back to the global option. parentOptions.scaling = Object.create(globalOptions.scaling); // this sets the pointer of the option back to the global option.
} }
// hanlde multiple input cases for arrows
// handle multiple input cases for arrows
if (newOptions.arrows !== undefined && newOptions.arrows !== null) { if (newOptions.arrows !== undefined && newOptions.arrows !== null) {
if (typeof newOptions.arrows === 'string') { if (typeof newOptions.arrows === 'string') {
let arrows = newOptions.arrows.toLowerCase(); let arrows = newOptions.arrows.toLowerCase();
@ -158,7 +158,7 @@ class Edge {
parentOptions.arrows = Object.create(globalOptions.arrows); // this sets the pointer of the option back to the global option. parentOptions.arrows = Object.create(globalOptions.arrows); // this sets the pointer of the option back to the global option.
} }
// hanlde multiple input cases for color
// handle multiple input cases for color
if (newOptions.color !== undefined && newOptions.color !== null) { if (newOptions.color !== undefined && newOptions.color !== null) {
// make a copy of the parent object in case this is referring to the global one (due to object create once, then update) // make a copy of the parent object in case this is referring to the global one (due to object create once, then update)
parentOptions.color = util.deepExtend({}, parentOptions.color, true); parentOptions.color = util.deepExtend({}, parentOptions.color, true);

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

@ -162,6 +162,8 @@ class Node {
* Static so it can also be used by the handler. * Static so it can also be used by the handler.
* @param parentOptions * @param parentOptions
* @param newOptions * @param newOptions
* @param allowDeletion
* @param globalOptions
*/ */
static parseOptions(parentOptions, newOptions, allowDeletion = false, globalOptions = {}) { static parseOptions(parentOptions, newOptions, allowDeletion = false, globalOptions = {}) {
var fields = [ var fields = [

+ 1
- 1
lib/network/modules/components/edges/BezierEdgeDynamic.js View File

@ -39,7 +39,7 @@ class BezierEdgeDynamic extends BezierEdgeBase {
this.via.setOptions({physics:false}) this.via.setOptions({physics:false})
} }
else { else {
// fix weird behaviour where a selfreferencing node has physics enabled
// fix weird behaviour where a self referencing node has physics enabled
if (this.from.id === this.to.id) { if (this.from.id === this.to.id) {
this.via.setOptions({physics: false}) this.via.setOptions({physics: false})
} }

+ 1
- 1
lib/network/modules/components/edges/util/EdgeBase.js View File

@ -504,7 +504,7 @@ class EdgeBase {
enableShadow(ctx) { enableShadow(ctx) {
if (this.options.shadow.enabled === true) { if (this.options.shadow.enabled === true) {
ctx.shadowColor = 'rgba(0,0,0,0.5)';
ctx.shadowColor = this.options.shadow.color;
ctx.shadowBlur = this.options.shadow.size; ctx.shadowBlur = this.options.shadow.size;
ctx.shadowOffsetX = this.options.shadow.x; ctx.shadowOffsetX = this.options.shadow.x;
ctx.shadowOffsetY = this.options.shadow.y; ctx.shadowOffsetY = this.options.shadow.y;

+ 1
- 1
lib/network/modules/components/nodes/util/NodeBase.js View File

@ -25,7 +25,7 @@ class NodeBase {
enableShadow(ctx) { enableShadow(ctx) {
if (this.options.shadow.enabled === true) { if (this.options.shadow.enabled === true) {
ctx.shadowColor = 'rgba(0,0,0,0.5)';
ctx.shadowColor = this.options.shadow.color;
ctx.shadowBlur = this.options.shadow.size; ctx.shadowBlur = this.options.shadow.size;
ctx.shadowOffsetX = this.options.shadow.x; ctx.shadowOffsetX = this.options.shadow.x;
ctx.shadowOffsetY = this.options.shadow.y; ctx.shadowOffsetY = this.options.shadow.y;

+ 2
- 0
lib/network/options.js View File

@ -72,6 +72,7 @@ let allOptions = {
selfReferenceSize: { number }, selfReferenceSize: { number },
shadow: { shadow: {
enabled: { boolean }, enabled: { boolean },
color: { string },
size: { number }, size: { number },
x: { number }, x: { number },
y: { number }, y: { number },
@ -204,6 +205,7 @@ let allOptions = {
}, },
shadow: { shadow: {
enabled: { boolean }, enabled: { boolean },
color: { string },
size: { number }, size: { number },
x: { number }, x: { number },
y: { number }, y: { number },

+ 0
- 1
lib/util.js View File

@ -1278,7 +1278,6 @@ exports.insertSort = function (a,compare) {
* @param [object] mergeTarget | this is either this.options or the options used for the groups. * @param [object] mergeTarget | this is either this.options or the options used for the groups.
* @param [object] options | options * @param [object] options | options
* @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
*/ */
exports.mergeOptions = function (mergeTarget, options, option, allowDeletion = false, globalOptions = {}) { exports.mergeOptions = function (mergeTarget, options, option, allowDeletion = false, globalOptions = {}) {
if (options[option] === null) { if (options[option] === null) {

+ 42
- 101
test/networkTest.html View File

@ -18,121 +18,62 @@
<div id="network"></div> <div id="network"></div>
<script> <script>
var nodes = new vis.DataSet([ var nodes = new vis.DataSet([
{"id":317,"label":"Start - BTN\n317\nSection","x":-817,"y":-24,"group":"Section"},
{"id":318,"label":"End Call\n318\nHangup","x":-933,"y":-175,"group":"Hangup"},
{"id":319,"label":"Call Error\n319\nSpeak","x":-727,"y":-175,"group":"Speak"}, {"id":320,"label":"Welcome\n320\nSpeak","x":-563,"y":-14,"group":"Speak"},
{"id":321,"label":"Enter TN\n321\nPrompt","x":-326,"y":-7,"group":"Prompt"},
{"id":322,"label":"CheckIsTenDigits\n322\nWebService","x":-84,"y":-5,"group":"WebService"},
{"id":323,"label":"VerifyIsTenDigits\n323\nCase","x":207,"y":-4,"group":"Case"},
{"id":324,"label":"CheckIsValidTN\n324\nWebService","x":492,"y":-10,"group":"WebService"},
{"id":325,"label":"Not Ten Digits\n325\nSpeak","x":-76,"y":-274,"group":"Speak"},
{"id":326,"label":"VerifyIsValidTN\n326\nCase","x":821,"y":-9,"group":"Case"},
{"id":327,"label":"Verify TN Is Correct\n327\nPrompt","x":812,"y":265,"group":"Prompt"},
{"id":328,"label":"Not Valid TN\n328\nSpeak","x":499,"y":-210,"group":"Speak"},
{"id":329,"label":"BTN Is Valid\n329\nSpeak","x":812,"y":397,"group":"Speak"},
{"id":330,"label":"Validate TPV ID\n330\nSection","x":708,"y":592,"group":"Section"},
{"id":331,"label":"End Section End Call\n331\nHangup","x":1040,"y":478,"group":"Hangup"},
{"id":332,"label":"Say BTN\n332\nSpeak","x":820,"y":113,"group":"Speak"},
{"id":333,"label":"Get TPV ID\n333\nWebService","x":800,"y":824,"group":"WebService"},
{"id":334,"label":"TPV ID Error\n334\nSpeak","x":1037,"y":682,"group":"Speak"},
{"id":335,"label":"Verify TPV ID Is Valid\n335\nCase","x":798,"y":1059,"group":"Case"},
{"id":336,"label":"TPV ID Is valid\n336\nSpeak","x":802,"y":1304,"group":"Speak"},
{"id":337,"label":"End Call\n337\nSection","x":828,"y":1605,"group":"Section"},
{"id":338,"label":"TPV ID Not Found\n338\nSpeak","x":1211,"y":1055,"group":"Speak"},
{"id":339,"label":"TPV ID End Call\n339\nHangup","x":1074,"y":1616,"group":"Hangup"}
{id: 1, label: '1'},
{id: 2, label: '2'},
{id: 3, label: '3'},
{id: 4, label: '4'},
{id: 5, label: '5'},
{id: 6, label: '6'},
{id: 7, label: '7'},
]); ]);
var edges = new vis.DataSet([ var edges = new vis.DataSet([
{"id":353,"from":317,"to":318,"label":"Hangup"},{"id":354,"from":317,"to":318,"label":"CcHangup"},{"id":355,"from":317,"to":319,"label":"Error"},{"id":356,"from":319,"to":318,"label":"Continue"},{"id":357,"from":319,"to":318,"label":"Error"},{"id":358,"from":319,"to":318,"label":"Hangup"},{"id":359,"from":317,"to":320,"label":"Continue"},{"id":360,"from":320,"to":321,"label":"Continue"},{"id":361,"from":321,"to":322,"label":"1"},{"id":362,"from":322,"to":323,"label":"Continue"},{"id":363,"from":323,"to":324,"label":"1"},{"id":364,"from":323,"to":325,"label":"2"},{"id":365,"from":325,"to":321,"label":"Continue"},{"id":366,"from":324,"to":326,"label":"Continue"},{"id":367,"from":326,"to":332,"label":"1"},{"id":368,"from":326,"to":328,"label":"2"},{"id":369,"from":327,"to":332,"label":"3"},{"id":370,"from":327,"to":321,"label":"2"},{"id":371,"from":328,"to":321,"label":"Continue"},{"id":372,"from":327,"to":329,"label":"1"},{"id":373,"from":329,"to":330,"label":"Continue"},{"id":374,"from":330,"to":333,"label":"Continue"},{"id":375,"from":330,"to":331,"label":"Hangup"},{"id":376,"from":332,"to":327,"label":"Continue"},{"id":377,"from":330,"to":334,"label":"Error"},{"id":378,"from":334,"to":331,"label":"Continue"},{"id":379,"from":333,"to":335,"label":"Continue"},{"id":380,"from":335,"to":336,"label":"1"},{"id":381,"from":336,"to":337,"label":"Continue"},{"id":382,"from":335,"to":338,"label":"0"},{"id":383,"from":338,"to":337,"label":"Continue"},{"id":384,"from":337,"to":339,"label":"Continue"}
{id: "e1", from: 2, to: 1, label: "e1"},
{id: "e2", from: 3, to: 1, label: "e2"},
{id: "e3", from: 4, to: 1, label: "e3"},
{id: "e4", from: 5, to: 1, label: "e4"},
{id: "e5", from: 6, to: 1, label: "e5"},
{id: "e6", from: 2, to: 7, label: "e6"},
{id: "e7", from: 3, to: 7, label: "e7"},
{id: "e8", from: 4, to: 7, label: "e8"},
{id: "e9", from: 5, to: 7, label: "e9"},
{id: "e10", from: 6, to: 7, label: "e10"},
]); ]);
// create a network
var container = document.getElementById('network'); var container = document.getElementById('network');
var data = { var data = {
edges: edges,
nodes: nodes
nodes: nodes,
edges: edges
}; };
var options = { var options = {
manipulation: {
initiallyActive: true,
addNode: true,
addEdge: true,
editEdge: true,
deleteNode: true,
deleteEdge: true
},
nodes: {
physics: false,
},
layout: {randomSeed: 8},
edges: { edges: {
physics: false,
arrows: 'to',
smooth: {
enabled: true,
type: 'continuous'
}
},
interaction: {
dragNodes: true,
dragView: true,
hover: true,
keyboard: {
enabled: true,
bindToWindow: false
},
navigationButtons: true,
selectable: true,
selectConnectedEdges: true,
hoverConnectedEdges: true,
zoomView: true
},
groups: {
Assignment: {
shape: 'box',
color: '#6699ff'
},
Hangup: {
shape: 'box',
color: '#b8b8b8'
},
Prompt: {
shape: 'box',
color: '#00ffff'
},
Section: {
shape: 'circle',
color: '#66ff66'
},
Speak: {
shape: 'box',
color: '#ffff66'
},
StartRecording: {
shape: 'box',
color: '#ff5050'
arrows: {
to: {
scaleFactor: 0.5
}
}, },
StopRecording: {
shape: 'box',
color: '#ff5050'
},
Transfer: {
shape: 'box',
color: '#ff66ff'
},
TransferAgent: {
shape: 'box',
color: '#ff9900'
},
Case: {
shape: 'box',
color: '#33cccc'
},
WebService: {
shape: 'box',
color: '#33cc33'
font: {
align: "middle"
} }
} }
}; };
var network = new vis.Network(container, data, options); var network = new vis.Network(container, data, options);
var clusterOptionsByData = {
joinCondition: function(node) {
if (node.id > 1 && node.id < 7)
return true;
return false;
},
clusterNodeProperties: {id:"c1", label:'c1'}
};
network.cluster(clusterOptionsByData);
setTimeout(function() {
network.setOptions({layout: { hierarchical: { direction: "LR" }}});
},2000)
</script> </script>
</body> </body>
</html> </html>

Loading…
Cancel
Save