Browse Source

Merge remote-tracking branch 'origin/v4' into v4

Conflicts:
	dist/vis.js
	dist/vis.min.css
	lib/network/modules/CanvasRenderer.js
	lib/network/modules/InteractionHandler.js
	lib/network/modules/SelectionHandler.js
flowchartTest
Alex de Mulder 9 years ago
parent
commit
af46198ee4
25 changed files with 141 additions and 110 deletions
  1. +5
    -0
      HISTORY.md
  2. +0
    -0
      docs/old_timeline.html
  3. +49
    -44
      docs/timeline/index.html
  4. +5
    -0
      examples/timeline/02_manipulation.html
  5. +1
    -1
      lib/DOMutil.js
  6. +1
    -1
      lib/network/dotparser.js
  7. +3
    -1
      lib/network/modules/Canvas.js
  8. +23
    -21
      lib/network/modules/CanvasRenderer.js
  9. +8
    -6
      lib/network/modules/Clustering.js
  10. +2
    -2
      lib/network/modules/ConfigurationSystem.js
  11. +2
    -2
      lib/network/modules/Groups.js
  12. +2
    -2
      lib/network/modules/InteractionHandler.js
  13. +2
    -2
      lib/network/modules/LayoutEngine.js
  14. +1
    -1
      lib/network/modules/ManipulationSystem.js
  15. +2
    -2
      lib/network/modules/NodesHandler.js
  16. +3
    -3
      lib/network/modules/PhysicsEngine.js
  17. +3
    -3
      lib/network/modules/SelectionHandler.js
  18. +1
    -1
      lib/network/modules/components/Edge.js
  19. +2
    -2
      lib/network/modules/components/edges/util/EdgeBase.js
  20. +1
    -1
      lib/network/modules/components/shared/Label.js
  21. +2
    -2
      lib/timeline/Core.js
  22. +1
    -1
      lib/timeline/component/GraphGroup.js
  23. +15
    -7
      lib/timeline/component/ItemSet.js
  24. +6
    -4
      lib/timeline/component/LineGraph.js
  25. +1
    -1
      lib/timeline/component/graph2d_types/line.js

+ 5
- 0
HISTORY.md View File

@ -14,6 +14,7 @@ http://visjs.org
### Timeline ### Timeline
- Implemented option `multiselect`, which is false by default.
- Added method `setData({groups: groups, items: items})`. - Added method `setData({groups: groups, items: items})`.
- Fixed range items not being displayed smaller than 10 pixels (twice the - Fixed range items not being displayed smaller than 10 pixels (twice the
padding). In order to have overflowing text, one should now apply css style padding). In order to have overflowing text, one should now apply css style
@ -27,6 +28,10 @@ http://visjs.org
- Renamed option `animate` to `animation`, and changed it to be either a boolean - Renamed option `animate` to `animation`, and changed it to be either a boolean
or an object `{duration: number, easingFunction: string}`. or an object `{duration: number, easingFunction: string}`.
### Graph2d
- Fixed #716: Height of graph `2px` too large when configuring a fixed height.
### Network ### Network
- Rebuilt the cluster system - Rebuilt the cluster system

docs/timeline.html → docs/old_timeline.html View File


+ 49
- 44
docs/timeline/index.html View File

@ -447,7 +447,7 @@ var options = {
The following options are available. The following options are available.
</p> </p>
<table class="moduleTable" >
<table class="moduleTable" id="optionTable">
<tr class="header"> <tr class="header">
<td>Name</td> <td>Name</td>
<td>Type</td> <td>Type</td>
@ -485,39 +485,34 @@ var options = {
If value is <code>'all'</code> then each field defined on the timeline item will become a <code>data-</code> attribute.</td> If value is <code>'all'</code> then each field defined on the timeline item will become a <code>data-</code> attribute.</td>
</tr> </tr>
<tr>
<td>editable</td>
<tr class='toggle collapsible' onclick="toggleTable('optionTable','editable', this);">
<td><span parent="editable" class="right-caret"></span> editable</td>
<td class="mid">boolean | Object</td> <td class="mid">boolean | Object</td>
<td class="mid"><code>false</code></td> <td class="mid"><code>false</code></td>
<td>If true, the items in the timeline can be manipulated. Only applicable when option <code>selectable</code> is <code><code>true</code></code>. See also the callbacks <code>onAdd</code>, <code>onUpdate</code>, <code>onMove</code>, and <code>onRemove</code>. When <code>editable</code> is an object, one can enable or disable individual manipulation actions. <td>If true, the items in the timeline can be manipulated. Only applicable when option <code>selectable</code> is <code><code>true</code></code>. See also the callbacks <code>onAdd</code>, <code>onUpdate</code>, <code>onMove</code>, and <code>onRemove</code>. When <code>editable</code> is an object, one can enable or disable individual manipulation actions.
See section <a href="#Editing_Items">Editing Items</a> for a detailed explanation. See section <a href="#Editing_Items">Editing Items</a> for a detailed explanation.
</td> </td>
</tr> </tr>
<tr>
<td>editable.add</td>
<tr parent="editable" class="hidden">
<td class="indent">editable.add</td>
<td class="mid">boolean</td> <td class="mid">boolean</td>
<td class="mid"><code>false</code></td> <td class="mid"><code>false</code></td>
<td>If true, new items can be created by double tapping an empty space in the Timeline. See section <a href="#Editing_Items">Editing Items</a> for a detailed explanation.</td> <td>If true, new items can be created by double tapping an empty space in the Timeline. See section <a href="#Editing_Items">Editing Items</a> for a detailed explanation.</td>
</tr> </tr>
<tr>
<td>editable.remove</td>
<tr parent="editable" class="hidden">
<td class="indent">editable.remove</td>
<td class="mid">boolean</td> <td class="mid">boolean</td>
<td class="mid"><code>false</code></td> <td class="mid"><code>false</code></td>
<td>If true, items can be deleted by first selecting them, and then clicking the delete button on the top right of the item. See section <a href="#Editing_Items">Editing Items</a> for a detailed explanation.</td> <td>If true, items can be deleted by first selecting them, and then clicking the delete button on the top right of the item. See section <a href="#Editing_Items">Editing Items</a> for a detailed explanation.</td>
</tr> </tr>
<tr>
<td>editable.updateGroup</td>
<tr parent="editable" class="hidden">
<td class="indent">editable.updateGroup</td>
<td class="mid">boolean</td> <td class="mid">boolean</td>
<td class="mid"><code>false</code></td> <td class="mid"><code>false</code></td>
<td>If true, items can be dragged from one group to another. Only applicable when the Timeline has groups. See section <a href="#Editing_Items">Editing Items</a> for a detailed explanation.</td> <td>If true, items can be dragged from one group to another. Only applicable when the Timeline has groups. See section <a href="#Editing_Items">Editing Items</a> for a detailed explanation.</td>
</tr> </tr>
<tr>
<td>editable.updateTime</td>
<tr parent="editable" class="hidden">
<td class="indent">editable.updateTime</td>
<td class="mid">boolean</td> <td class="mid">boolean</td>
<td class="mid"><code>false</code></td> <td class="mid"><code>false</code></td>
<td>If true, items can be dragged to another moment in time. See section <a href="#Editing_Items">Editing Items</a> for a detailed explanation.</td> <td>If true, items can be dragged to another moment in time. See section <a href="#Editing_Items">Editing Items</a> for a detailed explanation.</td>
@ -611,36 +606,32 @@ var options = {
<td>A map with i18n locales. See section <a href="#Localization">Localization</a> for more information.</td> <td>A map with i18n locales. See section <a href="#Localization">Localization</a> for more information.</td>
</tr> </tr>
<tr>
<td>margin</td>
<tr class='toggle collapsible' onclick="toggleTable('optionTable','margin', this);">
<td><span parent="margin" class="right-caret"></span> margin</td>
<td class="mid">number | Object</td> <td class="mid">number | Object</td>
<td class="mid">Object</td> <td class="mid">Object</td>
<td>When a number, applies the margin to <code>margin.axis</code>, <code>margin.item.horizontal</code>, and <code>margin.item.vertical</code>.</td> <td>When a number, applies the margin to <code>margin.axis</code>, <code>margin.item.horizontal</code>, and <code>margin.item.vertical</code>.</td>
</tr> </tr>
<tr>
<td>margin.axis</td>
<tr parent="margin" class="hidden">
<td class="indent">margin.axis</td>
<td class="mid">number</td> <td class="mid">number</td>
<td class="mid"><code>20</code></td> <td class="mid"><code>20</code></td>
<td>The minimal margin in pixels between items and the time axis.</td> <td>The minimal margin in pixels between items and the time axis.</td>
</tr> </tr>
<tr>
<td>margin.item</td>
<tr parent="margin" class="hidden">
<td class="indent">margin.item</td>
<td class="mid">number</td> <td class="mid">number</td>
<td class="mid"><code>10</code></td> <td class="mid"><code>10</code></td>
<td>The minimal margin in pixels between items in both horizontal and vertical direction.</td> <td>The minimal margin in pixels between items in both horizontal and vertical direction.</td>
</tr> </tr>
<tr>
<td>margin.item.horizontal</td>
<tr parent="margin" class="hidden">
<td class="indent2">margin.item.horizontal</td>
<td class="mid">number</td> <td class="mid">number</td>
<td class="mid"><code>10</code></td> <td class="mid"><code>10</code></td>
<td>The minimal horizontal margin in pixels between items.</td> <td>The minimal horizontal margin in pixels between items.</td>
</tr> </tr>
<tr>
<td>margin.item.vertical</td>
<tr parent="margin" class="hidden">
<td class="indent2">margin.item.vertical</td>
<td class="mid">number</td> <td class="mid">number</td>
<td class="mid"><code>10</code></td> <td class="mid"><code>10</code></td>
<td>The minimal vertical margin in pixels between items.</td> <td>The minimal vertical margin in pixels between items.</td>
@ -688,6 +679,16 @@ var options = {
</td> </td>
</tr> </tr>
<tr>
<td>multiselect</td>
<td class="mid">boolean</td>
<td class="mid"><code>false</code></td>
<td>
If true, multiple items can be selected using ctrl+click, shift+click, or by holding items.
Only applicable when option <code>selectable</code> is <code>true</code>.
</td>
</tr>
<tr> <tr>
<td>onAdd</td> <td>onAdd</td>
<td class="mid">function</td> <td class="mid">function</td>
@ -742,27 +743,26 @@ var options = {
</td> </td>
</tr> </tr>
<tr>
<td>orientation</td>
<tr class='toggle collapsible' onclick="toggleTable('optionTable','orientation', this);">
<td><span parent="orientation" class="right-caret"></span> orientation</td>
<td class="mid">String | Object</td> <td class="mid">String | Object</td>
<td class="mid"><code>'bottom'</code></td> <td class="mid"><code>'bottom'</code></td>
<td>Orientation of the timelines axis and items. When orientation is a string, the value is applied to both items and axis. Can be 'top', 'bottom' (default), or 'both'.</td> <td>Orientation of the timelines axis and items. When orientation is a string, the value is applied to both items and axis. Can be 'top', 'bottom' (default), or 'both'.</td>
</tr> </tr>
<tr>
<td>orientation.axis</td>
<tr parent="orientation" class="hidden">
<td class="indent">orientation.axis</td>
<td class="mid">String</td> <td class="mid">String</td>
<td class="mid"><code>'bottom'</code></td> <td class="mid"><code>'bottom'</code></td>
<td>Orientation of the timeline axis: 'top', 'bottom' (default), or 'both'. If orientation is 'bottom', the time axis is drawn at the bottom. When 'top', the axis is drawn on top. When 'both', two axes are drawn, both on top and at the bottom.</td> <td>Orientation of the timeline axis: 'top', 'bottom' (default), or 'both'. If orientation is 'bottom', the time axis is drawn at the bottom. When 'top', the axis is drawn on top. When 'both', two axes are drawn, both on top and at the bottom.</td>
</tr> </tr>
<tr>
<td>orientation.item</td>
<tr parent="orientation" class="hidden">
<td class="indent">orientation.item</td>
<td class="mid">String</td> <td class="mid">String</td>
<td class="mid"><code>'bottom'</code></td> <td class="mid"><code>'bottom'</code></td>
<td>Orientation of the timeline items: 'top' or 'bottom' (default). Determines whether items are aligned to the top or bottom of the Timeline.</td> <td>Orientation of the timeline items: 'top' or 'bottom' (default). Determines whether items are aligned to the top or bottom of the Timeline.</td>
</tr> </tr>
<tr> <tr>
<td>selectable</td> <td>selectable</td>
<td class="mid">boolean</td> <td class="mid">boolean</td>
@ -834,8 +834,14 @@ var options = {
<td>A template function used to generate the contents of the items. The function is called by the Timeline with an items data as argument, and must return HTML code as result. When the option template is specified, the items do not need to have a field <code>content</code>. See section <a href="#Templates">Templates</a> for a detailed explanation.</td> <td>A template function used to generate the contents of the items. The function is called by the Timeline with an items data as argument, and must return HTML code as result. When the option template is specified, the items do not need to have a field <code>content</code>. See section <a href="#Templates">Templates</a> for a detailed explanation.</td>
</tr> </tr>
<tr>
<td>timeAxis.scale</td>
<tr class='toggle collapsible' onclick="toggleTable('optionTable','timeAxis', this);">
<td><span parent="timeAxis" class="right-caret"></span> timeAxis</td>
<td class="mid">Object</td>
<td class="mid"><code>Object</code></td>
<td>Specify a fixed scale and step size for the time axis.</td>
</tr>
<tr parent="timeAxis" class="hidden">
<td class="indent">timeAxis.scale</td>
<td class="mid">String</td> <td class="mid">String</td>
<td class="mid">none</td> <td class="mid">none</td>
<td>Set a fixed scale for the time axis of the Timeline. Choose from <code>'millisecond'</code>, <code>'second'</code>, <code>'minute'</code>, <code>'hour'</code>, <code>'weekday'</code>, <code>'day'</code>, <code>'month'</code>, <code>'year'</code>. Example usage: <td>Set a fixed scale for the time axis of the Timeline. Choose from <code>'millisecond'</code>, <code>'second'</code>, <code>'minute'</code>, <code>'hour'</code>, <code>'weekday'</code>, <code>'day'</code>, <code>'month'</code>, <code>'year'</code>. Example usage:
@ -844,9 +850,8 @@ var options = {
}</pre> }</pre>
</td> </td>
</tr> </tr>
<tr>
<td>timeAxis.step</td>
<tr parent="timeAxis" class="hidden">
<td class="indent">timeAxis.step</td>
<td class="mid">number</td> <td class="mid">number</td>
<td class="mid"><code>1</code></td> <td class="mid"><code>1</code></td>
<td> <td>
@ -1280,7 +1285,7 @@ timeline.off('select', onSelect);
When the Timeline is configured to be editable (both options <code>selectable</code> and <code>editable</code> are <code><code>true</code></code>), the user can: When the Timeline is configured to be editable (both options <code>selectable</code> and <code>editable</code> are <code><code>true</code></code>), the user can:
</p> </p>
<ul> <ul>
<li>Select an item by clicking it, and use ctrl+click to or shift+click to select multiple items</li>
<li>Select an item by clicking it, and use ctrl+click to or shift+click to select multiple items (when <code>multiselect: true</code>).</li>
<li>Move selected items by dragging them.</li> <li>Move selected items by dragging them.</li>
<li>Create a new item by double tapping on an empty space.</li> <li>Create a new item by double tapping on an empty space.</li>
<li>Create a new range item by dragging on an empty space with the ctrl key down.</li> <li>Create a new range item by dragging on an empty space with the ctrl key down.</li>

+ 5
- 0
examples/timeline/02_manipulation.html View File

@ -44,6 +44,11 @@
start: '2014-01-10', start: '2014-01-10',
end: '2014-02-10', end: '2014-02-10',
height: '300px', height: '300px',
// allow selecting multiple items using ctrl+click, shift+click, or hold.
multiselect: true,
// allow manipulation of items
editable: true, editable: true,
/* alternatively, enable/disable individual actions: /* alternatively, enable/disable individual actions:

+ 1
- 1
lib/DOMutil.js View File

@ -150,7 +150,7 @@ exports.drawPoint = function(x, y, group, JSONcontainer, svgContainer, labelObj)
} }
if(group.options.drawPoints.styles !== undefined) { if(group.options.drawPoints.styles !== undefined) {
point.setAttributeNS(null, "style", 'vis-' + group.group.options.drawPoints.styles);
point.setAttributeNS(null, "style", group.group.options.drawPoints.styles);
} }
point.setAttributeNS(null, "class", group.className + " vis-point"); point.setAttributeNS(null, "class", group.className + " vis-point");
//handle label //handle label

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

@ -769,7 +769,7 @@ function DOTToGraph (data) {
merge(graphEdge, dotEdge.attr); merge(graphEdge, dotEdge.attr);
graphEdge.style = (dotEdge.type === '->') ? 'arrow' : 'line'; graphEdge.style = (dotEdge.type === '->') ? 'arrow' : 'line';
return graphEdge; return graphEdge;
}
};
dotData.edges.forEach(function (dotEdge) { dotData.edges.forEach(function (dotEdge) {
var from, to; var from, to;

+ 3
- 1
lib/network/modules/Canvas.js View File

@ -22,7 +22,7 @@ class Canvas {
width:'100%', width:'100%',
height:'100%', height:'100%',
autoResize: true autoResize: true
}
};
util.extend(this.options, this.defaultOptions); util.extend(this.options, this.defaultOptions);
this.bindEventListeners(); this.bindEventListeners();
@ -157,6 +157,8 @@ class Canvas {
// init hammer // init hammer
this.hammer = new Hammer(this.frame.canvas); this.hammer = new Hammer(this.frame.canvas);
this.hammer.get('pinch').set({enable: true}); this.hammer.get('pinch').set({enable: true});
// enable to get better response, todo: test on mobile.
//this.hammer.get('pan').set({threshold:2});
hammerUtil.onTouch(this.hammer, (event) => {this.body.eventListeners.onTouch(event)}); hammerUtil.onTouch(this.hammer, (event) => {this.body.eventListeners.onTouch(event)});
this.hammer.on('tap', (event) => {this.body.eventListeners.onTap(event)}); this.hammer.on('tap', (event) => {this.body.eventListeners.onTap(event)});

+ 23
- 21
lib/network/modules/CanvasRenderer.js View File

@ -3,7 +3,7 @@ if (typeof window !== 'undefined') {
window.webkitRequestAnimationFrame || window.msRequestAnimationFrame; window.webkitRequestAnimationFrame || window.msRequestAnimationFrame;
} }
var util = require('../../util');
let util = require('../../util');
class CanvasRenderer { class CanvasRenderer {
@ -24,7 +24,7 @@ class CanvasRenderer {
this.defaultOptions = { this.defaultOptions = {
hideEdgesOnDrag: false, hideEdgesOnDrag: false,
hideNodesOnDrag: false hideNodesOnDrag: false
}
};
util.extend(this.options, this.defaultOptions); util.extend(this.options, this.defaultOptions);
this._determineBrowserMethod(); this._determineBrowserMethod();
@ -137,7 +137,7 @@ class CanvasRenderer {
this.body.emitter.emit("initRedraw"); this.body.emitter.emit("initRedraw");
this.redrawRequested = false; this.redrawRequested = false;
var ctx = this.canvas.frame.canvas.getContext('2d');
let ctx = this.canvas.frame.canvas.getContext('2d');
// when the container div was hidden, this fixes it back up! // when the container div was hidden, this fixes it back up!
if (this.canvas.frame.canvas.width === 0 || this.canvas.frame.canvas.height === 0) { if (this.canvas.frame.canvas.width === 0 || this.canvas.frame.canvas.height === 0) {
@ -155,8 +155,8 @@ class CanvasRenderer {
ctx.setTransform(this.pixelRatio, 0, 0, this.pixelRatio, 0, 0); ctx.setTransform(this.pixelRatio, 0, 0, this.pixelRatio, 0, 0);
// clear the canvas // clear the canvas
var w = this.canvas.frame.canvas.clientWidth;
var h = this.canvas.frame.canvas.clientHeight;
let w = this.canvas.frame.canvas.clientWidth;
let h = this.canvas.frame.canvas.clientHeight;
ctx.clearRect(0, 0, w, h); ctx.clearRect(0, 0, w, h);
@ -191,8 +191,6 @@ class CanvasRenderer {
if (hidden === true) { if (hidden === true) {
ctx.clearRect(0, 0, w, h); ctx.clearRect(0, 0, w, h);
} }
} }
@ -204,13 +202,17 @@ class CanvasRenderer {
* @private * @private
*/ */
_drawNodes(ctx, alwaysShow = false) { _drawNodes(ctx, alwaysShow = false) {
var nodes = this.body.nodes;
var nodeIndices = this.body.nodeIndices;
var node;
var selected = [];
var topLeft = this.canvas.DOMtoCanvas({x:0,y:0});
var bottomRight = this.canvas.DOMtoCanvas({x:this.canvas.frame.canvas.clientWidth,y:this.canvas.frame.canvas.clientHeight});;
var viewableArea = {top:topLeft.y,left:topLeft.x,bottom:bottomRight.y,right:bottomRight.x};
let nodes = this.body.nodes;
let nodeIndices = this.body.nodeIndices;
let node;
let selected = [];
let margin = 20;
let topLeft = this.canvas.DOMtoCanvas({x:-margin,y:-margin});
let bottomRight = this.canvas.DOMtoCanvas({
x: this.canvas.frame.canvas.clientWidth+margin,
y: this.canvas.frame.canvas.clientHeight+margin
});
let viewableArea = {top:topLeft.y,left:topLeft.x,bottom:bottomRight.y,right:bottomRight.x};
// draw unselected nodes; // draw unselected nodes;
@ -245,9 +247,9 @@ class CanvasRenderer {
* @private * @private
*/ */
_drawEdges(ctx) { _drawEdges(ctx) {
var edges = this.body.edges;
var edgeIndices = this.body.edgeIndices;
var edge;
let edges = this.body.edges;
let edgeIndices = this.body.edgeIndices;
let edge;
for (let i = 0; i < edgeIndices.length; i++) { for (let i = 0; i < edgeIndices.length; i++) {
edge = edges[edgeIndices[i]]; edge = edges[edgeIndices[i]];
@ -264,9 +266,9 @@ class CanvasRenderer {
* @private * @private
*/ */
_drawControlNodes(ctx) { _drawControlNodes(ctx) {
var edges = this.body.edges;
var edgeIndices = this.body.edgeIndices;
var edge;
let edges = this.body.edges;
let edgeIndices = this.body.edgeIndices;
let edge;
for (let i = 0; i < edgeIndices.length; i++) { for (let i = 0; i < edgeIndices.length; i++) {
edge = edges[edgeIndices[i]]; edge = edges[edgeIndices[i]];
@ -281,7 +283,7 @@ class CanvasRenderer {
*/ */
_determineBrowserMethod() { _determineBrowserMethod() {
if (typeof window !== 'undefined') { if (typeof window !== 'undefined') {
var browserType = navigator.userAgent.toLowerCase();
let browserType = navigator.userAgent.toLowerCase();
this.requiresTimeout = false; this.requiresTimeout = false;
if (browserType.indexOf('msie 9.0') != -1) { // IE 9 if (browserType.indexOf('msie 9.0') != -1) { // IE 9
this.requiresTimeout = true; this.requiresTimeout = true;

+ 8
- 6
lib/network/modules/Clustering.js View File

@ -59,7 +59,7 @@ class ClusterEngine {
options = this._checkOptions(options); options = this._checkOptions(options);
let childNodesObj = {}; let childNodesObj = {};
let childEdgesObj = {}
let childEdgesObj = {};
// collect the nodes that will be in the cluster // collect the nodes that will be in the cluster
for (let i = 0; i < this.body.nodeIndices.length; i++) { for (let i = 0; i < this.body.nodeIndices.length; i++) {
@ -143,7 +143,7 @@ class ClusterEngine {
let childNodesObj = {}; let childNodesObj = {};
let childEdgesObj = {}
let childEdgesObj = {};
let parentNodeId = node.id; let parentNodeId = node.id;
let parentClonedOptions = this._cloneOptions(parentNodeId); let parentClonedOptions = this._cloneOptions(parentNodeId);
childNodesObj[parentNodeId] = node; childNodesObj[parentNodeId] = node;
@ -388,7 +388,7 @@ class ClusterEngine {
return this.body.nodes[nodeId].isCluster === true; return this.body.nodes[nodeId].isCluster === true;
} }
else { else {
console.log("Node does not exist.")
console.log("Node does not exist.");
return false; return false;
} }
} }
@ -426,8 +426,10 @@ class ClusterEngine {
// kill conditions // kill conditions
if (clusterNodeId === undefined) {throw new Error("No clusterNodeId supplied to openCluster.");} if (clusterNodeId === undefined) {throw new Error("No clusterNodeId supplied to openCluster.");}
if (this.body.nodes[clusterNodeId] === undefined) {throw new Error("The clusterNodeId supplied to openCluster does not exist.");} if (this.body.nodes[clusterNodeId] === undefined) {throw new Error("The clusterNodeId supplied to openCluster does not exist.");}
if (this.body.nodes[clusterNodeId].containedNodes === undefined) {console.log("The node:" + clusterNodeId + " is not a cluster."); return};
if (this.body.nodes[clusterNodeId].containedNodes === undefined) {
console.log("The node:" + clusterNodeId + " is not a cluster.");
return
}
let clusterNode = this.body.nodes[clusterNodeId]; let clusterNode = this.body.nodes[clusterNodeId];
let containedNodes = clusterNode.containedNodes; let containedNodes = clusterNode.containedNodes;
let containedEdges = clusterNode.containedEdges; let containedEdges = clusterNode.containedEdges;
@ -492,7 +494,7 @@ class ClusterEngine {
if (from === true) { if (from === true) {
edge.from = clusterStack[clusterStack.length - 1]; edge.from = clusterStack[clusterStack.length - 1];
edge.fromId = clusterStack[clusterStack.length - 1].id; edge.fromId = clusterStack[clusterStack.length - 1].id;
clusterStack.pop()
clusterStack.pop();
edge.fromArray = clusterStack; edge.fromArray = clusterStack;
} }
else { else {

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

@ -27,7 +27,7 @@ class ConfigurationSystem {
enabled: false, enabled: false,
filter: true, filter: true,
container: undefined container: undefined
}
};
util.extend(this.options, this.defaultOptions); util.extend(this.options, this.defaultOptions);
this.configureOptions = configureOptions; this.configureOptions = configureOptions;
@ -371,7 +371,7 @@ class ConfigurationSystem {
value = value === undefined ? defaultColor : value; value = value === undefined ? defaultColor : value;
div.onclick = () => { div.onclick = () => {
this._showColorPicker(value,div,path); this._showColorPicker(value,div,path);
}
};
let label = this._makeLabel(path[path.length-1], path); let label = this._makeLabel(path[path.length-1], path);
this._makeItem(path,label, div); this._makeItem(path,label, div);

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

@ -34,13 +34,13 @@ class Groups {
{border: "#FFC0CB", background: "#FD5A77", highlight: {border: "#FFD1D9", background: "#FD5A77"}, hover: {border: "#FFD1D9", background: "#FD5A77"}}, // 18: pink {border: "#FFC0CB", background: "#FD5A77", highlight: {border: "#FFD1D9", background: "#FD5A77"}, hover: {border: "#FFD1D9", background: "#FD5A77"}}, // 18: pink
{border: "#C2FABC", background: "#74D66A", highlight: {border: "#E6FFE3", background: "#74D66A"}, hover: {border: "#E6FFE3", background: "#74D66A"}}, // 19: mint {border: "#C2FABC", background: "#74D66A", highlight: {border: "#E6FFE3", background: "#74D66A"}, hover: {border: "#E6FFE3", background: "#74D66A"}}, // 19: mint
{border: "#EE0000", background: "#990000", highlight: {border: "#FF3333", background: "#BB0000"}, hover: {border: "#FF3333", background: "#BB0000"}}, // 20:bright red
{border: "#EE0000", background: "#990000", highlight: {border: "#FF3333", background: "#BB0000"}, hover: {border: "#FF3333", background: "#BB0000"}} // 20:bright red
]; ];
this.options = {}; this.options = {};
this.defaultOptions = { this.defaultOptions = {
useDefaultGroups: true useDefaultGroups: true
}
};
util.extend(this.options, this.defaultOptions); util.extend(this.options, this.defaultOptions);
} }

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

@ -47,7 +47,7 @@ class InteractionHandler {
navigationButtons: false, navigationButtons: false,
tooltipDelay: 300, tooltipDelay: 300,
zoomView: true zoomView: true
}
};
util.extend(this.options,this.defaultOptions); util.extend(this.options,this.defaultOptions);
this.bindEventListeners() this.bindEventListeners()
@ -478,7 +478,7 @@ class InteractionHandler {
// if the popup was not hidden above // if the popup was not hidden above
if (this.popup.hidden === false) { if (this.popup.hidden === false) {
popupVisible = true; popupVisible = true;
this.popup.setPosition(pointer.x + 3, pointer.y - 5)
this.popup.setPosition(pointer.x + 3, pointer.y - 5);
this.popup.show(); this.popup.show();
} }
} }

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

@ -17,7 +17,7 @@ class LayoutEngine {
direction: 'UD', // UD, DU, LR, RL direction: 'UD', // UD, DU, LR, RL
sortMethod: 'hubsize' // hubsize, directed sortMethod: 'hubsize' // hubsize, directed
} }
}
};
util.extend(this.options, this.defaultOptions); util.extend(this.options, this.defaultOptions);
this.hierarchicalLevels = {}; this.hierarchicalLevels = {};
@ -28,7 +28,7 @@ class LayoutEngine {
bindEventListeners() { bindEventListeners() {
this.body.emitter.on('_dataChanged', () => { this.body.emitter.on('_dataChanged', () => {
this.setupHierarchicalLayout(); this.setupHierarchicalLayout();
})
});
this.body.emitter.on('_resetHierarchicalLayout', () => { this.body.emitter.on('_resetHierarchicalLayout', () => {
this.setupHierarchicalLayout(); this.setupHierarchicalLayout();
}); });

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

@ -46,7 +46,7 @@ class ManipulationSystem {
borderWidth: 2, borderWidth: 2,
borderWidthSelected: 2 borderWidthSelected: 2
} }
}
};
util.extend(this.options, this.defaultOptions); util.extend(this.options, this.defaultOptions);
this.body.emitter.on('destroy', () => {this._clean();}); this.body.emitter.on('destroy', () => {this._clean();});

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

@ -216,7 +216,7 @@ class NodesHandler {
for (let i = 0; i < ids.length; i++) { for (let i = 0; i < ids.length; i++) {
id = ids[i]; id = ids[i];
let properties = this.body.data.nodes.get(id); let properties = this.body.data.nodes.get(id);
let node = this.create(properties);;
let node = this.create(properties);
newNodes.push(node); newNodes.push(node);
this.body.nodes[id] = node; // note: this may replace an existing node this.body.nodes[id] = node; // note: this may replace an existing node
} }
@ -386,7 +386,7 @@ class NodesHandler {
} }
else if (edge.fromId === nodeId) { else if (edge.fromId === nodeId) {
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;
} }
} }

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

@ -60,7 +60,7 @@ class PhysicsEngine {
fit: true fit: true
}, },
timestep: 0.5 timestep: 0.5
}
};
util.extend(this.options, this.defaultOptions); util.extend(this.options, this.defaultOptions);
this.bindEventListeners(); this.bindEventListeners();
@ -80,7 +80,7 @@ class PhysicsEngine {
if (this.ready === true) { if (this.ready === true) {
this.startSimulation(); this.startSimulation();
} }
})
});
this.body.emitter.on('stopSimulation', () => {this.stopSimulation();}); this.body.emitter.on('stopSimulation', () => {this.stopSimulation();});
this.body.emitter.on('destroy', () => { this.body.emitter.on('destroy', () => {
this.stopSimulation(false); this.stopSimulation(false);
@ -135,7 +135,7 @@ class PhysicsEngine {
else { else {
this.stabilized = false; this.stabilized = false;
this.ready = true; this.ready = true;
this.body.emitter.emit('fit', {}, true)
this.body.emitter.emit('fit', {}, true);
this.startSimulation(); this.startSimulation();
} }
} }

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

@ -39,7 +39,7 @@ class SelectionHandler {
let selected = false; let selected = false;
if (this.options.selectable === true) { if (this.options.selectable === true) {
this.unselectAll(); this.unselectAll();
let obj = this.getNodeAt(pointer) || this.getEdgeAt(pointer);;
let obj = this.getNodeAt(pointer) || this.getEdgeAt(pointer);
if (obj !== undefined) { if (obj !== undefined) {
selected = this.selectObject(obj); selected = this.selectObject(obj);
} }
@ -51,7 +51,7 @@ class SelectionHandler {
selectAdditionalOnPoint(pointer) { selectAdditionalOnPoint(pointer) {
let selectionChanged = false; let selectionChanged = false;
if (this.options.selectable === true) { if (this.options.selectable === true) {
let obj = this.getNodeAt(pointer) || this.getEdgeAt(pointer);;
let obj = this.getNodeAt(pointer) || this.getEdgeAt(pointer);
if (obj !== undefined) { if (obj !== undefined) {
selectionChanged = true; selectionChanged = true;
@ -73,7 +73,7 @@ class SelectionHandler {
properties['pointer'] = { properties['pointer'] = {
DOM: {x: pointer.x, y: pointer.y}, DOM: {x: pointer.x, y: pointer.y},
canvas: this.canvas.DOMtoCanvas(pointer) canvas: this.canvas.DOMtoCanvas(pointer)
}
};
properties['event'] = event; properties['event'] = event;
if (oldSelection !== undefined) { if (oldSelection !== undefined) {

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

@ -104,7 +104,7 @@ class Edge {
'to', 'to',
'title', 'title',
'value', 'value',
'width',
'width'
]; ];
// only deep extend the items in the field array. These do not have shorthand. // only deep extend the items in the field array. These do not have shorthand.

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

@ -1,4 +1,4 @@
let util = require("../../../../../util")
let util = require("../../../../../util");
class EdgeBase { class EdgeBase {
constructor(options, body, labelModule) { constructor(options, body, labelModule) {
@ -198,7 +198,7 @@ class EdgeBase {
let radius = this.options.selfReferenceSize; let radius = this.options.selfReferenceSize;
let pos, angle, distanceToBorder, distanceToPoint, difference; let pos, angle, distanceToBorder, distanceToPoint, difference;
let threshold = 0.05; let threshold = 0.05;
let middle = (low + high) * 0.5
let middle = (low + high) * 0.5;
while (low <= high && iteration < maxIterations) { while (low <= high && iteration < maxIterations) {
middle = (low + high) * 0.5; middle = (low + high) * 0.5;

+ 1
- 1
lib/network/modules/components/shared/Label.js View File

@ -90,7 +90,7 @@ class Label {
break; break;
case 'bottom': case 'bottom':
ctx.fillRect(-this.size.width * 0.5, lineMargin, this.size.width, this.size.height); ctx.fillRect(-this.size.width * 0.5, lineMargin, this.size.width, this.size.height);
break
break;
default: default:
ctx.fillRect(this.size.left, this.size.top, this.size.width, this.size.height); ctx.fillRect(this.size.left, this.size.top, this.size.width, this.size.height);
break; break;

+ 2
- 2
lib/timeline/Core.js View File

@ -688,7 +688,7 @@ Core.prototype._redraw = function() {
// reposition the scrollable contents // reposition the scrollable contents
var offset = this.props.scrollTop; var offset = this.props.scrollTop;
if (options.orientation.item == 'bottom') {
if (options.orientation.item != 'top') {
offset += Math.max(this.props.centerContainer.height - this.props.center.height - offset += Math.max(this.props.centerContainer.height - this.props.center.height -
this.props.border.top - this.props.border.bottom, 0); this.props.border.top - this.props.border.bottom, 0);
} }
@ -944,7 +944,7 @@ Core.prototype._updateScrollTop = function () {
if (scrollTopMin != this.props.scrollTopMin) { if (scrollTopMin != this.props.scrollTopMin) {
// in case of bottom orientation, change the scrollTop such that the contents // in case of bottom orientation, change the scrollTop such that the contents
// do not move relative to the time axis at the bottom // do not move relative to the time axis at the bottom
if (this.options.orientation.item == 'bottom') {
if (this.options.orientation.item != 'top') {
this.props.scrollTop += (scrollTopMin - this.props.scrollTopMin); this.props.scrollTop += (scrollTopMin - this.props.scrollTopMin);
} }
this.props.scrollTopMin = scrollTopMin; this.props.scrollTopMin = scrollTopMin;

+ 1
- 1
lib/timeline/component/GraphGroup.js View File

@ -138,7 +138,7 @@ GraphGroup.prototype.drawIcon = function(x, y, JSONcontainer, SVGcontainer, icon
path = DOMutil.getSVGElement("path", JSONcontainer, SVGcontainer); path = DOMutil.getSVGElement("path", JSONcontainer, SVGcontainer);
path.setAttributeNS(null, "class", this.className); path.setAttributeNS(null, "class", this.className);
if(this.style !== undefined) { if(this.style !== undefined) {
path.setAttributeNS(null, "style", 'vis-' + this.style);
path.setAttributeNS(null, "style", this.style);
} }
path.setAttributeNS(null, "d", "M" + x + ","+y+" L" + (x + iconWidth) + ","+y+""); path.setAttributeNS(null, "d", "M" + x + ","+y+" L" + (x + iconWidth) + ","+y+"");

+ 15
- 7
lib/timeline/component/ItemSet.js View File

@ -35,6 +35,8 @@ function ItemSet(body, options) {
groupOrder: null, groupOrder: null,
selectable: true, selectable: true,
multiselect: false,
editable: { editable: {
updateTime: false, updateTime: false,
updateGroup: false, updateGroup: false,
@ -226,7 +228,7 @@ ItemSet.prototype._create = function(){
* {Function} groupOrder * {Function} groupOrder
* A sorting function for ordering groups * A sorting function for ordering groups
* {Boolean} stack * {Boolean} stack
* If true (deafult), items will be stacked on
* If true (default), items will be stacked on
* top of each other. * top of each other.
* {Number} margin.axis * {Number} margin.axis
* Margin between the axis and the items in pixels. * Margin between the axis and the items in pixels.
@ -244,6 +246,9 @@ ItemSet.prototype._create = function(){
* Set margin for both axis and items in pixels. * Set margin for both axis and items in pixels.
* {Boolean} selectable * {Boolean} selectable
* If true (default), items can be selected. * If true (default), items can be selected.
* {Boolean} multiselect
* If true, multiple items can be selected.
* False by default.
* {Boolean} editable * {Boolean} editable
* Set all editable options to true or false * Set all editable options to true or false
* {Boolean} editable.updateTime * {Boolean} editable.updateTime
@ -272,7 +277,7 @@ ItemSet.prototype._create = function(){
ItemSet.prototype.setOptions = function(options) { ItemSet.prototype.setOptions = function(options) {
if (options) { if (options) {
// copy all options that we know // copy all options that we know
var fields = ['type', 'align', 'order', 'stack', 'selectable', 'groupOrder', 'dataAttributes', 'template','hide', 'snap'];
var fields = ['type', 'align', 'order', 'stack', 'selectable', 'multiselect', 'groupOrder', 'dataAttributes', 'template','hide', 'snap'];
util.selectiveExtend(fields, this.options, options); util.selectiveExtend(fields, this.options, options);
if ('orientation' in options) { if ('orientation' in options) {
@ -1465,15 +1470,18 @@ ItemSet.prototype._onAddItem = function (event) {
ItemSet.prototype._onMultiSelectItem = function (event) { ItemSet.prototype._onMultiSelectItem = function (event) {
if (!this.options.selectable) return; if (!this.options.selectable) return;
var selection,
item = this.itemFromTarget(event);
var item = this.itemFromTarget(event);
if (item) { if (item) {
// multi select items
selection = this.getSelection(); // current selection
// multi select items (if allowed)
var selection = this.options.multiselect
? this.getSelection() // take current selection
: []; // deselect current selection
var shiftKey = event.srcEvent && event.srcEvent.shiftKey || false; var shiftKey = event.srcEvent && event.srcEvent.shiftKey || false;
if (shiftKey) {
if (shiftKey && this.options.multiselect) {
// select all items between the old selection and the tapped item // select all items between the old selection and the tapped item
// determine the selection range // determine the selection range

+ 6
- 4
lib/timeline/component/LineGraph.js View File

@ -538,7 +538,9 @@ LineGraph.prototype.redraw = function(forceGraphUpdate) {
// calculate actual size and position // calculate actual size and position
this.props.width = this.dom.frame.offsetWidth; this.props.width = this.dom.frame.offsetWidth;
this.props.height = this.body.domProps.centerContainer.height;
this.props.height = this.body.domProps.centerContainer.height
- this.body.domProps.border.top
- this.body.domProps.border.bottom;
// update the graph if there is no lastWidth or with, used for the initial draw // update the graph if there is no lastWidth or with, used for the initial draw
if (this.lastWidth === undefined && this.props.width) { if (this.lastWidth === undefined && this.props.width) {
@ -568,9 +570,9 @@ LineGraph.prototype.redraw = function(forceGraphUpdate) {
// update the height of the graph on each redraw of the graph. // update the height of the graph on each redraw of the graph.
if (this.updateSVGheight == true) { if (this.updateSVGheight == true) {
if (this.options.graphHeight != this.body.domProps.centerContainer.height + 'px') {
this.options.graphHeight = this.body.domProps.centerContainer.height + 'px';
this.svg.style.height = this.body.domProps.centerContainer.height + 'px';
if (this.options.graphHeight != this.props.height + 'px') {
this.options.graphHeight = this.props.height + 'px';
this.svg.style.height = this.props.height + 'px';
} }
this.updateSVGheight = false; this.updateSVGheight = false;
} }

+ 1
- 1
lib/timeline/component/graph2d_types/line.js View File

@ -119,7 +119,7 @@ Line.prototype.draw = function (dataset, group, framework) {
path = DOMutil.getSVGElement('path', framework.svgElements, framework.svg); path = DOMutil.getSVGElement('path', framework.svgElements, framework.svg);
path.setAttributeNS(null, "class", group.className); path.setAttributeNS(null, "class", group.className);
if(group.style !== undefined) { if(group.style !== undefined) {
path.setAttributeNS(null, "style", 'vis-' + group.style);
path.setAttributeNS(null, "style", group.style);
} }
// construct path from dataset // construct path from dataset

Loading…
Cancel
Save