Browse Source

Released version 4.15.0

gh-pages
jos 8 years ago
parent
commit
3703b4ecbf
14 changed files with 315 additions and 220 deletions
  1. +1
    -1
      dist/vis.css
  2. +237
    -170
      dist/vis.js
  3. +1
    -1
      dist/vis.map
  4. +1
    -1
      dist/vis.min.css
  5. +22
    -22
      dist/vis.min.js
  6. +12
    -7
      docs/graph2d/index.html
  7. +8
    -8
      docs/network/index.html
  8. +2
    -0
      docs/network/layout.html
  9. +8
    -0
      docs/network/nodes.html
  10. +11
    -0
      docs/timeline/index.html
  11. BIN
      download/vis.zip
  12. +4
    -0
      examples/network/layout/hierarchicalLayoutWithoutPhysics.html
  13. +3
    -5
      examples/network/nodeStyles/customGroups.html
  14. +5
    -5
      index.html

+ 1
- 1
dist/vis.css View File

@ -1056,7 +1056,7 @@ div.vis-network-tooltip {
font-family: verdana;
font-size:14px;
font-color:#000000;
color:#000000;
background-color: #f5f4ed;
-moz-border-radius: 3px;

+ 237
- 170
dist/vis.js View File

@ -4,8 +4,8 @@
*
* A dynamic, browser-based visualization library.
*
* @version 4.14.0
* @date 2016-02-04
* @version 4.15.0
* @date 2016-02-23
*
* @license
* Copyright (C) 2011-2016 Almende B.V, http://almende.com
@ -9343,7 +9343,7 @@ return /******/ (function(modules) { // webpackBootstrap
if (typeof this.showTooltip === 'function') {
content.innerHTML = this.showTooltip(dataPoint.point);
} else {
content.innerHTML = '<table>' + '<tr><td>x:</td><td>' + dataPoint.point.x + '</td></tr>' + '<tr><td>y:</td><td>' + dataPoint.point.y + '</td></tr>' + '<tr><td>z:</td><td>' + dataPoint.point.z + '</td></tr>' + '</table>';
content.innerHTML = '<table>' + '<tr><td>' + this.xLabel + ':</td><td>' + dataPoint.point.x + '</td></tr>' + '<tr><td>' + this.yLabel + ':</td><td>' + dataPoint.point.y + '</td></tr>' + '<tr><td>' + this.zLabel + ':</td><td>' + dataPoint.point.z + '</td></tr>' + '</table>';
}
content.style.left = '0';
@ -22170,6 +22170,7 @@ return /******/ (function(modules) { // webpackBootstrap
if (interval > 1000) interval = 1000;
me.redraw();
me.body.emitter.emit('currentTimeTick');
// start a renderTimer to adjust for the new time
me.currentTimeTimer = setTimeout(update, interval);
@ -25592,14 +25593,14 @@ return /******/ (function(modules) { // webpackBootstrap
left: {
range: { min: undefined, max: undefined },
format: function format(value) {
return '' + Number.parseFloat(value.toPrecision(3));
return '' + parseFloat(value.toPrecision(3));
},
title: { text: undefined, style: undefined }
},
right: {
range: { min: undefined, max: undefined },
format: function format(value) {
return '' + Number.parseFloat(value.toPrecision(3));
return '' + parseFloat(value.toPrecision(3));
},
title: { text: undefined, style: undefined }
}
@ -28552,6 +28553,7 @@ return /******/ (function(modules) { // webpackBootstrap
shapeProperties: {
borderDashes: false, // only for borders
borderRadius: 6, // only for box shape
interpolation: true, // only for image and circularImage shapes
useImageSize: false, // only for image and circularImage shapes
useBorderWithImage: false // only for image shape
},
@ -30221,8 +30223,35 @@ return /******/ (function(modules) { // webpackBootstrap
// draw shadow if enabled
this.enableShadow(ctx);
// draw image
ctx.drawImage(this.imageObj, this.left, this.top, this.width, this.height);
var factor = this.imageObj.width / this.width / this.body.view.scale;
if (factor > 2 && this.options.shapeProperties.interpolation === true) {
var w = this.imageObj.width;
var h = this.imageObj.height;
var can2 = document.createElement('canvas');
can2.width = w;
can2.height = w;
var ctx2 = can2.getContext('2d');
factor *= 0.5;
w *= 0.5;
h *= 0.5;
ctx2.drawImage(this.imageObj, 0, 0, w, h);
var distance = 0;
var iterations = 1;
while (factor > 2 && iterations < 4) {
ctx2.drawImage(can2, distance, 0, w, h, distance + w, 0, w / 2, h / 2);
distance += w;
factor *= 0.5;
w *= 0.5;
h *= 0.5;
iterations += 1;
}
ctx.drawImage(can2, distance, 0, w, h, this.left, this.top, this.width, this.height);
} else {
// draw image
ctx.drawImage(this.imageObj, this.left, this.top, this.width, this.height);
}
// disable shadows for other elements.
this.disableShadow(ctx);
@ -32129,8 +32158,8 @@ return /******/ (function(modules) { // webpackBootstrap
var arrowData = {};
// restore edge targets to defaults
this.edgeType.fromPoint = this.from;
this.edgeType.toPoint = this.to;
this.edgeType.fromPoint = this.edgeType.from;
this.edgeType.toPoint = this.edgeType.to;
// from and to arrows give a different end point for edges. we set them here
if (this.options.arrows.from.enabled === true) {
@ -38286,8 +38315,8 @@ return /******/ (function(modules) { // webpackBootstrap
var _determineIfDifferent2 = this._determineIfDifferent(previousSelection, currentSelection);
var nodesChanges = _determineIfDifferent2.nodesChanges;
var edgesChanges = _determineIfDifferent2.edgesChanges;
var nodesChanged = _determineIfDifferent2.nodesChanged;
var edgesChanged = _determineIfDifferent2.edgesChanged;
var nodeSelected = false;
@ -38296,15 +38325,15 @@ return /******/ (function(modules) { // webpackBootstrap
this.selectionHandler._generateClickEvent('selectNode', event, pointer);
selected = true;
nodeSelected = true;
} else if (selectedNodesCount - previouslySelectedNodeCount < 0) {
// node was deselected
this.selectionHandler._generateClickEvent('deselectNode', event, pointer, previousSelection);
selected = true;
} else if (selectedNodesCount === previouslySelectedNodeCount && nodesChanges === true) {
} else if (nodesChanged === true && selectedNodesCount > 0) {
this.selectionHandler._generateClickEvent('deselectNode', event, pointer, previousSelection);
this.selectionHandler._generateClickEvent('selectNode', event, pointer);
nodeSelected = true;
selected = true;
} else if (selectedNodesCount - previouslySelectedNodeCount < 0) {
// node was deselected
this.selectionHandler._generateClickEvent('deselectNode', event, pointer, previousSelection);
selected = true;
}
// handle the selected edges
@ -38312,13 +38341,13 @@ return /******/ (function(modules) { // webpackBootstrap
// edge was selected
this.selectionHandler._generateClickEvent('selectEdge', event, pointer);
selected = true;
} else if (selectedEdgesCount - previouslySelectedEdgeCount < 0) {
// edge was deselected
} else if (selectedEdgesCount > 0 && edgesChanged === true) {
this.selectionHandler._generateClickEvent('deselectEdge', event, pointer, previousSelection);
this.selectionHandler._generateClickEvent('selectEdge', event, pointer);
selected = true;
} else if (selectedEdgesCount === previouslySelectedEdgeCount && edgesChanges === true) {
} else if (selectedEdgesCount - previouslySelectedEdgeCount < 0) {
// edge was deselected
this.selectionHandler._generateClickEvent('deselectEdge', event, pointer, previousSelection);
this.selectionHandler._generateClickEvent('selectEdge', event, pointer);
selected = true;
}
@ -38333,37 +38362,37 @@ return /******/ (function(modules) { // webpackBootstrap
* This function checks if the nodes and edges previously selected have changed.
* @param previousSelection
* @param currentSelection
* @returns {{nodesChanges: boolean, edgesChanges: boolean}}
* @returns {{nodesChanged: boolean, edgesChanged: boolean}}
* @private
*/
}, {
key: '_determineIfDifferent',
value: function _determineIfDifferent(previousSelection, currentSelection) {
var nodesChanges = false;
var edgesChanges = false;
var nodesChanged = false;
var edgesChanged = false;
for (var i = 0; i < previousSelection.nodes.length; i++) {
if (currentSelection.nodes.indexOf(previousSelection.nodes[i]) === -1) {
nodesChanges = true;
nodesChanged = true;
}
}
for (var i = 0; i < currentSelection.nodes.length; i++) {
if (previousSelection.nodes.indexOf(previousSelection.nodes[i]) === -1) {
nodesChanges = true;
nodesChanged = true;
}
}
for (var i = 0; i < previousSelection.edges.length; i++) {
if (currentSelection.edges.indexOf(previousSelection.edges[i]) === -1) {
edgesChanges = true;
edgesChanged = true;
}
}
for (var i = 0; i < currentSelection.edges.length; i++) {
if (previousSelection.edges.indexOf(previousSelection.edges[i]) === -1) {
edgesChanges = true;
edgesChanged = true;
}
}
return { nodesChanges: nodesChanges, edgesChanges: edgesChanges };
return { nodesChanged: nodesChanged, edgesChanged: edgesChanged };
}
/**
@ -40083,6 +40112,7 @@ return /******/ (function(modules) { // webpackBootstrap
treeSpacing: 200,
blockShifting: true,
edgeMinimization: true,
parentCentralization: true,
direction: 'UD', // UD, DU, LR, RL
sortMethod: 'hubsize' // hubsize, directed
}
@ -40364,8 +40394,8 @@ return /******/ (function(modules) { // webpackBootstrap
var undefinedLevel = false;
this.hierarchicalLevels = {};
this.lastNodeOnLevel = {};
this.hierarchicalParents = {};
this.hierarchicalChildren = {};
this.hierarchicalChildrenReference = {};
this.hierarchicalParentReference = {};
this.hierarchicalTrees = {};
this.treeIndex = -1;
@ -40447,9 +40477,7 @@ return /******/ (function(modules) { // webpackBootstrap
var treeSizes = getTreeSizes();
for (var i = 0; i < treeSizes.length - 1; i++) {
var diff = treeSizes[i].max - treeSizes[i + 1].min;
if (diff !== _this2.options.hierarchical.treeSpacing) {
shiftTree(i + 1, diff - _this2.options.hierarchical.treeSpacing);
}
shiftTree(i + 1, diff + _this2.options.hierarchical.treeSpacing);
}
};
@ -40458,7 +40486,9 @@ return /******/ (function(modules) { // webpackBootstrap
for (var nodeId in _this2.hierarchicalTrees) {
if (_this2.hierarchicalTrees.hasOwnProperty(nodeId)) {
if (_this2.hierarchicalTrees[nodeId] === index) {
_this2._setPositionForHierarchy(_this2.body.nodes[nodeId], offset, undefined, true);
var node = _this2.body.nodes[nodeId];
var pos = _this2._getPositionForHierarchy(node);
_this2._setPositionForHierarchy(node, pos + offset, undefined, true);
}
}
}
@ -40483,7 +40513,7 @@ return /******/ (function(modules) { // webpackBootstrap
// get the width of all trees
var getTreeSizes = function getTreeSizes() {
var treeWidths = [];
for (var i = 0; i < _this2.treeIndex; i++) {
for (var i = 0; i <= _this2.treeIndex; i++) {
treeWidths.push(getTreeSize(i));
}
return treeWidths;
@ -40492,8 +40522,8 @@ return /******/ (function(modules) { // webpackBootstrap
// get a map of all nodes in this branch
var getBranchNodes = function getBranchNodes(source, map) {
map[source.id] = true;
if (_this2.hierarchicalParents[source.id]) {
var children = _this2.hierarchicalParents[source.id].children;
if (_this2.hierarchicalChildrenReference[source.id]) {
var children = _this2.hierarchicalChildrenReference[source.id];
if (children.length > 0) {
for (var i = 0; i < children.length; i++) {
getBranchNodes(_this2.body.nodes[children[i]], map);
@ -40543,8 +40573,8 @@ return /******/ (function(modules) { // webpackBootstrap
// get the maximum level of a branch.
var getMaxLevel = function getMaxLevel(nodeId) {
var level = _this2.hierarchicalLevels[nodeId];
if (_this2.hierarchicalParents[nodeId]) {
var children = _this2.hierarchicalParents[nodeId].children;
if (_this2.hierarchicalChildrenReference[nodeId]) {
var children = _this2.hierarchicalChildrenReference[nodeId];
if (children.length > 0) {
for (var i = 0; i < children.length; i++) {
level = Math.max(level, getMaxLevel(children[i]));
@ -40563,13 +40593,12 @@ return /******/ (function(modules) { // webpackBootstrap
// check if two nodes have the same parent(s)
var hasSameParent = function hasSameParent(node1, node2) {
var parents1 = _this2.hierarchicalChildren[node1.id];
var parents2 = _this2.hierarchicalChildren[node2.id];
var parents1 = _this2.hierarchicalParentReference[node1.id];
var parents2 = _this2.hierarchicalParentReference[node2.id];
if (parents1 === undefined || parents2 === undefined) {
return false;
}
parents1 = parents1.parents;
parents2 = parents2.parents;
for (var i = 0; i < parents1.length; i++) {
for (var j = 0; j < parents2.length; j++) {
if (parents1[i] == parents2[j]) {
@ -40782,7 +40811,7 @@ return /******/ (function(modules) { // webpackBootstrap
}
if (newPosition !== nodePosition) {
//console.log("moving Node:",diff, minSpace, maxSpace)
//console.log("moving Node:",diff, minSpace, maxSpace);
_this2._setPositionForHierarchy(node, newPosition, undefined, true);
//this.body.emitter.emit("_redraw");
stillShifting = true;
@ -40816,7 +40845,7 @@ return /******/ (function(modules) { // webpackBootstrap
}
};
//// method to remove whitespace between branches. Because we do bottom up, we can center the parents.
// method to remove whitespace between branches. Because we do bottom up, we can center the parents.
var shiftBranchesCloserBottomUp = function shiftBranchesCloserBottomUp(iterations) {
var levels = Object.keys(_this2.distributionOrdering);
levels = levels.reverse();
@ -40837,6 +40866,19 @@ return /******/ (function(modules) { // webpackBootstrap
}
};
// center all parents
var centerAllParentsBottomUp = function centerAllParentsBottomUp() {
var levels = Object.keys(_this2.distributionOrdering);
levels = levels.reverse();
for (var i = 0; i < levels.length; i++) {
var level = levels[i];
var levelNodes = _this2.distributionOrdering[level];
for (var j = 0; j < levelNodes.length; j++) {
_this2._centerParent(levelNodes[j]);
}
}
};
// the actual work is done here.
if (this.options.hierarchical.blockShifting === true) {
shiftBranchesCloserBottomUp(5);
@ -40848,6 +40890,10 @@ return /******/ (function(modules) { // webpackBootstrap
minimizeEdgeLengthBottomUp(20);
}
if (this.options.hierarchical.parentCentralization === true) {
centerAllParentsBottomUp();
}
shiftTrees();
}
@ -40902,16 +40948,16 @@ return /******/ (function(modules) { // webpackBootstrap
}, {
key: '_centerParent',
value: function _centerParent(node) {
if (this.hierarchicalChildren[node.id]) {
var parents = this.hierarchicalChildren[node.id].parents;
if (this.hierarchicalParentReference[node.id]) {
var parents = this.hierarchicalParentReference[node.id];
for (var i = 0; i < parents.length; i++) {
var parentId = parents[i];
var parentNode = this.body.nodes[parentId];
if (this.hierarchicalParents[parentId]) {
if (this.hierarchicalChildrenReference[parentId]) {
// get the range of the children
var minPos = 1e9;
var maxPos = -1e9;
var children = this.hierarchicalParents[parentId].children;
var children = this.hierarchicalChildrenReference[parentId];
if (children.length > 0) {
for (var _i = 0; _i < children.length; _i++) {
var childNode = this.body.nodes[children[_i]];
@ -40956,19 +41002,113 @@ return /******/ (function(modules) { // webpackBootstrap
var nodeArray = Object.keys(distribution[level]);
nodeArray = this._indexArrayToNodes(nodeArray);
this._sortNodeArray(nodeArray);
var handledNodeCount = 0;
for (var i = 0; i < nodeArray.length; i++) {
var node = nodeArray[i];
if (this.positionedNodes[node.id] === undefined) {
this._setPositionForHierarchy(node, this.options.hierarchical.nodeSpacing * i, level);
this.positionedNodes[node.id] = true;
this._placeBranchNodes(node.id, level);
var pos = this.options.hierarchical.nodeSpacing * handledNodeCount;
// we get the X or Y values we need and store them in pos and previousPos. The get and set make sure we get X or Y
if (handledNodeCount > 0) {
pos = this._getPositionForHierarchy(nodeArray[i - 1]) + this.options.hierarchical.nodeSpacing;
}
this._setPositionForHierarchy(node, pos, level);
this._validataPositionAndContinue(node, level, pos);
handledNodeCount++;
}
}
}
}
}
/**
* This is a recursively called function to enumerate the branches from the largest hubs and place the nodes
* on a X position that ensures there will be no overlap.
*
* @param parentId
* @param parentLevel
* @private
*/
}, {
key: '_placeBranchNodes',
value: function _placeBranchNodes(parentId, parentLevel) {
// if this is not a parent, cancel the placing. This can happen with multiple parents to one child.
if (this.hierarchicalChildrenReference[parentId] === undefined) {
return;
}
// get a list of childNodes
var childNodes = [];
for (var i = 0; i < this.hierarchicalChildrenReference[parentId].length; i++) {
childNodes.push(this.body.nodes[this.hierarchicalChildrenReference[parentId][i]]);
}
// use the positions to order the nodes.
this._sortNodeArray(childNodes);
// position the childNodes
for (var i = 0; i < childNodes.length; i++) {
var childNode = childNodes[i];
var childNodeLevel = this.hierarchicalLevels[childNode.id];
// check if the child node is below the parent node and if it has already been positioned.
if (childNodeLevel > parentLevel && this.positionedNodes[childNode.id] === undefined) {
// get the amount of space required for this node. If parent the width is based on the amount of children.
var pos = undefined;
// we get the X or Y values we need and store them in pos and previousPos. The get and set make sure we get X or Y
if (i === 0) {
pos = this._getPositionForHierarchy(this.body.nodes[parentId]);
} else {
pos = this._getPositionForHierarchy(childNodes[i - 1]) + this.options.hierarchical.nodeSpacing;
}
this._setPositionForHierarchy(childNode, pos, childNodeLevel);
this._validataPositionAndContinue(childNode, childNodeLevel, pos);
} else {
return;
}
}
// center the parent nodes.
var minPos = 1e9;
var maxPos = -1e9;
for (var i = 0; i < childNodes.length; i++) {
var childNodeId = childNodes[i].id;
minPos = Math.min(minPos, this._getPositionForHierarchy(this.body.nodes[childNodeId]));
maxPos = Math.max(maxPos, this._getPositionForHierarchy(this.body.nodes[childNodeId]));
}
this._setPositionForHierarchy(this.body.nodes[parentId], 0.5 * (minPos + maxPos), parentLevel);
}
/**
* This method checks for overlap and if required shifts the branch. It also keeps records of positioned nodes.
* Finally it will call _placeBranchNodes to place the branch nodes.
* @param node
* @param level
* @param pos
* @private
*/
}, {
key: '_validataPositionAndContinue',
value: function _validataPositionAndContinue(node, level, pos) {
// if overlap has been detected, we shift the branch
if (this.lastNodeOnLevel[level] !== undefined) {
var previousPos = this._getPositionForHierarchy(this.body.nodes[this.lastNodeOnLevel[level]]);
if (pos - previousPos < this.options.hierarchical.nodeSpacing) {
var diff = previousPos + this.options.hierarchical.nodeSpacing - pos;
var sharedParent = this._findCommonParent(this.lastNodeOnLevel[level], node.id);
this._shiftBlock(sharedParent.withChild, diff);
}
}
// store change in position.
this.lastNodeOnLevel[level] = node.id;
this.positionedNodes[node.id] = true;
this._placeBranchNodes(node.id, level);
}
/**
* Receives an array with node indices and returns an array with the actual node references. Used for sorting based on
* node properties.
@ -41178,14 +41318,14 @@ return /******/ (function(modules) { // webpackBootstrap
if (_this6.hierarchicalLevels[childNode.id] > _this6.hierarchicalLevels[parentNode.id]) {
var parentNodeId = parentNode.id;
var childNodeId = childNode.id;
if (_this6.hierarchicalParents[parentNodeId] === undefined) {
_this6.hierarchicalParents[parentNodeId] = { children: [], amount: 0 };
if (_this6.hierarchicalChildrenReference[parentNodeId] === undefined) {
_this6.hierarchicalChildrenReference[parentNodeId] = [];
}
_this6.hierarchicalParents[parentNodeId].children.push(childNodeId);
if (_this6.hierarchicalChildren[childNodeId] === undefined) {
_this6.hierarchicalChildren[childNodeId] = { parents: [], amount: 0 };
_this6.hierarchicalChildrenReference[parentNodeId].push(childNodeId);
if (_this6.hierarchicalParentReference[childNodeId] === undefined) {
_this6.hierarchicalParentReference[childNodeId] = [];
}
_this6.hierarchicalChildren[childNodeId].parents.push(parentNodeId);
_this6.hierarchicalParentReference[childNodeId].push(parentNodeId);
}
};
@ -41201,11 +41341,21 @@ return /******/ (function(modules) { // webpackBootstrap
}, {
key: '_crawlNetwork',
value: function _crawlNetwork(callback, startingNodeId) {
var _this7 = this;
if (callback === undefined) callback = function () {};
var progress = {};
var crawler = function crawler(node) {
var treeIndex = 0;
var crawler = function crawler(node, tree) {
if (progress[node.id] === undefined) {
if (_this7.hierarchicalTrees[node.id] === undefined) {
_this7.hierarchicalTrees[node.id] = tree;
_this7.treeIndex = Math.max(tree, _this7.treeIndex);
}
progress[node.id] = true;
var childNode = undefined;
for (var i = 0; i < node.edges.length; i++) {
@ -41218,7 +41368,7 @@ return /******/ (function(modules) { // webpackBootstrap
if (node.id !== childNode.id) {
callback(node, childNode, node.edges[i]);
crawler(childNode);
crawler(childNode, tree);
}
}
}
@ -41229,7 +41379,10 @@ return /******/ (function(modules) { // webpackBootstrap
if (startingNodeId === undefined) {
for (var i = 0; i < this.body.nodeIndices.length; i++) {
var node = this.body.nodes[this.body.nodeIndices[i]];
crawler(node);
if (progress[node.id] === undefined) {
crawler(node, treeIndex);
treeIndex += 1;
}
}
} else {
var node = this.body.nodes[startingNodeId];
@ -41241,80 +41394,6 @@ return /******/ (function(modules) { // webpackBootstrap
}
}
/**
* This is a recursively called function to enumerate the branches from the largest hubs and place the nodes
* on a X position that ensures there will be no overlap.
*
* @param parentId
* @param parentLevel
* @private
*/
}, {
key: '_placeBranchNodes',
value: function _placeBranchNodes(parentId, parentLevel) {
// if this is not a parent, cancel the placing. This can happen with multiple parents to one child.
if (this.hierarchicalParents[parentId] === undefined) {
return;
}
// get a list of childNodes
var childNodes = [];
for (var i = 0; i < this.hierarchicalParents[parentId].children.length; i++) {
childNodes.push(this.body.nodes[this.hierarchicalParents[parentId].children[i]]);
}
// use the positions to order the nodes.
this._sortNodeArray(childNodes);
// position the childNodes
for (var i = 0; i < childNodes.length; i++) {
var childNode = childNodes[i];
var childNodeLevel = this.hierarchicalLevels[childNode.id];
// check if the child node is below the parent node and if it has already been positioned.
if (childNodeLevel > parentLevel && this.positionedNodes[childNode.id] === undefined) {
// get the amount of space required for this node. If parent the width is based on the amount of children.
var pos = undefined;
// we get the X or Y values we need and store them in pos and previousPos. The get and set make sure we get X or Y
if (i === 0) {
pos = this._getPositionForHierarchy(this.body.nodes[parentId]);
} else {
pos = this._getPositionForHierarchy(childNodes[i - 1]) + this.options.hierarchical.nodeSpacing;
}
this._setPositionForHierarchy(childNode, pos, childNodeLevel);
// if overlap has been detected, we shift the branch
if (this.lastNodeOnLevel[childNodeLevel] !== undefined) {
var previousPos = this._getPositionForHierarchy(this.body.nodes[this.lastNodeOnLevel[childNodeLevel]]);
if (pos - previousPos < this.options.hierarchical.nodeSpacing) {
var diff = previousPos + this.options.hierarchical.nodeSpacing - pos;
var sharedParent = this._findCommonParent(this.lastNodeOnLevel[childNodeLevel], childNode.id);
this._shiftBlock(sharedParent.withChild, diff);
}
}
// store change in position.
this.lastNodeOnLevel[childNodeLevel] = childNode.id;
this.positionedNodes[childNode.id] = true;
this._placeBranchNodes(childNode.id, childNodeLevel);
} else {
return;
}
}
// center the parent nodes.
var minPos = 1e9;
var maxPos = -1e9;
for (var i = 0; i < childNodes.length; i++) {
var childNodeId = childNodes[i].id;
minPos = Math.min(minPos, this._getPositionForHierarchy(this.body.nodes[childNodeId]));
maxPos = Math.max(maxPos, this._getPositionForHierarchy(this.body.nodes[childNodeId]));
}
this._setPositionForHierarchy(this.body.nodes[parentId], 0.5 * (minPos + maxPos), parentLevel);
}
/**
* Shift a branch a certain distance
* @param parentId
@ -41329,9 +41408,9 @@ return /******/ (function(modules) { // webpackBootstrap
} else {
this.body.nodes[parentId].y += diff;
}
if (this.hierarchicalParents[parentId] !== undefined) {
for (var i = 0; i < this.hierarchicalParents[parentId].children.length; i++) {
this._shiftBlock(this.hierarchicalParents[parentId].children[i], diff);
if (this.hierarchicalChildrenReference[parentId] !== undefined) {
for (var i = 0; i < this.hierarchicalChildrenReference[parentId].length; i++) {
this._shiftBlock(this.hierarchicalChildrenReference[parentId][i], diff);
}
}
}
@ -41346,22 +41425,22 @@ return /******/ (function(modules) { // webpackBootstrap
}, {
key: '_findCommonParent',
value: function _findCommonParent(childA, childB) {
var _this7 = this;
var _this8 = this;
var parents = {};
var iterateParents = function iterateParents(parents, child) {
if (_this7.hierarchicalChildren[child] !== undefined) {
for (var i = 0; i < _this7.hierarchicalChildren[child].parents.length; i++) {
var _parent = _this7.hierarchicalChildren[child].parents[i];
if (_this8.hierarchicalParentReference[child] !== undefined) {
for (var i = 0; i < _this8.hierarchicalParentReference[child].length; i++) {
var _parent = _this8.hierarchicalParentReference[child][i];
parents[_parent] = true;
iterateParents(parents, _parent);
}
}
};
var findParent = function findParent(parents, child) {
if (_this7.hierarchicalChildren[child] !== undefined) {
for (var i = 0; i < _this7.hierarchicalChildren[child].parents.length; i++) {
var _parent2 = _this7.hierarchicalChildren[child].parents[i];
if (_this8.hierarchicalParentReference[child] !== undefined) {
for (var i = 0; i < _this8.hierarchicalParentReference[child].length; i++) {
var _parent2 = _this8.hierarchicalParentReference[child][i];
if (parents[_parent2] !== undefined) {
return { foundParent: _parent2, withChild: child };
}
@ -41390,6 +41469,7 @@ return /******/ (function(modules) { // webpackBootstrap
value: function _setPositionForHierarchy(node, position, level) {
var doNotUpdate = arguments.length <= 3 || arguments[3] === undefined ? false : arguments[3];
//console.log('_setPositionForHierarchy',node.id, position)
if (doNotUpdate !== true) {
if (this.distributionOrdering[level] === undefined) {
this.distributionOrdering[level] = [];
@ -41401,27 +41481,6 @@ return /******/ (function(modules) { // webpackBootstrap
this.distributionIndex[node.id] = this.distributionOrdering[level].length - 1;
}
this.distributionOrderingPresence[level][node.id] = true;
if (this.hierarchicalTrees[node.id] === undefined) {
if (this.hierarchicalChildren[node.id] !== undefined) {
var tree = 1;
// get the lowest tree denominator.
for (var i = 0; i < this.hierarchicalChildren[node.id].parents.length; i++) {
var parentId = this.hierarchicalChildren[node.id].parents[i];
if (this.hierarchicalTrees[parentId] !== undefined) {
//tree = Math.min(tree,this.hierarchicalTrees[parentId]);
tree = this.hierarchicalTrees[parentId];
}
}
//for (let i = 0; i < this.hierarchicalChildren.parents.length; i++) {
// let parentId = this.hierarchicalChildren.parents[i];
// this.hierarchicalTrees[parentId] = tree;
//}
this.hierarchicalTrees[node.id] = tree;
} else {
this.hierarchicalTrees[node.id] = ++this.treeIndex;
}
}
}
if (this.options.hierarchical.direction === 'UD' || this.options.hierarchical.direction === 'DU') {
@ -41774,7 +41833,7 @@ return /******/ (function(modules) { // webpackBootstrap
this.inMode = 'editNode';
if (typeof this.options.editNode === 'function') {
if (node.isCluster !== true) {
var data = util.deepExtend({}, node.options, true);
var data = util.deepExtend({}, node.options, false);
data.x = node.x;
data.y = node.y;
@ -42395,6 +42454,11 @@ return /******/ (function(modules) { // webpackBootstrap
edge.edgeType.to = to;
}
// we use the selection to find the node that is being dragged. We explicitly select it here.
if (this.selectedControlNode !== undefined) {
this.selectionHandler.selectObject(this.selectedControlNode);
}
this.body.emitter.emit('_redraw');
}
@ -42409,7 +42473,6 @@ return /******/ (function(modules) { // webpackBootstrap
this.body.emitter.emit('disablePhysics');
var pointer = this.body.functions.getPointer(event.center);
var pos = this.canvas.DOMtoCanvas(pointer);
if (this.selectedControlNode !== undefined) {
this.selectedControlNode.x = pos.x;
this.selectedControlNode.y = pos.y;
@ -42433,12 +42496,13 @@ return /******/ (function(modules) { // webpackBootstrap
var pointer = this.body.functions.getPointer(event.center);
var pointerObj = this.selectionHandler._pointerToPositionObject(pointer);
var edge = this.body.edges[this.edgeBeingEditedId];
// if the node that was dragged is not a control node, return
if (this.selectedControlNode === undefined) {
return;
}
// we use the selection to find the node that is being dragged. We explicitly DEselect the control node here.
this.selectionHandler.unselectAll();
var overlappingNodeIds = this.selectionHandler._getAllNodesOverlappingWith(pointerObj);
var node = undefined;
for (var i = overlappingNodeIds.length - 1; i >= 0; i--) {
@ -42447,7 +42511,6 @@ return /******/ (function(modules) { // webpackBootstrap
break;
}
}
// perform the connection
if (node !== undefined && this.selectedControlNode !== undefined) {
if (node.isCluster === true) {
@ -42825,6 +42888,7 @@ return /******/ (function(modules) { // webpackBootstrap
treeSpacing: { number: number },
blockShifting: { boolean: boolean },
edgeMinimization: { boolean: boolean },
parentCentralization: { boolean: boolean },
direction: { string: ['UD', 'DU', 'LR', 'RL'] }, // UD, DU, LR, RL
sortMethod: { string: ['hubsize', 'directed'] }, // hubsize, directed
__type__: { object: object, boolean: boolean }
@ -42918,6 +42982,7 @@ return /******/ (function(modules) { // webpackBootstrap
shapeProperties: {
borderDashes: { boolean: boolean, array: array },
borderRadius: { number: number },
interpolation: { boolean: boolean },
useImageSize: { boolean: boolean },
useBorderWithImage: { boolean: boolean },
__type__: { object: object }
@ -43058,6 +43123,7 @@ return /******/ (function(modules) { // webpackBootstrap
shapeProperties: {
borderDashes: false,
borderRadius: [6, 0, 20, 1],
interpolation: true,
useImageSize: false
},
size: [25, 0, 200, 1]
@ -43128,6 +43194,7 @@ return /******/ (function(modules) { // webpackBootstrap
treeSpacing: [200, 20, 500, 5],
blockShifting: true,
edgeMinimization: true,
parentCentralization: true,
direction: ['UD', 'DU', 'LR', 'RL'], // UD, DU, LR, RL
sortMethod: ['hubsize', 'directed'] // hubsize, directed
}

+ 1
- 1
dist/vis.map
File diff suppressed because it is too large
View File


+ 1
- 1
dist/vis.min.css
File diff suppressed because it is too large
View File


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


+ 12
- 7
docs/graph2d/index.html View File

@ -1145,6 +1145,12 @@ function (option, path) {
</td>
</tr>
<tr>
<td>getDataRange()</td>
<td>Object</td>
<td>Get the range of all the items as an object containing <code>min: Date</code> and <code>max: Date</code>.</td>
</tr>
<tr id="getEventProperties">
<td>getEventProperties(event)</td>
<td>Object</td>
@ -1176,13 +1182,6 @@ function (option, path) {
<td>Get the current visible window. Returns an object with properties <code>start: Date</code> and <code>end: Date</code>.</td>
</tr>
<tr>
<td>getItemRange()</td>
<td>Object</td>
<td>Get the range of all the items as an object containing <code>min: Date</code> and <code>max: Date</code>.</td>
</tr>
<tr>
<td>isGroupVisible(groupId)</td>
<td>Boolean</td>
@ -1305,6 +1304,12 @@ Graph2d.off('rangechanged', onChange);
<th>Properties</th>
<th>Description</th>
</tr>
<tr>
<td>currentTimeTick</td>
<td>Fired when the current time bar redraws. The rate depends on the zoom level.</td>
</tr>
<tr>
<td>click</td>
<td>

+ 8
- 8
docs/network/index.html View File

@ -339,49 +339,49 @@ network.setOptions(options);
<tr><td id="event_configure">configure</td>
<td>Object</td>
<td>Object</td>
<td href="./configure.html">All options in this object are explained in the configure module.</a>
<td>All options in this object are explained in the <a href="./configure.html">configure module</a>.
</td>
</tr>
<tr><td id="event_edges">edges</td>
<td>Object</td>
<td>Object</td>
<td href="./edges.html">All options in this object are explained in the edges module.</a>
<td>All options in this object are explained in the <a href="./edges.html">edges module</a>.
</td>
</tr>
<tr><td id="event_nodes">nodes</td>
<td>Object</td>
<td>Object</td>
<td href="./nodes.html">All options in this object are explained in the nodes module.</a>
<td>All options in this object are explained in the <a href="./nodes.html">nodes module</a>.
</td>
</tr>
<tr><td id="event_groups">groups</td>
<td>Object</td>
<td>Object</td>
<td href="./groups.html">All options in this object are explained in the groups module.</a>
<td>All options in this object are explained in the <a href="./groups.html">groups module</a>.
</td>
</tr>
<tr><td id="event_layout">layout</td>
<td>Object</td>
<td>Object</td>
<td href="./layout.html">All options in this object are explained in the layout module.</a>
<td>All options in this object are explained in the <a href="./layout.html">layout module</a>.
</td>
</tr>
<tr><td id="event_interaction">interaction</td>
<td>Object</td>
<td>Object</td>
<td href="./interaction.html">All options in this object are explained in the interaction module.</a>
<td>All options in this object are explained in the <a href="./interaction.html">interaction module</a>.
</td>
</tr>
<tr><td id="event_manipulation">manipulation</td>
<td>Object</td>
<td>Object</td>
<td href="./manipulation.html">All options in this object are explained in the manipulation module.</a>
<td>All options in this object are explained in the <a href="./manipulation.html">manipulation module</a>.
</td>
</tr>
<tr><td id="event_physics">physics</td>
<td>Object</td>
<td>Object</td>
<td href="./physics.html">All options in this object are explained in the physics module.</a>
<td>All options in this object are explained in the <a href="./physics.html">physics module</a>.
</td>
</tr>
</table>

+ 2
- 0
docs/network/layout.html View File

@ -109,6 +109,7 @@ var options = {
treeSpacing: 200,
blockShifting: true,
edgeMinimization: true,
parentCentralization: true,
direction: 'UD', // UD, DU, LR, RL
sortMethod: 'hubsize' // hubsize, directed
}
@ -142,6 +143,7 @@ network.setOptions(options);
it's branch along with it for as far as it can, respecting the nodeSpacing on any level. This is mainly for the initial layout. If you enable physics, they layout will be determined by the physics. This will greatly speed up the stabilization time though!</td></tr>
<tr parent="hierarchical" class="hidden"><td class="indent">hierarchical.edgeMinimization</td><td>Boolean</td><td><code>true</code></td> <td>Method for reducing whitespace. Can be used alone or together with block shifting. Enabling block shifting will usually speed up the layout process.
Each node will try to move along its free axis to reduce the total length of it's edges. This is mainly for the initial layout. If you enable physics, they layout will be determined by the physics. This will greatly speed up the stabilization time though!</td></tr>
<tr parent="hierarchical" class="hidden"><td class="indent">hierarchical.parentCentralization</td><td>Boolean</td><td><code>true</code></td> <td>When true, the parents nodes will be centered again after the the layout algorithm has been finished.</td></tr>
<tr parent="hierarchical" class="hidden"><td class="indent">hierarchical.direction</td><td>String</td><td><code>'UD'</code></td> <td>The direction of the hierarchical layout. The available options are: <code>UD, DU, LR, RL</code>. To simplify: up-down, down-up, left-right, right-left.</td></tr>
<tr parent="hierarchical" class="hidden"><td class="indent">hierarchical.sortMethod</td><td>String</td><td><code>'hubsize'</code></td> <td>The algorithm used to ascertain the levels of the nodes based on the data. The possible options are: <code>hubsize, directed</code>. <br><br>
Hubsize takes the nodes with the most edges and puts them at the top. From that the rest of the hierarchy is evaluated. <br><br>

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

@ -180,6 +180,7 @@ var options = {
shapeProperties: {
borderDashes: false, // only for borders
borderRadius: 6, // only for box shape
interpolation: false, // only for image and circularImage shapes
useImageSize: false, // only for image and circularImage shapes
useBorderWithImage: false // only for image shape
}
@ -645,6 +646,13 @@ mySize = minSize + diff * scale;
<td>This property is used only for the <code>box</code> shape. It allows you to determine the roundness of the corners of the shape.
</td>
</tr>
<tr parent="shapeProperties" class="hidden">
<td class="indent">shapeProperties.interpolation</td>
<td>Boolean</td>
<td><code>true</code></td>
<td>This property only applies to the <code>image</code> and <code>circularImage</code> shapes. When true, the image is resampled when scaled down, resulting in a nicer image at the cost of computional time.</i>
</td>
</tr>
<tr parent="shapeProperties" class="hidden">
<td class="indent">shapeProperties.useImageSize</td>
<td>Boolean</td>

+ 11
- 0
docs/timeline/index.html View File

@ -1150,6 +1150,12 @@ document.getElementById('myTimeline').onclick = function (event) {
</td>
</tr>
<tr>
<td>getItemRange()</td>
<td>Object</td>
<td>Get the range of all the items as an object containing <code>min: Date</code> and <code>max: Date</code>.</td>
</tr>
<tr>
<td>getSelection()</td>
<td>number[]</td>
@ -1342,6 +1348,11 @@ timeline.off('select', onSelect);
<th>Description</th>
</tr>
<tr>
<td>currentTimeTick</td>
<td>Fired when the current time bar redraws. The rate depends on the zoom level.</td>
</tr>
<tr>
<td>click</td>
<td>

BIN
download/vis.zip View File


+ 4
- 0
examples/network/layout/hierarchicalLayoutWithoutPhysics.html View File

@ -47,6 +47,10 @@ The hierarchical layout can now be controlled without the use of physics. This i
<td>Method for reducing whitespace. Can be used alone or together with block shifting. Enabling block shifting will usually speed up the layout process.
Each node will try to move along its free axis to reduce the total length of it's edges.</td>
</tr>
<tr>
<td><code>parentCentralization</code></td>
<td>When true, the parents nodes will be centered again after the the layout algorithm has been finished.</td>
</tr>
</table>
<br /><br />
Play with the settings below the network and see how the layout changes!

+ 3
- 5
examples/network/nodeStyles/customGroups.html View File

@ -26,12 +26,9 @@
</head>
<body>
<i class="fa fa-flag"></i> We use an icon once in the DOM so the CSS for fontAwesome is loaded.</h2>
<div id="mynetwork"></div>
<script type="text/javascript">
var color = 'gray';
var len = undefined;
var nodes = [
{id: 0, label: "0", group: 'source'},
{id: 1, label: "1", group: 'icons'},
@ -128,7 +125,8 @@
}
}
};
network = new vis.Network(container, data, options);
var network = new vis.Network(container, data, options);
</script>
</body>
</html>

+ 5
- 5
index.html View File

@ -28,7 +28,7 @@
<script src="./js/smooth-scroll.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vis/4.14.0/vis.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vis/4.15.0/vis.min.js"></script>
<script language="JavaScript">
smoothScroll.init();
@ -36,7 +36,7 @@
function evalLinks() {
if (typeof vis === 'undefined') {
console.log(document.getElementById("linkStatus"));
document.getElementById("linkStatus").innerHTML = "Note: The latest version (4.14.0) is not yet available on cdnjs, <a href='https://cdnjs.com/libraries/vis'>click here</a> to to pick the latest available version.<br />";
document.getElementById("linkStatus").innerHTML = "Note: The latest version (4.15.0) is not yet available on cdnjs, <a href='https://cdnjs.com/libraries/vis'>click here</a> to to pick the latest available version.<br />";
document.getElementById("cdn_vis").style.color = "rgb(150,150,150)";
document.getElementById("cdn_vis_css").style.color = "rgb(150,150,150)";
}
@ -210,13 +210,13 @@
<pre class="prettyprint">bower install vis</pre>
<h3>link from cdnjs.com</h3>
<p>
<a id="cdn_vis" href="https://cdnjs.cloudflare.com/ajax/libs/vis/4.14.0/vis.min.js" target="_blank">vis.min.js</a> <br>
<a id="cdn_vis_css" href="https://cdnjs.cloudflare.com/ajax/libs/vis/4.14.0/vis.min.css" target="_blank">vis.min.css</a> <br>
<a id="cdn_vis" href="https://cdnjs.cloudflare.com/ajax/libs/vis/4.15.0/vis.min.js" target="_blank">vis.min.js</a> <br>
<a id="cdn_vis_css" href="https://cdnjs.cloudflare.com/ajax/libs/vis/4.15.0/vis.min.css" target="_blank">vis.min.css</a> <br>
<span id="linkStatus"></span>
</p>
<h3>download</h3>
<p>
<a href="download/vis.zip">vis.zip (version <span class="version">4.14.0</span>)</a>
<a href="download/vis.zip">vis.zip (version <span class="version">4.15.0</span>)</a>
</p>
</div>
</div>

Loading…
Cancel
Save