From bbbaeb48e009354c95fe050faf9261db2880555e Mon Sep 17 00:00:00 2001 From: jos Date: Fri, 4 Sep 2015 16:07:29 +0200 Subject: [PATCH 001/205] Fixed #1215: inconsistent types of properties `start` and `end` in callback functions `onMove`, `onMoving`, `onAdd` --- HISTORY.md | 5 ++ dist/vis.js | 93 +++++++++++++++++++++-------- lib/timeline/component/ItemSet.js | 97 +++++++++++++++++++------------ test/timeline_groups.html | 5 +- 4 files changed, 138 insertions(+), 62 deletions(-) diff --git a/HISTORY.md b/HISTORY.md index cc097f1d..141227e7 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -8,6 +8,11 @@ http://visjs.org - Added German (de) locale. Thanks @Tooa. +### Timeline + +- Fixed #1215: inconsistent types of properties `start` and `end` in callback + functions `onMove`, `onMoving`, `onAdd`. + ## 2015-08-28, version 4.8.0 diff --git a/dist/vis.js b/dist/vis.js index 76dfffa0..9195cc57 100644 --- a/dist/vis.js +++ b/dist/vis.js @@ -5,7 +5,7 @@ * A dynamic, browser-based visualization library. * * @version 4.8.1-SNAPSHOT - * @date 2015-08-28 + * @date 2015-09-04 * * @license * Copyright (C) 2011-2015 Almende B.V, http://almende.com @@ -16734,7 +16734,7 @@ return /******/ (function(modules) { // webpackBootstrap item: dragLeftItem, initialX: event.center.x, dragLeft: true, - data: util.extend({}, item.data) // clone the items data + data: this._cloneItemData(item.data) }; this.touchParams.itemProps = [props]; @@ -16743,7 +16743,7 @@ return /******/ (function(modules) { // webpackBootstrap item: dragRightItem, initialX: event.center.x, dragRight: true, - data: util.extend({}, item.data) // clone the items data + data: this._cloneItemData(item.data) }; this.touchParams.itemProps = [props]; @@ -16752,18 +16752,16 @@ return /******/ (function(modules) { // webpackBootstrap var baseGroupIndex = this._getGroupIndex(item.data.group); - this.touchParams.itemProps = this.getSelection().map(function (id) { + this.touchParams.itemProps = this.getSelection().map((function (id) { var item = me.items[id]; var groupIndex = me._getGroupIndex(item.data.group); - var props = { + return { item: item, initialX: event.center.x, groupOffset: baseGroupIndex - groupIndex, - data: util.extend({}, item.data) // clone the items data + data: this._cloneItemData(item.data) }; - - return props; - }); + }).bind(this)); } event.stopPropagation(); @@ -16805,14 +16803,14 @@ return /******/ (function(modules) { // webpackBootstrap var newItem = new RangeItem(itemData, this.conversion, this.options); newItem.id = id; // TODO: not so nice setting id afterwards - newItem.data = itemData; + newItem.data = this._cloneItemData(itemData); this._addItem(newItem); var props = { item: newItem, dragRight: true, initialX: event.center.x, - data: util.extend({}, itemData) + data: newItem.data }; this.touchParams.itemProps = [props]; @@ -16851,14 +16849,12 @@ return /******/ (function(modules) { // webpackBootstrap } // move - this.touchParams.itemProps.forEach(function (props) { - var newProps = {}; + this.touchParams.itemProps.forEach((function (props) { var current = me.body.util.toTime(event.center.x - xOffset); var initial = me.body.util.toTime(props.initialX - xOffset); - var offset = current - initial; - - var itemData = util.extend({}, props.item.data); // clone the data + var offset = current - initial; // ms + var itemData = this._cloneItemData(props.item.data); // clone the data if (props.item.editable === false) { return; } @@ -16871,6 +16867,7 @@ return /******/ (function(modules) { // webpackBootstrap if (itemData.start != undefined) { var initialStart = util.convert(props.data.start, 'Date'); var start = new Date(initialStart.valueOf() + offset); + // TODO: pass a Moment instead of a Date to snap(). (Breaking change) itemData.start = snap ? snap(start, scale, step) : start; } } else if (props.dragRight) { @@ -16878,6 +16875,7 @@ return /******/ (function(modules) { // webpackBootstrap if (itemData.end != undefined) { var initialEnd = util.convert(props.data.end, 'Date'); var end = new Date(initialEnd.valueOf() + offset); + // TODO: pass a Moment instead of a Date to snap(). (Breaking change) itemData.end = snap ? snap(end, scale, step) : end; } } else { @@ -16890,9 +16888,11 @@ return /******/ (function(modules) { // webpackBootstrap var initialEnd = util.convert(props.data.end, 'Date'); var duration = initialEnd.valueOf() - initialStart.valueOf(); + // TODO: pass a Moment instead of a Date to snap(). (Breaking change) itemData.start = snap ? snap(start, scale, step) : start; itemData.end = new Date(itemData.start.valueOf() + duration); } else { + // TODO: pass a Moment instead of a Date to snap(). (Breaking change) itemData.start = snap ? snap(start, scale, step) : start; } } @@ -16914,12 +16914,13 @@ return /******/ (function(modules) { // webpackBootstrap } // confirm moving the item + itemData = this._cloneItemData(itemData); // convert start and end to the correct type me.options.onMoving(itemData, function (itemData) { if (itemData) { props.item.setData(itemData); } }); - }); + }).bind(this)); this.stackDirty = true; // force re-stacking of all items next redraw this.body.emitter.emit('change'); @@ -16959,7 +16960,7 @@ return /******/ (function(modules) { // webpackBootstrap var itemProps = this.touchParams.itemProps; this.touchParams.itemProps = null; - itemProps.forEach(function (props) { + itemProps.forEach((function (props) { var id = props.item.id; var exists = me.itemsData.get(id, me.itemOptions) != null; @@ -16977,7 +16978,7 @@ return /******/ (function(modules) { // webpackBootstrap }); } else { // update existing item - var itemData = util.extend({}, props.item.data); // clone the data + var itemData = this._cloneItemData(props.item.data); // convert start and end to the correct type me.options.onMove(itemData, function (itemData) { if (itemData) { // apply changes @@ -16992,7 +16993,7 @@ return /******/ (function(modules) { // webpackBootstrap } }); } - }); + }).bind(this)); } }; @@ -17233,7 +17234,7 @@ return /******/ (function(modules) { // webpackBootstrap var scale = this.body.util.getScale(); var step = this.body.util.getStep(); - var newItem = { + var newItemData = { start: snap ? snap(start, scale, step) : start, content: 'new item' }; @@ -17241,18 +17242,19 @@ return /******/ (function(modules) { // webpackBootstrap // when default type is a range, add a default end date to the new item if (this.options.type === 'range') { var end = this.body.util.toTime(x + this.props.width / 5); - newItem.end = snap ? snap(end, scale, step) : end; + newItemData.end = snap ? snap(end, scale, step) : end; } - newItem[this.itemsData._fieldId] = util.randomUUID(); + newItemData[this.itemsData._fieldId] = util.randomUUID(); var group = this.groupFromTarget(event); if (group) { - newItem.group = group.groupId; + newItemData.group = group.groupId; } // execute async handler to customize (or cancel) adding an item - this.options.onAdd(newItem, function (item) { + newItemData = this._cloneItemData(newItemData); // convert start and end to the correct type + this.options.onAdd(newItemData, function (item) { if (item) { me.itemsData.getDataSet().add(item); // TODO: need to trigger a redraw? @@ -17419,6 +17421,29 @@ return /******/ (function(modules) { // webpackBootstrap return null; }; + /** + * Clone the data of an item, and "normalize" it: convert the start and end date + * to the type (Date, Moment, ...) configured in the DataSet. If not configured, + * start and end are converted to Date. + * @param {Object} itemData, typically `item.data` + * @return {Object} The cloned object + * @private + */ + ItemSet.prototype._cloneItemData = function (itemData) { + var clone = util.extend({}, itemData); + + // convert start and end date to the type (Date, Moment, ...) configured in the DataSet + var type = this.itemsData.getDataSet()._options.type; + if (clone.start != undefined) { + clone.start = util.convert(clone.start, type && type.start || 'Date'); + } + if (clone.end != undefined) { + clone.end = util.convert(clone.end, type && type.end || 'Date'); + } + + return clone; + }; + module.exports = ItemSet; /***/ }, @@ -43054,6 +43079,24 @@ return /******/ (function(modules) { // webpackBootstrap exports['en_EN'] = exports['en']; exports['en_US'] = exports['en']; + // German + exports['de'] = { + edit: 'Editieren', + del: 'Lösche Auswahl', + back: 'Zurück', + addNode: 'Knoten hinzufügen', + addEdge: 'Kante hinzufügen', + editNode: 'Knoten editieren', + editEdge: 'Kante editieren', + addDescription: 'Klicke auf eine freie Stelle, um einen neuen Knoten zu plazieren.', + edgeDescription: 'Klicke auf einen Knoten und ziehe die Kante zu einem anderen Knoten, um diese zu verbinden.', + editEdgeDescription: 'Klicke auf die Verbindungspunkte und ziehe diese auf einen Knoten, um sie zu verbinden.', + createEdgeError: 'Es ist nicht möglich, Kanten mit Clustern zu verbinden.', + deleteClusterError: 'Cluster können nicht gelöscht werden.', + editClusterError: 'Cluster können nicht editiert werden.' + }; + exports['de_DE'] = exports['de']; + // Spanish exports['es'] = { edit: 'Editar', diff --git a/lib/timeline/component/ItemSet.js b/lib/timeline/component/ItemSet.js index be30cf67..c4c11511 100644 --- a/lib/timeline/component/ItemSet.js +++ b/lib/timeline/component/ItemSet.js @@ -1160,7 +1160,7 @@ ItemSet.prototype._getGroupIndex = function(groupId) { if (groupId == this.groupIds[i]) return i; } -} +}; /** * Start dragging the selected events @@ -1174,8 +1174,8 @@ ItemSet.prototype._onDragStart = function (event) { if (item && item.selected) { - if (!this.options.editable.updateTime && - !this.options.editable.updateGroup && + if (!this.options.editable.updateTime && + !this.options.editable.updateGroup && !item.editable) { return; } @@ -1193,7 +1193,7 @@ ItemSet.prototype._onDragStart = function (event) { item: dragLeftItem, initialX: event.center.x, dragLeft: true, - data: util.extend({}, item.data) // clone the items data + data: this._cloneItemData(item.data) }; this.touchParams.itemProps = [props]; @@ -1203,7 +1203,7 @@ ItemSet.prototype._onDragStart = function (event) { item: dragRightItem, initialX: event.center.x, dragRight: true, - data: util.extend({}, item.data) // clone the items data + data: this._cloneItemData(item.data) }; this.touchParams.itemProps = [props]; @@ -1216,15 +1216,13 @@ ItemSet.prototype._onDragStart = function (event) { this.touchParams.itemProps = this.getSelection().map(function (id) { var item = me.items[id]; var groupIndex = me._getGroupIndex(item.data.group); - var props = { + return { item: item, initialX: event.center.x, groupOffset: baseGroupIndex-groupIndex, - data: util.extend({}, item.data) // clone the items data + data: this._cloneItemData(item.data) }; - - return props; - }); + }.bind(this)); } event.stopPropagation(); @@ -1267,14 +1265,14 @@ ItemSet.prototype._onDragStartAddItem = function (event) { var newItem = new RangeItem(itemData, this.conversion, this.options); newItem.id = id; // TODO: not so nice setting id afterwards - newItem.data = itemData; + newItem.data = this._cloneItemData(itemData); this._addItem(newItem); var props = { item: newItem, dragRight: true, initialX: event.center.x, - data: util.extend({}, itemData) + data: newItem.data }; this.touchParams.itemProps = [props]; @@ -1301,32 +1299,30 @@ ItemSet.prototype._onDrag = function (event) { var updateGroupAllowed = me.options.editable.updateGroup; var newGroupBase = null; if (updateGroupAllowed && selectedItem) { - if (selectedItem.data.group != undefined) { - // drag from one group to another - var group = me.groupFromTarget(event); - if (group) { - //we know the offset for all items, so the new group for all items - //will be relative to this one. - newGroupBase = this._getGroupIndex(group.groupId); - } + if (selectedItem.data.group != undefined) { + // drag from one group to another + var group = me.groupFromTarget(event); + if (group) { + //we know the offset for all items, so the new group for all items + //will be relative to this one. + newGroupBase = this._getGroupIndex(group.groupId); } + } } // move this.touchParams.itemProps.forEach(function (props) { - var newProps = {}; var current = me.body.util.toTime(event.center.x - xOffset); var initial = me.body.util.toTime(props.initialX - xOffset); - var offset = current - initial; - - var itemData = util.extend({}, props.item.data); // clone the data + var offset = current - initial; // ms + var itemData = this._cloneItemData(props.item.data); // clone the data if (props.item.editable === false) { return; } - var updateTimeAllowed = me.options.editable.updateTime || - props.item.editable === true; + var updateTimeAllowed = me.options.editable.updateTime || + props.item.editable === true; if (updateTimeAllowed) { if (props.dragLeft) { @@ -1334,6 +1330,7 @@ ItemSet.prototype._onDrag = function (event) { if (itemData.start != undefined) { var initialStart = util.convert(props.data.start, 'Date'); var start = new Date(initialStart.valueOf() + offset); + // TODO: pass a Moment instead of a Date to snap(). (Breaking change) itemData.start = snap ? snap(start, scale, step) : start; } } @@ -1342,6 +1339,7 @@ ItemSet.prototype._onDrag = function (event) { if (itemData.end != undefined) { var initialEnd = util.convert(props.data.end, 'Date'); var end = new Date(initialEnd.valueOf() + offset); + // TODO: pass a Moment instead of a Date to snap(). (Breaking change) itemData.end = snap ? snap(end, scale, step) : end; } } @@ -1355,18 +1353,20 @@ ItemSet.prototype._onDrag = function (event) { var initialEnd = util.convert(props.data.end, 'Date'); var duration = initialEnd.valueOf() - initialStart.valueOf(); + // TODO: pass a Moment instead of a Date to snap(). (Breaking change) itemData.start = snap ? snap(start, scale, step) : start; itemData.end = new Date(itemData.start.valueOf() + duration); } else { + // TODO: pass a Moment instead of a Date to snap(). (Breaking change) itemData.start = snap ? snap(start, scale, step) : start; } } } } - var updateGroupAllowed = me.options.editable.updateGroup || - props.item.editable === true; + var updateGroupAllowed = me.options.editable.updateGroup || + props.item.editable === true; if (updateGroupAllowed && (!props.dragLeft && !props.dragRight) && newGroupBase!=null) { if (itemData.group != undefined) { @@ -1381,12 +1381,13 @@ ItemSet.prototype._onDrag = function (event) { } // confirm moving the item + itemData = this._cloneItemData(itemData); // convert start and end to the correct type me.options.onMoving(itemData, function (itemData) { if (itemData) { props.item.setData(itemData); } }); - }); + }.bind(this)); this.stackDirty = true; // force re-stacking of all items next redraw this.body.emitter.emit('change'); @@ -1445,7 +1446,7 @@ ItemSet.prototype._onDragEnd = function (event) { } else { // update existing item - var itemData = util.extend({}, props.item.data); // clone the data + var itemData = this._cloneItemData(props.item.data); // convert start and end to the correct type me.options.onMove(itemData, function (itemData) { if (itemData) { // apply changes @@ -1461,7 +1462,7 @@ ItemSet.prototype._onDragEnd = function (event) { } }); } - }); + }.bind(this)); } }; @@ -1708,7 +1709,7 @@ ItemSet.prototype._onAddItem = function (event) { var scale = this.body.util.getScale(); var step = this.body.util.getStep(); - var newItem = { + var newItemData = { start: snap ? snap(start, scale, step) : start, content: 'new item' }; @@ -1716,18 +1717,19 @@ ItemSet.prototype._onAddItem = function (event) { // when default type is a range, add a default end date to the new item if (this.options.type === 'range') { var end = this.body.util.toTime(x + this.props.width / 5); - newItem.end = snap ? snap(end, scale, step) : end; + newItemData.end = snap ? snap(end, scale, step) : end; } - newItem[this.itemsData._fieldId] = util.randomUUID(); + newItemData[this.itemsData._fieldId] = util.randomUUID(); var group = this.groupFromTarget(event); if (group) { - newItem.group = group.groupId; + newItemData.group = group.groupId; } // execute async handler to customize (or cancel) adding an item - this.options.onAdd(newItem, function (item) { + newItemData = this._cloneItemData(newItemData); // convert start and end to the correct type + this.options.onAdd(newItemData, function (item) { if (item) { me.itemsData.getDataSet().add(item); // TODO: need to trigger a redraw? @@ -1901,4 +1903,27 @@ ItemSet.itemSetFromTarget = function(event) { return null; }; +/** + * Clone the data of an item, and "normalize" it: convert the start and end date + * to the type (Date, Moment, ...) configured in the DataSet. If not configured, + * start and end are converted to Date. + * @param {Object} itemData, typically `item.data` + * @return {Object} The cloned object + * @private + */ +ItemSet.prototype._cloneItemData = function (itemData) { + var clone = util.extend({}, itemData); + + // convert start and end date to the type (Date, Moment, ...) configured in the DataSet + var type = this.itemsData.getDataSet()._options.type; + if (clone.start != undefined) { + clone.start = util.convert(clone.start, type && type.start || 'Date'); + } + if (clone.end != undefined) { + clone.end = util.convert(clone.end , type && type.end || 'Date'); + } + + return clone; +}; + module.exports = ItemSet; diff --git a/test/timeline_groups.html b/test/timeline_groups.html index aac1c2ca..4df1b433 100644 --- a/test/timeline_groups.html +++ b/test/timeline_groups.html @@ -71,7 +71,9 @@ } // create a dataset with items - var items = new vis.DataSet(); + var items = new vis.DataSet({ + type: {start: 'Moment', end: 'Moment'} + }); for (var i = 0; i < itemCount; i++) { var start = now.clone().add(Math.random() * 200, 'hours'); var end = Math.random() > 0.5 ? start.clone().add(24, 'hours') : undefined; @@ -117,6 +119,7 @@ }, onMove: function (item, callback) { + console.log('onMove', item) if (confirm('Do you really want to move the item to\n' + 'start: ' + item.start + '\n' + 'end: ' + item.end + '?')) { From d97bb0db68ab6e3ed39e279e24afe965dab5deb3 Mon Sep 17 00:00:00 2001 From: jos Date: Fri, 4 Sep 2015 16:15:35 +0200 Subject: [PATCH 002/205] Fixed #1267: wrong description for `clickToUse` --- docs/network/index.html | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/docs/network/index.html b/docs/network/index.html index dc0eaf40..a930d4b5 100644 --- a/docs/network/index.html +++ b/docs/network/index.html @@ -333,11 +333,7 @@ network.setOptions(options); clickToUse Boolean false - Locales object. By default only 'en', 'de', 'es' and 'nl' are supported. Take a look - at - the locales - section below for more explaination on how to customize this. + When a Network is configured to be clickToUse, it will react to mouse and touch events only when active. When active, a blue shadow border is displayed around the Network. The network is set active by clicking on it, and is changed to inactive again by clicking outside the Network or by pressing the ESC key. configure From 3f5c71eea3c819bcb4603714ffe45fa2d7ef8544 Mon Sep 17 00:00:00 2001 From: Alex de Mulder Date: Sun, 6 Sep 2015 15:38:27 +0200 Subject: [PATCH 003/205] - Fixed critical camera zoom bug #1273. #1266, #1255 - unified some methods in the networkUtil - Fixed initial zoom issues #1252 --- HISTORY.md | 1 + dist/vis.js | 6824 +++++++++++++------------ dist/vis.min.css | 2 +- examples/network/exampleUtil.js | 56 + lib/network/NetworkUtil.js | 77 + lib/network/modules/Canvas.js | 39 +- lib/network/modules/CanvasRenderer.js | 12 +- lib/network/modules/LayoutEngine.js | 24 + lib/network/modules/PhysicsEngine.js | 4 +- lib/network/modules/View.js | 115 +- test/networkTest.html | 141 +- 11 files changed, 3742 insertions(+), 3553 deletions(-) create mode 100644 lib/network/NetworkUtil.js diff --git a/HISTORY.md b/HISTORY.md index cc097f1d..238152d2 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -7,6 +7,7 @@ http://visjs.org ### Network - Added German (de) locale. Thanks @Tooa. +- Fixed critical camera zoom bug #1273. ## 2015-08-28, version 4.8.0 diff --git a/dist/vis.js b/dist/vis.js index 76dfffa0..cdace7bc 100644 --- a/dist/vis.js +++ b/dist/vis.js @@ -5,7 +5,7 @@ * A dynamic, browser-based visualization library. * * @version 4.8.1-SNAPSHOT - * @date 2015-08-28 + * @date 2015-09-06 * * @license * Copyright (C) 2011-2015 Almende B.V, http://almende.com @@ -29,7 +29,7 @@ if(typeof exports === 'object' && typeof module === 'object') module.exports = factory(); else if(typeof define === 'function' && define.amd) - define([], factory); + define(factory); else if(typeof exports === 'object') exports["vis"] = factory(); else @@ -97,8 +97,8 @@ return /******/ (function(modules) { // webpackBootstrap exports.graph3d = { Camera: __webpack_require__(15), Filter: __webpack_require__(16), - Point2d: __webpack_require__(14), - Point3d: __webpack_require__(13), + Point2d: __webpack_require__(12), + Point3d: __webpack_require__(14), Slider: __webpack_require__(17), StepNumber: __webpack_require__(18) }; @@ -110,16 +110,16 @@ return /******/ (function(modules) { // webpackBootstrap DateUtil: __webpack_require__(27), DataStep: __webpack_require__(52), Range: __webpack_require__(24), - stack: __webpack_require__(32), - TimeStep: __webpack_require__(30), + stack: __webpack_require__(31), + TimeStep: __webpack_require__(34), components: { items: { - Item: __webpack_require__(34), + Item: __webpack_require__(33), BackgroundItem: __webpack_require__(38), BoxItem: __webpack_require__(36), PointItem: __webpack_require__(37), - RangeItem: __webpack_require__(33) + RangeItem: __webpack_require__(32) }, Component: __webpack_require__(26), @@ -127,7 +127,7 @@ return /******/ (function(modules) { // webpackBootstrap CustomTime: __webpack_require__(42), DataAxis: __webpack_require__(51), GraphGroup: __webpack_require__(53), - Group: __webpack_require__(31), + Group: __webpack_require__(30), BackgroundGroup: __webpack_require__(35), ItemSet: __webpack_require__(29), Legend: __webpack_require__(57), @@ -139,10 +139,10 @@ return /******/ (function(modules) { // webpackBootstrap // Network exports.Network = __webpack_require__(59); exports.network = { - Images: __webpack_require__(116), - dotparser: __webpack_require__(114), - gephiParser: __webpack_require__(115), - allOptions: __webpack_require__(110) + Images: __webpack_require__(117), + dotparser: __webpack_require__(115), + gephiParser: __webpack_require__(116), + allOptions: __webpack_require__(111) }; exports.network.convertDot = function (input) { return exports.network.dotparser.DOTToGraph(input); @@ -551,11 +551,11 @@ return /******/ (function(modules) { // webpackBootstrap // object is an ASP date return new Date(Number(match[1])); // parse number } else { - return moment(object).toDate(); // parse string - } + return moment(object).toDate(); // parse string + } } else { - throw new Error('Cannot convert object of type ' + exports.getType(object) + ' to type Date'); - } + throw new Error('Cannot convert object of type ' + exports.getType(object) + ' to type Date'); + } case 'Moment': if (exports.isNumber(object)) { @@ -572,11 +572,11 @@ return /******/ (function(modules) { // webpackBootstrap // object is an ASP date return moment(Number(match[1])); // parse number } else { - return moment(object); // parse string - } + return moment(object); // parse string + } } else { - throw new Error('Cannot convert object of type ' + exports.getType(object) + ' to type Date'); - } + throw new Error('Cannot convert object of type ' + exports.getType(object) + ' to type Date'); + } case 'ISODate': if (exports.isNumber(object)) { @@ -591,11 +591,11 @@ return /******/ (function(modules) { // webpackBootstrap // object is an ASP date return new Date(Number(match[1])).toISOString(); // parse number } else { - return new Date(object).toISOString(); // parse string - } + return new Date(object).toISOString(); // parse string + } } else { - throw new Error('Cannot convert object of type ' + exports.getType(object) + ' to type ISODate'); - } + throw new Error('Cannot convert object of type ' + exports.getType(object) + ' to type ISODate'); + } case 'ASPDate': if (exports.isNumber(object)) { @@ -609,8 +609,8 @@ return /******/ (function(modules) { // webpackBootstrap // object is an ASP date value = new Date(Number(match[1])).valueOf(); // parse number } else { - value = new Date(object).valueOf(); // parse string - } + value = new Date(object).valueOf(); // parse string + } return '/Date(' + value + ')/'; } else { throw new Error('Cannot convert object of type ' + exports.getType(object) + ' to type ASPDate'); @@ -842,13 +842,13 @@ return /******/ (function(modules) { // webpackBootstrap if (element.addEventListener) { if (useCapture === undefined) useCapture = false; - if (action === 'mousewheel' && navigator.userAgent.indexOf('Firefox') >= 0) { - action = 'DOMMouseScroll'; // For Firefox + if (action === "mousewheel" && navigator.userAgent.indexOf("Firefox") >= 0) { + action = "DOMMouseScroll"; // For Firefox } element.addEventListener(action, listener, useCapture); } else { - element.attachEvent('on' + action, listener); // IE browsers + element.attachEvent("on" + action, listener); // IE browsers } }; @@ -864,14 +864,14 @@ return /******/ (function(modules) { // webpackBootstrap // non-IE browsers if (useCapture === undefined) useCapture = false; - if (action === 'mousewheel' && navigator.userAgent.indexOf('Firefox') >= 0) { - action = 'DOMMouseScroll'; // For Firefox + if (action === "mousewheel" && navigator.userAgent.indexOf("Firefox") >= 0) { + action = "DOMMouseScroll"; // For Firefox } element.removeEventListener(action, listener, useCapture); } else { // IE browsers - element.detachEvent('on' + action, listener); + element.detachEvent("on" + action, listener); } }; @@ -884,8 +884,8 @@ return /******/ (function(modules) { // webpackBootstrap if (event.preventDefault) { event.preventDefault(); // non-IE browsers } else { - event.returnValue = false; // IE browsers - } + event.returnValue = false; // IE browsers + } }; /** @@ -1050,17 +1050,17 @@ return /******/ (function(modules) { // webpackBootstrap * @returns {*} */ exports.overrideOpacity = function (color, opacity) { - if (color.indexOf('rgba') != -1) { + if (color.indexOf("rgba") != -1) { return color; - } else if (color.indexOf('rgb') != -1) { - var rgb = color.substr(color.indexOf('(') + 1).replace(')', '').split(','); - return 'rgba(' + rgb[0] + ',' + rgb[1] + ',' + rgb[2] + ',' + opacity + ')'; + } else if (color.indexOf("rgb") != -1) { + var rgb = color.substr(color.indexOf("(") + 1).replace(")", "").split(","); + return "rgba(" + rgb[0] + "," + rgb[1] + "," + rgb[2] + "," + opacity + ")"; } else { var rgb = exports.hexToRGB(color); if (rgb == null) { return color; } else { - return 'rgba(' + rgb.r + ',' + rgb.g + ',' + rgb.b + ',' + opacity + ')'; + return "rgba(" + rgb.r + "," + rgb.g + "," + rgb.b + "," + opacity + ")"; } } }; @@ -1074,7 +1074,7 @@ return /******/ (function(modules) { // webpackBootstrap * @constructor */ exports.RGBToHex = function (red, green, blue) { - return '#' + ((1 << 24) + (red << 16) + (green << 8) + blue).toString(16).slice(1); + return "#" + ((1 << 24) + (red << 16) + (green << 8) + blue).toString(16).slice(1); }; /** @@ -1290,12 +1290,12 @@ return /******/ (function(modules) { // webpackBootstrap }; exports.isValidRGB = function (rgb) { - rgb = rgb.replace(' ', ''); + rgb = rgb.replace(" ", ""); var isOk = /rgb\((\d{1,3}),(\d{1,3}),(\d{1,3})\)/i.test(rgb); return isOk; }; exports.isValidRGBA = function (rgba) { - rgba = rgba.replace(' ', ''); + rgba = rgba.replace(" ", ""); var isOk = /rgba\((\d{1,3}),(\d{1,3}),(\d{1,3}),(.{1,3})\)/i.test(rgba); return isOk; }; @@ -1308,11 +1308,11 @@ return /******/ (function(modules) { // webpackBootstrap * @returns {*} */ exports.selectiveBridgeObject = function (fields, referenceObject) { - if (typeof referenceObject == 'object') { + if (typeof referenceObject == "object") { var objectTo = Object.create(referenceObject); for (var i = 0; i < fields.length; i++) { if (referenceObject.hasOwnProperty(fields[i])) { - if (typeof referenceObject[fields[i]] == 'object') { + if (typeof referenceObject[fields[i]] == "object") { objectTo[fields[i]] = exports.bridgeObject(referenceObject[fields[i]]); } } @@ -1331,11 +1331,11 @@ return /******/ (function(modules) { // webpackBootstrap * @returns {*} */ exports.bridgeObject = function (referenceObject) { - if (typeof referenceObject == 'object') { + if (typeof referenceObject == "object") { var objectTo = Object.create(referenceObject); for (var i in referenceObject) { if (referenceObject.hasOwnProperty(i)) { - if (typeof referenceObject[i] == 'object') { + if (typeof referenceObject[i] == "object") { objectTo[i] = exports.bridgeObject(referenceObject[i]); } } @@ -1547,13 +1547,13 @@ return /******/ (function(modules) { // webpackBootstrap /***/ function(module, exports, __webpack_require__) { /* WEBPACK VAR INJECTION */(function(module) {//! moment.js - //! version : 2.10.6 + //! version : 2.10.3 //! authors : Tim Wood, Iskren Chernev, Moment.js contributors //! license : MIT //! momentjs.com (function (global, factory) { - true ? module.exports = factory() : + true ? module.exports = factory() : typeof define === 'function' && define.amd ? define(factory) : global.moment = factory() }(this, function () { 'use strict'; @@ -1642,7 +1642,6 @@ return /******/ (function(modules) { // webpackBootstrap flags.overflow < 0 && !flags.empty && !flags.invalidMonth && - !flags.invalidWeekday && !flags.nullInput && !flags.invalidFormat && !flags.userInvalidated; @@ -1723,7 +1722,7 @@ return /******/ (function(modules) { // webpackBootstrap // Moment prototype object function Moment(config) { copyConfig(this, config); - this._d = new Date(config._d != null ? config._d.getTime() : NaN); + this._d = new Date(+config._d); // Prevent infinite loop in case updateOffset creates new moment // objects. if (updateInProgress === false) { @@ -1737,20 +1736,16 @@ return /******/ (function(modules) { // webpackBootstrap return obj instanceof Moment || (obj != null && obj._isAMomentObject != null); } - function absFloor (number) { - if (number < 0) { - return Math.ceil(number); - } else { - return Math.floor(number); - } - } - function toInt(argumentForCoercion) { var coercedNumber = +argumentForCoercion, value = 0; if (coercedNumber !== 0 && isFinite(coercedNumber)) { - value = absFloor(coercedNumber); + if (coercedNumber >= 0) { + value = Math.floor(coercedNumber); + } else { + value = Math.ceil(coercedNumber); + } } return value; @@ -1848,7 +1843,9 @@ return /******/ (function(modules) { // webpackBootstrap function defineLocale (name, values) { if (values !== null) { values.abbr = name; - locales[name] = locales[name] || new Locale(); + if (!locales[name]) { + locales[name] = new Locale(); + } locales[name].set(values); // backwards compat for now: also set the locale @@ -1952,14 +1949,16 @@ return /******/ (function(modules) { // webpackBootstrap } function zeroFill(number, targetLength, forceSign) { - var absNumber = '' + Math.abs(number), - zerosToFill = targetLength - absNumber.length, + var output = '' + Math.abs(number), sign = number >= 0; - return (sign ? (forceSign ? '+' : '') : '-') + - Math.pow(10, Math.max(0, zerosToFill)).toString().substr(1) + absNumber; + + while (output.length < targetLength) { + output = '0' + output; + } + return (sign ? (forceSign ? '+' : '') : '-') + output; } - var formattingTokens = /(\[[^\[]*\])|(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Q|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|mm?|ss?|S{1,9}|x|X|zz?|ZZ?|.)/g; + var formattingTokens = /(\[[^\[]*\])|(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Q|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|mm?|ss?|S{1,4}|x|X|zz?|ZZ?|.)/g; var localFormattingTokens = /(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g; @@ -2027,7 +2026,10 @@ return /******/ (function(modules) { // webpackBootstrap } format = expandFormat(format, m.localeData()); - formatFunctions[format] = formatFunctions[format] || makeFormatFunction(format); + + if (!formatFunctions[format]) { + formatFunctions[format] = makeFormatFunction(format); + } return formatFunctions[format](m); } @@ -2071,15 +2073,8 @@ return /******/ (function(modules) { // webpackBootstrap var regexes = {}; - function isFunction (sth) { - // https://github.com/moment/moment/issues/2325 - return typeof sth === 'function' && - Object.prototype.toString.call(sth) === '[object Function]'; - } - - function addRegexToken (token, regex, strictRegex) { - regexes[token] = isFunction(regex) ? regex : function (isStrict) { + regexes[token] = typeof regex === 'function' ? regex : function (isStrict) { return (isStrict && strictRegex) ? strictRegex : regex; }; } @@ -2287,11 +2282,12 @@ return /******/ (function(modules) { // webpackBootstrap } function deprecate(msg, fn) { - var firstTime = true; + var firstTime = true, + msgWithStack = msg + '\n' + (new Error()).stack; return extend(function () { if (firstTime) { - warn(msg + '\n' + (new Error()).stack); + warn(msgWithStack); firstTime = false; } return fn.apply(this, arguments); @@ -2339,14 +2335,14 @@ return /******/ (function(modules) { // webpackBootstrap getParsingFlags(config).iso = true; for (i = 0, l = isoDates.length; i < l; i++) { if (isoDates[i][1].exec(string)) { - config._f = isoDates[i][0]; + // match[5] should be 'T' or undefined + config._f = isoDates[i][0] + (match[6] || ' '); break; } } for (i = 0, l = isoTimes.length; i < l; i++) { if (isoTimes[i][1].exec(string)) { - // match[6] should be 'T' or space - config._f += (match[6] || ' ') + isoTimes[i][0]; + config._f += isoTimes[i][0]; break; } } @@ -2425,10 +2421,7 @@ return /******/ (function(modules) { // webpackBootstrap addRegexToken('YYYYY', match1to6, match6); addRegexToken('YYYYYY', match1to6, match6); - addParseToken(['YYYYY', 'YYYYYY'], YEAR); - addParseToken('YYYY', function (input, array) { - array[YEAR] = input.length === 2 ? utils_hooks__hooks.parseTwoDigitYear(input) : toInt(input); - }); + addParseToken(['YYYY', 'YYYYY', 'YYYYYY'], YEAR); addParseToken('YY', function (input, array) { array[YEAR] = utils_hooks__hooks.parseTwoDigitYear(input); }); @@ -2555,18 +2548,18 @@ return /******/ (function(modules) { // webpackBootstrap //http://en.wikipedia.org/wiki/ISO_week_date#Calculating_a_date_given_the_year.2C_week_number_and_weekday function dayOfYearFromWeeks(year, week, weekday, firstDayOfWeekOfYear, firstDayOfWeek) { - var week1Jan = 6 + firstDayOfWeek - firstDayOfWeekOfYear, janX = createUTCDate(year, 0, 1 + week1Jan), d = janX.getUTCDay(), dayOfYear; - if (d < firstDayOfWeek) { - d += 7; - } + var d = createUTCDate(year, 0, 1).getUTCDay(); + var daysToAdd; + var dayOfYear; - weekday = weekday != null ? 1 * weekday : firstDayOfWeek; - - dayOfYear = 1 + week1Jan + 7 * (week - 1) - d + weekday; + d = d === 0 ? 7 : d; + weekday = weekday != null ? weekday : firstDayOfWeek; + daysToAdd = firstDayOfWeek - d + (d > firstDayOfWeekOfYear ? 7 : 0) - (d < firstDayOfWeek ? 7 : 0); + dayOfYear = 7 * (week - 1) + (weekday - firstDayOfWeek) + daysToAdd + 1; return { - year: dayOfYear > 0 ? year : year - 1, - dayOfYear: dayOfYear > 0 ? dayOfYear : daysInYear(year - 1) + dayOfYear + year : dayOfYear > 0 ? year : year - 1, + dayOfYear : dayOfYear > 0 ? dayOfYear : daysInYear(year - 1) + dayOfYear }; } @@ -2852,19 +2845,9 @@ return /******/ (function(modules) { // webpackBootstrap } function createFromConfig (config) { - var res = new Moment(checkOverflow(prepareConfig(config))); - if (res._nextDay) { - // Adding is smart enough around DST - res.add(1, 'd'); - res._nextDay = undefined; - } - - return res; - } - - function prepareConfig (config) { var input = config._i, - format = config._f; + format = config._f, + res; config._locale = config._locale || locale_locales__getLocale(config._l); @@ -2888,7 +2871,14 @@ return /******/ (function(modules) { // webpackBootstrap configFromInput(config); } - return config; + res = new Moment(checkOverflow(config)); + if (res._nextDay) { + // Adding is smart enough around DST + res.add(1, 'd'); + res._nextDay = undefined; + } + + return res; } function configFromInput(config) { @@ -2968,7 +2958,7 @@ return /******/ (function(modules) { // webpackBootstrap } res = moments[0]; for (i = 1; i < moments.length; ++i) { - if (!moments[i].isValid() || moments[i][fn](res)) { + if (moments[i][fn](res)) { res = moments[i]; } } @@ -3080,6 +3070,7 @@ return /******/ (function(modules) { // webpackBootstrap } else { return local__createLocal(input).local(); } + return model._isUTC ? local__createLocal(input).zone(model._offset || 0) : local__createLocal(input).local(); } function getDateOffset (m) { @@ -3179,7 +3170,12 @@ return /******/ (function(modules) { // webpackBootstrap } function hasAlignedHourOffset (input) { - input = input ? local__createLocal(input).utcOffset() : 0; + if (!input) { + input = 0; + } + else { + input = local__createLocal(input).utcOffset(); + } return (this.utcOffset() - input) % 60 === 0; } @@ -3192,24 +3188,12 @@ return /******/ (function(modules) { // webpackBootstrap } function isDaylightSavingTimeShifted () { - if (typeof this._isDSTShifted !== 'undefined') { - return this._isDSTShifted; + if (this._a) { + var other = this._isUTC ? create_utc__createUTC(this._a) : local__createLocal(this._a); + return this.isValid() && compareArrays(this._a, other.toArray()) > 0; } - var c = {}; - - copyConfig(c, this); - c = prepareConfig(c); - - if (c._a) { - var other = c._isUTC ? create_utc__createUTC(c._a) : local__createLocal(c._a); - this._isDSTShifted = this.isValid() && - compareArrays(c._a, other.toArray()) > 0; - } else { - this._isDSTShifted = false; - } - - return this._isDSTShifted; + return false; } function isLocal () { @@ -3369,7 +3353,7 @@ return /******/ (function(modules) { // webpackBootstrap var add_subtract__add = createAdder(1, 'add'); var add_subtract__subtract = createAdder(-1, 'subtract'); - function moment_calendar__calendar (time, formats) { + function moment_calendar__calendar (time) { // We want to compare the start of today, vs this. // Getting start-of-today depends on whether we're local/utc/offset or not. var now = time || local__createLocal(), @@ -3381,7 +3365,7 @@ return /******/ (function(modules) { // webpackBootstrap diff < 1 ? 'sameDay' : diff < 2 ? 'nextDay' : diff < 7 ? 'nextWeek' : 'sameElse'; - return this.format(formats && formats[format] || this.localeData().calendar(format, this, local__createLocal(now))); + return this.format(this.localeData().calendar(format, this, local__createLocal(now))); } function clone () { @@ -3428,6 +3412,14 @@ return /******/ (function(modules) { // webpackBootstrap } } + function absFloor (number) { + if (number < 0) { + return Math.ceil(number); + } else { + return Math.floor(number); + } + } + function diff (input, units, asFloat) { var that = cloneWithOffset(input, this), zoneDelta = (that.utcOffset() - this.utcOffset()) * 6e4, @@ -3618,19 +3610,6 @@ return /******/ (function(modules) { // webpackBootstrap return [m.year(), m.month(), m.date(), m.hour(), m.minute(), m.second(), m.millisecond()]; } - function toObject () { - var m = this; - return { - years: m.year(), - months: m.month(), - date: m.date(), - hours: m.hours(), - minutes: m.minutes(), - seconds: m.seconds(), - milliseconds: m.milliseconds() - }; - } - function moment_valid__isValid () { return valid__isValid(this); } @@ -3802,20 +3781,18 @@ return /******/ (function(modules) { // webpackBootstrap // HELPERS function parseWeekday(input, locale) { - if (typeof input !== 'string') { - return input; - } - - if (!isNaN(input)) { - return parseInt(input, 10); - } - - input = locale.weekdaysParse(input); - if (typeof input === 'number') { - return input; + if (typeof input === 'string') { + if (!isNaN(input)) { + input = parseInt(input, 10); + } + else { + input = locale.weekdaysParse(input); + if (typeof input !== 'number') { + return null; + } + } } - - return null; + return input; } // LOCALES @@ -3838,7 +3815,9 @@ return /******/ (function(modules) { // webpackBootstrap function localeWeekdaysParse (weekdayName) { var i, mom, regex; - this._weekdaysParse = this._weekdaysParse || []; + if (!this._weekdaysParse) { + this._weekdaysParse = []; + } for (i = 0; i < 7; i++) { // make the regex if we don't have it already @@ -3985,26 +3964,12 @@ return /******/ (function(modules) { // webpackBootstrap return ~~(this.millisecond() / 10); }); - addFormatToken(0, ['SSS', 3], 0, 'millisecond'); - addFormatToken(0, ['SSSS', 4], 0, function () { - return this.millisecond() * 10; - }); - addFormatToken(0, ['SSSSS', 5], 0, function () { - return this.millisecond() * 100; - }); - addFormatToken(0, ['SSSSSS', 6], 0, function () { - return this.millisecond() * 1000; - }); - addFormatToken(0, ['SSSSSSS', 7], 0, function () { - return this.millisecond() * 10000; - }); - addFormatToken(0, ['SSSSSSSS', 8], 0, function () { - return this.millisecond() * 100000; - }); - addFormatToken(0, ['SSSSSSSSS', 9], 0, function () { - return this.millisecond() * 1000000; - }); + function millisecond__milliseconds (token) { + addFormatToken(0, [token, 3], 0, 'millisecond'); + } + millisecond__milliseconds('SSS'); + millisecond__milliseconds('SSSS'); // ALIASES @@ -4015,19 +3980,11 @@ return /******/ (function(modules) { // webpackBootstrap addRegexToken('S', match1to3, match1); addRegexToken('SS', match1to3, match2); addRegexToken('SSS', match1to3, match3); - - var token; - for (token = 'SSSS'; token.length <= 9; token += 'S') { - addRegexToken(token, matchUnsigned); - } - - function parseMs(input, array) { + addRegexToken('SSSS', matchUnsigned); + addParseToken(['S', 'SS', 'SSS', 'SSSS'], function (input, array) { array[MILLISECOND] = toInt(('0.' + input) * 1000); - } + }); - for (token = 'S'; token.length <= 9; token += 'S') { - addParseToken(token, parseMs); - } // MOMENTS var getSetMillisecond = makeGetSet('Milliseconds', false); @@ -4074,7 +4031,6 @@ return /******/ (function(modules) { // webpackBootstrap momentPrototype__proto.startOf = startOf; momentPrototype__proto.subtract = add_subtract__subtract; momentPrototype__proto.toArray = toArray; - momentPrototype__proto.toObject = toObject; momentPrototype__proto.toDate = toDate; momentPrototype__proto.toISOString = moment_format__toISOString; momentPrototype__proto.toJSON = moment_format__toISOString; @@ -4174,23 +4130,19 @@ return /******/ (function(modules) { // webpackBootstrap LT : 'h:mm A', L : 'MM/DD/YYYY', LL : 'MMMM D, YYYY', - LLL : 'MMMM D, YYYY h:mm A', - LLLL : 'dddd, MMMM D, YYYY h:mm A' + LLL : 'MMMM D, YYYY LT', + LLLL : 'dddd, MMMM D, YYYY LT' }; function longDateFormat (key) { - var format = this._longDateFormat[key], - formatUpper = this._longDateFormat[key.toUpperCase()]; - - if (format || !formatUpper) { - return format; + var output = this._longDateFormat[key]; + if (!output && this._longDateFormat[key.toUpperCase()]) { + output = this._longDateFormat[key.toUpperCase()].replace(/MMMM|MM|DD|dddd/g, function (val) { + return val.slice(1); + }); + this._longDateFormat[key] = output; } - - this._longDateFormat[key] = formatUpper.replace(/MMMM|MM|DD|dddd/g, function (val) { - return val.slice(1); - }); - - return this._longDateFormat[key]; + return output; } var defaultInvalidDate = 'Invalid date'; @@ -4399,29 +4351,12 @@ return /******/ (function(modules) { // webpackBootstrap return duration_add_subtract__addSubtract(this, input, value, -1); } - function absCeil (number) { - if (number < 0) { - return Math.floor(number); - } else { - return Math.ceil(number); - } - } - function bubble () { var milliseconds = this._milliseconds; var days = this._days; var months = this._months; var data = this._data; - var seconds, minutes, hours, years, monthsFromDays; - - // if we have a mix of positive and negative values, bubble down first - // check: https://github.com/moment/moment/issues/2166 - if (!((milliseconds >= 0 && days >= 0 && months >= 0) || - (milliseconds <= 0 && days <= 0 && months <= 0))) { - milliseconds += absCeil(monthsToDays(months) + days) * 864e5; - days = 0; - months = 0; - } + var seconds, minutes, hours, years = 0; // The following code bubbles up values, see the tests for // examples of what that means. @@ -4438,13 +4373,17 @@ return /******/ (function(modules) { // webpackBootstrap days += absFloor(hours / 24); - // convert days to months - monthsFromDays = absFloor(daysToMonths(days)); - months += monthsFromDays; - days -= absCeil(monthsToDays(monthsFromDays)); + // Accurately convert days to years, assume start from year 0. + years = absFloor(daysToYears(days)); + days -= absFloor(yearsToDays(years)); + + // 30 days to a month + // TODO (iskren): Use anchor date (like 1st Jan) to compute this. + months += absFloor(days / 30); + days %= 30; // 12 months -> 1 year - years = absFloor(months / 12); + years += absFloor(months / 12); months %= 12; data.days = days; @@ -4454,15 +4393,15 @@ return /******/ (function(modules) { // webpackBootstrap return this; } - function daysToMonths (days) { + function daysToYears (days) { // 400 years have 146097 days (taking into account leap year rules) - // 400 years have 12 months === 4800 - return days * 4800 / 146097; + return days * 400 / 146097; } - function monthsToDays (months) { - // the reverse of daysToMonths - return months * 146097 / 4800; + function yearsToDays (years) { + // years * 365 + absFloor(years / 4) - + // absFloor(years / 100) + absFloor(years / 400); + return years * 146097 / 400; } function as (units) { @@ -4474,11 +4413,11 @@ return /******/ (function(modules) { // webpackBootstrap if (units === 'month' || units === 'year') { days = this._days + milliseconds / 864e5; - months = this._months + daysToMonths(days); + months = this._months + daysToYears(days) * 12; return units === 'month' ? months : months / 12; } else { // handle milliseconds separately because of floating point math errors (issue #1867) - days = this._days + Math.round(monthsToDays(this._months)); + days = this._days + Math.round(yearsToDays(this._months / 12)); switch (units) { case 'week' : return days / 7 + milliseconds / 6048e5; case 'day' : return days + milliseconds / 864e5; @@ -4528,7 +4467,7 @@ return /******/ (function(modules) { // webpackBootstrap }; } - var milliseconds = makeGetter('milliseconds'); + var duration_get__milliseconds = makeGetter('milliseconds'); var seconds = makeGetter('seconds'); var minutes = makeGetter('minutes'); var hours = makeGetter('hours'); @@ -4606,36 +4545,13 @@ return /******/ (function(modules) { // webpackBootstrap var iso_string__abs = Math.abs; function iso_string__toISOString() { - // for ISO strings we do not use the normal bubbling rules: - // * milliseconds bubble up until they become hours - // * days do not bubble at all - // * months bubble up until they become years - // This is because there is no context-free conversion between hours and days - // (think of clock changes) - // and also not between days and months (28-31 days per month) - var seconds = iso_string__abs(this._milliseconds) / 1000; - var days = iso_string__abs(this._days); - var months = iso_string__abs(this._months); - var minutes, hours, years; - - // 3600 seconds -> 60 minutes -> 1 hour - minutes = absFloor(seconds / 60); - hours = absFloor(minutes / 60); - seconds %= 60; - minutes %= 60; - - // 12 months -> 1 year - years = absFloor(months / 12); - months %= 12; - - // inspired by https://github.com/dordille/moment-isoduration/blob/master/moment.isoduration.js - var Y = years; - var M = months; - var D = days; - var h = hours; - var m = minutes; - var s = seconds; + var Y = iso_string__abs(this.years()); + var M = iso_string__abs(this.months()); + var D = iso_string__abs(this.days()); + var h = iso_string__abs(this.hours()); + var m = iso_string__abs(this.minutes()); + var s = iso_string__abs(this.seconds() + this.milliseconds() / 1000); var total = this.asSeconds(); if (!total) { @@ -4672,7 +4588,7 @@ return /******/ (function(modules) { // webpackBootstrap duration_prototype__proto.valueOf = duration_as__valueOf; duration_prototype__proto._bubble = bubble; duration_prototype__proto.get = duration_get__get; - duration_prototype__proto.milliseconds = milliseconds; + duration_prototype__proto.milliseconds = duration_get__milliseconds; duration_prototype__proto.seconds = seconds; duration_prototype__proto.minutes = minutes; duration_prototype__proto.hours = hours; @@ -4710,7 +4626,7 @@ return /******/ (function(modules) { // webpackBootstrap // Side effect imports - utils_hooks__hooks.version = '2.10.6'; + utils_hooks__hooks.version = '2.10.3'; setHookCallback(local__createLocal); @@ -5125,21 +5041,21 @@ return /******/ (function(modules) { // webpackBootstrap var point; if (groupTemplate.style == 'circle') { point = exports.getSVGElement('circle', JSONcontainer, svgContainer); - point.setAttributeNS(null, 'cx', x); - point.setAttributeNS(null, 'cy', y); - point.setAttributeNS(null, 'r', 0.5 * groupTemplate.size); + point.setAttributeNS(null, "cx", x); + point.setAttributeNS(null, "cy", y); + point.setAttributeNS(null, "r", 0.5 * groupTemplate.size); } else { point = exports.getSVGElement('rect', JSONcontainer, svgContainer); - point.setAttributeNS(null, 'x', x - 0.5 * groupTemplate.size); - point.setAttributeNS(null, 'y', y - 0.5 * groupTemplate.size); - point.setAttributeNS(null, 'width', groupTemplate.size); - point.setAttributeNS(null, 'height', groupTemplate.size); + point.setAttributeNS(null, "x", x - 0.5 * groupTemplate.size); + point.setAttributeNS(null, "y", y - 0.5 * groupTemplate.size); + point.setAttributeNS(null, "width", groupTemplate.size); + point.setAttributeNS(null, "height", groupTemplate.size); } if (groupTemplate.style !== undefined) { - point.setAttributeNS(null, 'style', groupTemplate.style); + point.setAttributeNS(null, "style", groupTemplate.style); } - point.setAttributeNS(null, 'class', groupTemplate.className + ' vis-point'); + point.setAttributeNS(null, "class", groupTemplate.className + " vis-point"); //handle label if (labelObj) { @@ -5156,10 +5072,10 @@ return /******/ (function(modules) { // webpackBootstrap } if (labelObj.className) { - label.setAttributeNS(null, 'class', labelObj.className + ' vis-label'); + label.setAttributeNS(null, "class", labelObj.className + " vis-label"); } - label.setAttributeNS(null, 'x', x); - label.setAttributeNS(null, 'y', y); + label.setAttributeNS(null, "x", x); + label.setAttributeNS(null, "y", y); } return point; @@ -5179,13 +5095,13 @@ return /******/ (function(modules) { // webpackBootstrap y -= height; } var rect = exports.getSVGElement('rect', JSONcontainer, svgContainer); - rect.setAttributeNS(null, 'x', x - 0.5 * width); - rect.setAttributeNS(null, 'y', y); - rect.setAttributeNS(null, 'width', width); - rect.setAttributeNS(null, 'height', height); - rect.setAttributeNS(null, 'class', className); + rect.setAttributeNS(null, "x", x - 0.5 * width); + rect.setAttributeNS(null, "y", y); + rect.setAttributeNS(null, "width", width); + rect.setAttributeNS(null, "height", height); + rect.setAttributeNS(null, "class", className); if (style) { - rect.setAttributeNS(null, 'style', style); + rect.setAttributeNS(null, "style", style); } } }; @@ -5815,8 +5731,8 @@ return /******/ (function(modules) { // webpackBootstrap // TODO: extend order by an Object {field:String, direction:String} // where direction can be 'asc' or 'desc' else { - throw new TypeError('Order must be a function or a string'); - } + throw new TypeError('Order must be a function or a string'); + } }; /** @@ -6592,7 +6508,9 @@ return /******/ (function(modules) { // webpackBootstrap if (this._ids[id]) { delete this._ids[id]; removed.push(id); - } else {} + } else { + // nothing interesting for me :-( + } } } @@ -6636,20 +6554,18 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = DataView; - // nothing interesting for me :-( - /***/ }, /* 11 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; - var Emitter = __webpack_require__(12); + var Emitter = __webpack_require__(13); var DataSet = __webpack_require__(8); var DataView = __webpack_require__(10); var util = __webpack_require__(1); - var Point3d = __webpack_require__(13); - var Point2d = __webpack_require__(14); + var Point3d = __webpack_require__(14); + var Point2d = __webpack_require__(12); var Camera = __webpack_require__(15); var Filter = __webpack_require__(16); var Slider = __webpack_require__(17); @@ -6881,9 +6797,11 @@ return /******/ (function(modules) { // webpackBootstrap if (backgroundColor.fill !== undefined) fill = backgroundColor.fill; if (backgroundColor.stroke !== undefined) stroke = backgroundColor.stroke; if (backgroundColor.strokeWidth !== undefined) strokeWidth = backgroundColor.strokeWidth; - } else if (backgroundColor === undefined) {} else { - throw 'Unsupported type of backgroundColor'; - } + } else if (backgroundColor === undefined) { + // use use defaults + } else { + throw 'Unsupported type of backgroundColor'; + } this.frame.style.backgroundColor = fill; this.frame.style.borderColor = stroke; @@ -7589,9 +7507,9 @@ return /******/ (function(modules) { // webpackBootstrap widthMin = dotSize / 2; // px widthMax = dotSize / 2 + dotSize * 2; // Todo: put this in one function } else { - widthMin = 20; // px - widthMax = 20; // px - } + widthMin = 20; // px + widthMax = 20; // px + } var height = Math.max(this.frame.clientHeight * 0.25, 100); var top = this.margin; @@ -8127,9 +8045,9 @@ return /******/ (function(modules) { // webpackBootstrap strokeStyle = this.axisColor; // TODO: should be customizable } } else { - fillStyle = 'gray'; - strokeStyle = this.axisColor; - } + fillStyle = 'gray'; + strokeStyle = this.axisColor; + } ctx.lineWidth = this._getStrokeWidth(point); ctx.fillStyle = fillStyle; @@ -8884,12 +8802,28 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = Graph3d; - // use use defaults - /***/ }, /* 12 */ /***/ function(module, exports) { + /** + * @prototype Point2d + * @param {Number} [x] + * @param {Number} [y] + */ + "use strict"; + + function Point2d(x, y) { + this.x = x !== undefined ? x : 0; + this.y = y !== undefined ? y : 0; + } + + module.exports = Point2d; + +/***/ }, +/* 13 */ +/***/ function(module, exports) { + /** * Expose `Emitter`. @@ -9057,7 +8991,7 @@ return /******/ (function(modules) { // webpackBootstrap /***/ }, -/* 13 */ +/* 14 */ /***/ function(module, exports) { /** @@ -9139,31 +9073,13 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = Point3d; -/***/ }, -/* 14 */ -/***/ function(module, exports) { - - /** - * @prototype Point2d - * @param {Number} [x] - * @param {Number} [y] - */ - "use strict"; - - function Point2d(x, y) { - this.x = x !== undefined ? x : 0; - this.y = y !== undefined ? y : 0; - } - - module.exports = Point2d; - /***/ }, /* 15 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; - var Point3d = __webpack_require__(13); + var Point3d = __webpack_require__(14); /** * @class Camera @@ -10007,7 +9923,7 @@ return /******/ (function(modules) { // webpackBootstrap 'use strict'; - var Emitter = __webpack_require__(12); + var Emitter = __webpack_require__(13); var Hammer = __webpack_require__(20); var moment = __webpack_require__(2); var util = __webpack_require__(1); @@ -10404,7 +10320,10 @@ return /******/ (function(modules) { // webpackBootstrap var getEnd = function getEnd(item) { var end = item.data.end != undefined ? item.data.end : item.data.start; return util.convert(end, 'Date').valueOf(); - }; + } + + // calculate the date of the left side and right side of the items given + ; interval = max - min; // ms @@ -10412,8 +10331,6 @@ return /******/ (function(modules) { // webpackBootstrap interval = 10; } factor = interval / _this.props.center.width; - - // calculate the date of the left side and right side of the items given util.forEach(_this.itemSet.items, (function (item) { item.show(); @@ -14074,7 +13991,9 @@ return /******/ (function(modules) { // webpackBootstrap /** * Destroy the component. Cleanup DOM and event listeners */ - Component.prototype.destroy = function () {}; + Component.prototype.destroy = function () { + // should be implemented by the component + }; /** * Test whether the component is resized since the last time _isResized() was @@ -14093,8 +14012,6 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = Component; - // should be implemented by the component - /***/ }, /* 27 */ /***/ function(module, exports) { @@ -14169,16 +14086,16 @@ return /******/ (function(modules) { // webpackBootstrap } startDate.dayOfYear(start.dayOfYear()); startDate.year(start.year()); - startDate.subtract(7, "days"); + startDate.subtract(7, 'days'); endDate.dayOfYear(start.dayOfYear()); endDate.year(start.year()); - endDate.subtract(7 - offset, "days"); + endDate.subtract(7 - offset, 'days'); - runUntil.add(1, "weeks"); + runUntil.add(1, 'weeks'); break; case "weekly": - var dayOffset = endDate.diff(startDate, "days"); + var dayOffset = endDate.diff(startDate, 'days'); var day = startDate.day(); // set the start date to the range.start @@ -14190,12 +14107,12 @@ return /******/ (function(modules) { // webpackBootstrap // force startDate.day(day); endDate.day(day); - endDate.add(dayOffset, "days"); + endDate.add(dayOffset, 'days'); - startDate.subtract(1, "weeks"); - endDate.subtract(1, "weeks"); + startDate.subtract(1, 'weeks'); + endDate.subtract(1, 'weeks'); - runUntil.add(1, "weeks"); + runUntil.add(1, 'weeks'); break; case "monthly": if (startDate.month() != endDate.month()) { @@ -14203,26 +14120,26 @@ return /******/ (function(modules) { // webpackBootstrap } startDate.month(start.month()); startDate.year(start.year()); - startDate.subtract(1, "months"); + startDate.subtract(1, 'months'); endDate.month(start.month()); endDate.year(start.year()); - endDate.subtract(1, "months"); - endDate.add(offset, "months"); + endDate.subtract(1, 'months'); + endDate.add(offset, 'months'); - runUntil.add(1, "months"); + runUntil.add(1, 'months'); break; case "yearly": if (startDate.year() != endDate.year()) { offset = 1; } startDate.year(start.year()); - startDate.subtract(1, "years"); + startDate.subtract(1, 'years'); endDate.year(start.year()); - endDate.subtract(1, "years"); - endDate.add(offset, "years"); + endDate.subtract(1, 'years'); + endDate.add(offset, 'years'); - runUntil.add(1, "years"); + runUntil.add(1, 'years'); break; default: console.log("Wrong repeat format, allowed are: daily, weekly, monthly, yearly. Given:", hiddenDates[i].repeat); @@ -14232,20 +14149,20 @@ return /******/ (function(modules) { // webpackBootstrap body.hiddenDates.push({ start: startDate.valueOf(), end: endDate.valueOf() }); switch (hiddenDates[i].repeat) { case "daily": - startDate.add(1, "days"); - endDate.add(1, "days"); + startDate.add(1, 'days'); + endDate.add(1, 'days'); break; case "weekly": - startDate.add(1, "weeks"); - endDate.add(1, "weeks"); + startDate.add(1, 'weeks'); + endDate.add(1, 'weeks'); break; case "monthly": - startDate.add(1, "months"); - endDate.add(1, "months"); + startDate.add(1, 'months'); + endDate.add(1, 'months'); break; case "yearly": - startDate.add(1, "y"); - endDate.add(1, "y"); + startDate.add(1, 'y'); + endDate.add(1, 'y'); break; default: console.log("Wrong repeat format, allowed are: daily, weekly, monthly, yearly. Given:", hiddenDates[i].repeat); @@ -14292,14 +14209,14 @@ return /******/ (function(modules) { // webpackBootstrap } // j start inside i else if (hiddenDates[j].start >= hiddenDates[i].start && hiddenDates[j].start <= hiddenDates[i].end) { - hiddenDates[i].end = hiddenDates[j].end; - hiddenDates[j].remove = true; - } - // j end inside i - else if (hiddenDates[j].end >= hiddenDates[i].start && hiddenDates[j].end <= hiddenDates[i].end) { - hiddenDates[i].start = hiddenDates[j].start; - hiddenDates[j].remove = true; - } + hiddenDates[i].end = hiddenDates[j].end; + hiddenDates[j].remove = true; + } + // j end inside i + else if (hiddenDates[j].end >= hiddenDates[i].start && hiddenDates[j].end <= hiddenDates[i].end) { + hiddenDates[i].start = hiddenDates[j].start; + hiddenDates[j].remove = true; + } } } } @@ -14565,7 +14482,7 @@ return /******/ (function(modules) { // webpackBootstrap 'use strict'; - var Emitter = __webpack_require__(12); + var Emitter = __webpack_require__(13); var Hammer = __webpack_require__(20); var hammerUtil = __webpack_require__(25); var util = __webpack_require__(1); @@ -15497,7 +15414,7 @@ return /******/ (function(modules) { // webpackBootstrap if (newScrollTop != oldScrollTop) { this._redraw(); // TODO: this causes two redraws when dragging, the other is triggered by rangechange already - this.emit('verticalDrag'); + this.emit("verticalDrag"); } }; @@ -15567,13 +15484,13 @@ return /******/ (function(modules) { // webpackBootstrap var util = __webpack_require__(1); var DataSet = __webpack_require__(8); var DataView = __webpack_require__(10); - var TimeStep = __webpack_require__(30); + var TimeStep = __webpack_require__(34); var Component = __webpack_require__(26); - var Group = __webpack_require__(31); + var Group = __webpack_require__(30); var BackgroundGroup = __webpack_require__(35); var BoxItem = __webpack_require__(36); var PointItem = __webpack_require__(37); - var RangeItem = __webpack_require__(33); + var RangeItem = __webpack_require__(32); var BackgroundItem = __webpack_require__(38); var UNGROUPED = '__ungrouped__'; // reserved group id for ungrouped items @@ -17082,25 +16999,25 @@ return /******/ (function(modules) { // webpackBootstrap } // if dragged group was move downwards everything above should have an offset else if (origOrder[curPos + orgOffset] == draggedId) { - orgOffset = 1; - continue; - } - // found a group (apart from dragged group) that has the wrong position -> switch with the - // group at the position where other one should be, fix index arrays and continue - else { - var slippedPosition = newOrder.indexOf(origOrder[curPos + orgOffset]); - var switchGroup = groupsData.get(newOrder[curPos + newOffset]); - var shouldBeGroup = groupsData.get(origOrder[curPos + orgOffset]); - this.options.groupOrderSwap(switchGroup, shouldBeGroup, groupsData); - groupsData.update(switchGroup); - groupsData.update(shouldBeGroup); - - var switchGroupId = newOrder[curPos + newOffset]; - newOrder[curPos + newOffset] = origOrder[curPos + orgOffset]; - newOrder[slippedPosition] = switchGroupId; - - curPos++; - } + orgOffset = 1; + continue; + } + // found a group (apart from dragged group) that has the wrong position -> switch with the + // group at the position where other one should be, fix index arrays and continue + else { + var slippedPosition = newOrder.indexOf(origOrder[curPos + orgOffset]); + var switchGroup = groupsData.get(newOrder[curPos + newOffset]); + var shouldBeGroup = groupsData.get(origOrder[curPos + orgOffset]); + this.options.groupOrderSwap(switchGroup, shouldBeGroup, groupsData); + groupsData.update(switchGroup); + groupsData.update(shouldBeGroup); + + var switchGroupId = newOrder[curPos + newOffset]; + newOrder[curPos + newOffset] = origOrder[curPos + orgOffset]; + newOrder[slippedPosition] = switchGroupId; + + curPos++; + } } } } @@ -17427,872 +17344,165 @@ return /******/ (function(modules) { // webpackBootstrap 'use strict'; - var moment = __webpack_require__(2); - var DateUtil = __webpack_require__(27); var util = __webpack_require__(1); + var stack = __webpack_require__(31); + var RangeItem = __webpack_require__(32); /** - * @constructor TimeStep - * The class TimeStep is an iterator for dates. You provide a start date and an - * end date. The class itself determines the best scale (step size) based on the - * provided start Date, end Date, and minimumStep. - * - * If minimumStep is provided, the step size is chosen as close as possible - * to the minimumStep but larger than minimumStep. If minimumStep is not - * provided, the scale is set to 1 DAY. - * The minimumStep should correspond with the onscreen size of about 6 characters - * - * Alternatively, you can set a scale by hand. - * After creation, you can initialize the class by executing first(). Then you - * can iterate from the start date to the end date via next(). You can check if - * the end date is reached with the function hasNext(). After each step, you can - * retrieve the current date via getCurrent(). - * The TimeStep has scales ranging from milliseconds, seconds, minutes, hours, - * days, to years. - * - * Version: 1.2 - * - * @param {Date} [start] The start date, for example new Date(2010, 9, 21) - * or new Date(2010, 9, 21, 23, 45, 00) - * @param {Date} [end] The end date - * @param {Number} [minimumStep] Optional. Minimum step size in milliseconds + * @constructor Group + * @param {Number | String} groupId + * @param {Object} data + * @param {ItemSet} itemSet */ - function TimeStep(start, end, minimumStep, hiddenDates) { - this.moment = moment; - - // variables - this.current = this.moment(); - this._start = this.moment(); - this._end = this.moment(); + function Group(groupId, data, itemSet) { + this.groupId = groupId; + this.subgroups = {}; + this.subgroupIndex = 0; + this.subgroupOrderer = data && data.subgroupOrder; + this.itemSet = itemSet; - this.autoScale = true; - this.scale = 'day'; - this.step = 1; + this.dom = {}; + this.props = { + label: { + width: 0, + height: 0 + } + }; + this.className = null; - // initialize the range - this.setRange(start, end, minimumStep); + this.items = {}; // items filtered by groupId of this group + this.visibleItems = []; // items currently visible in window + this.orderedItems = { + byStart: [], + byEnd: [] + }; + this.checkRangedItems = false; // needed to refresh the ranged items if the window is programatically changed with NO overlap. + var me = this; + this.itemSet.body.emitter.on("checkRangedItems", function () { + me.checkRangedItems = true; + }); - // hidden Dates options - this.switchedDay = false; - this.switchedMonth = false; - this.switchedYear = false; - this.hiddenDates = hiddenDates; - if (hiddenDates === undefined) { - this.hiddenDates = []; - } + this._create(); - this.format = TimeStep.FORMAT; // default formatting + this.setData(data); } - // Time formatting - TimeStep.FORMAT = { - minorLabels: { - millisecond: 'SSS', - second: 's', - minute: 'HH:mm', - hour: 'HH:mm', - weekday: 'ddd D', - day: 'D', - month: 'MMM', - year: 'YYYY' - }, - majorLabels: { - millisecond: 'HH:mm:ss', - second: 'D MMMM HH:mm', - minute: 'ddd D MMMM', - hour: 'ddd D MMMM', - weekday: 'MMMM YYYY', - day: 'MMMM YYYY', - month: 'YYYY', - year: '' - } - }; - /** - * Set custom constructor function for moment. Can be used to set dates - * to UTC or to set a utcOffset. - * @param {function} moment + * Create DOM elements for the group + * @private */ - TimeStep.prototype.setMoment = function (moment) { - this.moment = moment; + Group.prototype._create = function () { + var label = document.createElement('div'); + if (this.itemSet.options.groupEditable.order) { + label.className = 'vis-label draggable'; + } else { + label.className = 'vis-label'; + } + this.dom.label = label; - // update the date properties, can have a new utcOffset - this.current = this.moment(this.current); - this._start = this.moment(this._start); - this._end = this.moment(this._end); - }; + var inner = document.createElement('div'); + inner.className = 'vis-inner'; + label.appendChild(inner); + this.dom.inner = inner; - /** - * Set custom formatting for the minor an major labels of the TimeStep. - * Both `minorLabels` and `majorLabels` are an Object with properties: - * 'millisecond', 'second', 'minute', 'hour', 'weekday', 'day', 'month', 'year'. - * @param {{minorLabels: Object, majorLabels: Object}} format - */ - TimeStep.prototype.setFormat = function (format) { - var defaultFormat = util.deepExtend({}, TimeStep.FORMAT); - this.format = util.deepExtend(defaultFormat, format); + var foreground = document.createElement('div'); + foreground.className = 'vis-group'; + foreground['timeline-group'] = this; + this.dom.foreground = foreground; + + this.dom.background = document.createElement('div'); + this.dom.background.className = 'vis-group'; + + this.dom.axis = document.createElement('div'); + this.dom.axis.className = 'vis-group'; + + // create a hidden marker to detect when the Timelines container is attached + // to the DOM, or the style of a parent of the Timeline is changed from + // display:none is changed to visible. + this.dom.marker = document.createElement('div'); + this.dom.marker.style.visibility = 'hidden'; + this.dom.marker.innerHTML = '?'; + this.dom.background.appendChild(this.dom.marker); }; /** - * Set a new range - * If minimumStep is provided, the step size is chosen as close as possible - * to the minimumStep but larger than minimumStep. If minimumStep is not - * provided, the scale is set to 1 DAY. - * The minimumStep should correspond with the onscreen size of about 6 characters - * @param {Date} [start] The start date and time. - * @param {Date} [end] The end date and time. - * @param {int} [minimumStep] Optional. Minimum step size in milliseconds + * Set the group data for this group + * @param {Object} data Group data, can contain properties content and className */ - TimeStep.prototype.setRange = function (start, end, minimumStep) { - if (!(start instanceof Date) || !(end instanceof Date)) { - throw 'No legal start or end date in method setRange'; + Group.prototype.setData = function (data) { + // update contents + var content; + if (this.itemSet.options && this.itemSet.options.groupTemplate) { + content = this.itemSet.options.groupTemplate(data); + } else { + content = data && data.content; } - this._start = start != undefined ? this.moment(start.valueOf()) : new Date(); - this._end = end != undefined ? this.moment(end.valueOf()) : new Date(); - - if (this.autoScale) { - this.setMinimumStep(minimumStep); + if (content instanceof Element) { + this.dom.inner.appendChild(content); + while (this.dom.inner.firstChild) { + this.dom.inner.removeChild(this.dom.inner.firstChild); + } + this.dom.inner.appendChild(content); + } else if (content !== undefined && content !== null) { + this.dom.inner.innerHTML = content; + } else { + this.dom.inner.innerHTML = this.groupId || ''; // groupId can be null } - }; - /** - * Set the range iterator to the start date. - */ - TimeStep.prototype.start = function () { - this.current = this._start.clone(); - this.roundToMinor(); - }; + // update title + this.dom.label.title = data && data.title || ''; - /** - * Round the current date to the first minor date value - * This must be executed once when the current date is set to start Date - */ - TimeStep.prototype.roundToMinor = function () { - // round to floor - // IMPORTANT: we have no breaks in this switch! (this is no bug) - // noinspection FallThroughInSwitchStatementJS - switch (this.scale) { - case 'year': - this.current.year(this.step * Math.floor(this.current.year() / this.step)); - this.current.month(0); - case 'month': - this.current.date(1); - case 'day': // intentional fall through - case 'weekday': - this.current.hours(0); - case 'hour': - this.current.minutes(0); - case 'minute': - this.current.seconds(0); - case 'second': - this.current.milliseconds(0); - //case 'millisecond': // nothing to do for milliseconds + if (!this.dom.inner.firstChild) { + util.addClassName(this.dom.inner, 'vis-hidden'); + } else { + util.removeClassName(this.dom.inner, 'vis-hidden'); } - if (this.step != 1) { - // round down to the first minor value that is a multiple of the current step size - switch (this.scale) { - case 'millisecond': - this.current.subtract(this.current.milliseconds() % this.step, 'milliseconds');break; - case 'second': - this.current.subtract(this.current.seconds() % this.step, 'seconds');break; - case 'minute': - this.current.subtract(this.current.minutes() % this.step, 'minutes');break; - case 'hour': - this.current.subtract(this.current.hours() % this.step, 'hours');break; - case 'weekday': // intentional fall through - case 'day': - this.current.subtract((this.current.date() - 1) % this.step, 'day');break; - case 'month': - this.current.subtract(this.current.month() % this.step, 'month');break; - case 'year': - this.current.subtract(this.current.year() % this.step, 'year');break; - default: - break; + // update className + var className = data && data.className || null; + if (className != this.className) { + if (this.className) { + util.removeClassName(this.dom.label, this.className); + util.removeClassName(this.dom.foreground, this.className); + util.removeClassName(this.dom.background, this.className); + util.removeClassName(this.dom.axis, this.className); } + util.addClassName(this.dom.label, className); + util.addClassName(this.dom.foreground, className); + util.addClassName(this.dom.background, className); + util.addClassName(this.dom.axis, className); + this.className = className; + } + + // update style + if (this.style) { + util.removeCssText(this.dom.label, this.style); + this.style = null; + } + if (data && data.style) { + util.addCssText(this.dom.label, data.style); + this.style = data.style; } }; /** - * Check if the there is a next step - * @return {boolean} true if the current date has not passed the end date + * Get the width of the group label + * @return {number} width */ - TimeStep.prototype.hasNext = function () { - return this.current.valueOf() <= this._end.valueOf(); + Group.prototype.getLabelWidth = function () { + return this.props.label.width; }; /** - * Do the next step + * Repaint this group + * @param {{start: number, end: number}} range + * @param {{item: {horizontal: number, vertical: number}, axis: number}} margin + * @param {boolean} [restack=false] Force restacking of all items + * @return {boolean} Returns true if the group is resized */ - TimeStep.prototype.next = function () { - var prev = this.current.valueOf(); - - // Two cases, needed to prevent issues with switching daylight savings - // (end of March and end of October) - if (this.current.month() < 6) { - switch (this.scale) { - case 'millisecond': - this.current.add(this.step, 'millisecond');break; - case 'second': - this.current.add(this.step, 'second');break; - case 'minute': - this.current.add(this.step, 'minute');break; - case 'hour': - this.current.add(this.step, 'hour'); - // in case of skipping an hour for daylight savings, adjust the hour again (else you get: 0h 5h 9h ... instead of 0h 4h 8h ...) - // TODO: is this still needed now we use the function of moment.js? - this.current.subtract(this.current.hours() % this.step, 'hour'); - break; - case 'weekday': // intentional fall through - case 'day': - this.current.add(this.step, 'day');break; - case 'month': - this.current.add(this.step, 'month');break; - case 'year': - this.current.add(this.step, 'year');break; - default: - break; - } - } else { - switch (this.scale) { - case 'millisecond': - this.current.add(this.step, 'millisecond');break; - case 'second': - this.current.add(this.step, 'second');break; - case 'minute': - this.current.add(this.step, 'minute');break; - case 'hour': - this.current.add(this.step, 'hour');break; - case 'weekday': // intentional fall through - case 'day': - this.current.add(this.step, 'day');break; - case 'month': - this.current.add(this.step, 'month');break; - case 'year': - this.current.add(this.step, 'year');break; - default: - break; - } - } - - if (this.step != 1) { - // round down to the correct major value - switch (this.scale) { - case 'millisecond': - if (this.current.milliseconds() < this.step) this.current.milliseconds(0);break; - case 'second': - if (this.current.seconds() < this.step) this.current.seconds(0);break; - case 'minute': - if (this.current.minutes() < this.step) this.current.minutes(0);break; - case 'hour': - if (this.current.hours() < this.step) this.current.hours(0);break; - case 'weekday': // intentional fall through - case 'day': - if (this.current.date() < this.step + 1) this.current.date(1);break; - case 'month': - if (this.current.month() < this.step) this.current.month(0);break; - case 'year': - break; // nothing to do for year - default: - break; - } - } - - // safety mechanism: if current time is still unchanged, move to the end - if (this.current.valueOf() == prev) { - this.current = this._end.clone(); - } - - DateUtil.stepOverHiddenDates(this.moment, this, prev); - }; - - /** - * Get the current datetime - * @return {Moment} current The current date - */ - TimeStep.prototype.getCurrent = function () { - return this.current; - }; - - /** - * Set a custom scale. Autoscaling will be disabled. - * For example setScale('minute', 5) will result - * in minor steps of 5 minutes, and major steps of an hour. - * - * @param {{scale: string, step: number}} params - * An object containing two properties: - * - A string 'scale'. Choose from 'millisecond', 'second', - * 'minute', 'hour', 'weekday', 'day', 'month', 'year'. - * - A number 'step'. A step size, by default 1. - * Choose for example 1, 2, 5, or 10. - */ - TimeStep.prototype.setScale = function (params) { - if (params && typeof params.scale == 'string') { - this.scale = params.scale; - this.step = params.step > 0 ? params.step : 1; - this.autoScale = false; - } - }; - - /** - * Enable or disable autoscaling - * @param {boolean} enable If true, autoascaling is set true - */ - TimeStep.prototype.setAutoScale = function (enable) { - this.autoScale = enable; - }; - - /** - * Automatically determine the scale that bests fits the provided minimum step - * @param {Number} [minimumStep] The minimum step size in milliseconds - */ - TimeStep.prototype.setMinimumStep = function (minimumStep) { - if (minimumStep == undefined) { - return; - } - - //var b = asc + ds; - - var stepYear = 1000 * 60 * 60 * 24 * 30 * 12; - var stepMonth = 1000 * 60 * 60 * 24 * 30; - var stepDay = 1000 * 60 * 60 * 24; - var stepHour = 1000 * 60 * 60; - var stepMinute = 1000 * 60; - var stepSecond = 1000; - var stepMillisecond = 1; - - // find the smallest step that is larger than the provided minimumStep - if (stepYear * 1000 > minimumStep) { - this.scale = 'year';this.step = 1000; - } - if (stepYear * 500 > minimumStep) { - this.scale = 'year';this.step = 500; - } - if (stepYear * 100 > minimumStep) { - this.scale = 'year';this.step = 100; - } - if (stepYear * 50 > minimumStep) { - this.scale = 'year';this.step = 50; - } - if (stepYear * 10 > minimumStep) { - this.scale = 'year';this.step = 10; - } - if (stepYear * 5 > minimumStep) { - this.scale = 'year';this.step = 5; - } - if (stepYear > minimumStep) { - this.scale = 'year';this.step = 1; - } - if (stepMonth * 3 > minimumStep) { - this.scale = 'month';this.step = 3; - } - if (stepMonth > minimumStep) { - this.scale = 'month';this.step = 1; - } - if (stepDay * 5 > minimumStep) { - this.scale = 'day';this.step = 5; - } - if (stepDay * 2 > minimumStep) { - this.scale = 'day';this.step = 2; - } - if (stepDay > minimumStep) { - this.scale = 'day';this.step = 1; - } - if (stepDay / 2 > minimumStep) { - this.scale = 'weekday';this.step = 1; - } - if (stepHour * 4 > minimumStep) { - this.scale = 'hour';this.step = 4; - } - if (stepHour > minimumStep) { - this.scale = 'hour';this.step = 1; - } - if (stepMinute * 15 > minimumStep) { - this.scale = 'minute';this.step = 15; - } - if (stepMinute * 10 > minimumStep) { - this.scale = 'minute';this.step = 10; - } - if (stepMinute * 5 > minimumStep) { - this.scale = 'minute';this.step = 5; - } - if (stepMinute > minimumStep) { - this.scale = 'minute';this.step = 1; - } - if (stepSecond * 15 > minimumStep) { - this.scale = 'second';this.step = 15; - } - if (stepSecond * 10 > minimumStep) { - this.scale = 'second';this.step = 10; - } - if (stepSecond * 5 > minimumStep) { - this.scale = 'second';this.step = 5; - } - if (stepSecond > minimumStep) { - this.scale = 'second';this.step = 1; - } - if (stepMillisecond * 200 > minimumStep) { - this.scale = 'millisecond';this.step = 200; - } - if (stepMillisecond * 100 > minimumStep) { - this.scale = 'millisecond';this.step = 100; - } - if (stepMillisecond * 50 > minimumStep) { - this.scale = 'millisecond';this.step = 50; - } - if (stepMillisecond * 10 > minimumStep) { - this.scale = 'millisecond';this.step = 10; - } - if (stepMillisecond * 5 > minimumStep) { - this.scale = 'millisecond';this.step = 5; - } - if (stepMillisecond > minimumStep) { - this.scale = 'millisecond';this.step = 1; - } - }; - - /** - * Snap a date to a rounded value. - * The snap intervals are dependent on the current scale and step. - * Static function - * @param {Date} date the date to be snapped. - * @param {string} scale Current scale, can be 'millisecond', 'second', - * 'minute', 'hour', 'weekday, 'day', 'month', 'year'. - * @param {number} step Current step (1, 2, 4, 5, ... - * @return {Date} snappedDate - */ - TimeStep.snap = function (date, scale, step) { - var clone = moment(date); - - if (scale == 'year') { - var year = clone.year() + Math.round(clone.month() / 12); - clone.year(Math.round(year / step) * step); - clone.month(0); - clone.date(0); - clone.hours(0); - clone.minutes(0); - clone.seconds(0); - clone.milliseconds(0); - } else if (scale == 'month') { - if (clone.date() > 15) { - clone.date(1); - clone.add(1, 'month'); - // important: first set Date to 1, after that change the month. - } else { - clone.date(1); - } - - clone.hours(0); - clone.minutes(0); - clone.seconds(0); - clone.milliseconds(0); - } else if (scale == 'day') { - //noinspection FallthroughInSwitchStatementJS - switch (step) { - case 5: - case 2: - clone.hours(Math.round(clone.hours() / 24) * 24);break; - default: - clone.hours(Math.round(clone.hours() / 12) * 12);break; - } - clone.minutes(0); - clone.seconds(0); - clone.milliseconds(0); - } else if (scale == 'weekday') { - //noinspection FallthroughInSwitchStatementJS - switch (step) { - case 5: - case 2: - clone.hours(Math.round(clone.hours() / 12) * 12);break; - default: - clone.hours(Math.round(clone.hours() / 6) * 6);break; - } - clone.minutes(0); - clone.seconds(0); - clone.milliseconds(0); - } else if (scale == 'hour') { - switch (step) { - case 4: - clone.minutes(Math.round(clone.minutes() / 60) * 60);break; - default: - clone.minutes(Math.round(clone.minutes() / 30) * 30);break; - } - clone.seconds(0); - clone.milliseconds(0); - } else if (scale == 'minute') { - //noinspection FallthroughInSwitchStatementJS - switch (step) { - case 15: - case 10: - clone.minutes(Math.round(clone.minutes() / 5) * 5); - clone.seconds(0); - break; - case 5: - clone.seconds(Math.round(clone.seconds() / 60) * 60);break; - default: - clone.seconds(Math.round(clone.seconds() / 30) * 30);break; - } - clone.milliseconds(0); - } else if (scale == 'second') { - //noinspection FallthroughInSwitchStatementJS - switch (step) { - case 15: - case 10: - clone.seconds(Math.round(clone.seconds() / 5) * 5); - clone.milliseconds(0); - break; - case 5: - clone.milliseconds(Math.round(clone.milliseconds() / 1000) * 1000);break; - default: - clone.milliseconds(Math.round(clone.milliseconds() / 500) * 500);break; - } - } else if (scale == 'millisecond') { - var _step = step > 5 ? step / 2 : 1; - clone.milliseconds(Math.round(clone.milliseconds() / _step) * _step); - } - - return clone; - }; - - /** - * Check if the current value is a major value (for example when the step - * is DAY, a major value is each first day of the MONTH) - * @return {boolean} true if current date is major, else false. - */ - TimeStep.prototype.isMajor = function () { - if (this.switchedYear == true) { - this.switchedYear = false; - switch (this.scale) { - case 'year': - case 'month': - case 'weekday': - case 'day': - case 'hour': - case 'minute': - case 'second': - case 'millisecond': - return true; - default: - return false; - } - } else if (this.switchedMonth == true) { - this.switchedMonth = false; - switch (this.scale) { - case 'weekday': - case 'day': - case 'hour': - case 'minute': - case 'second': - case 'millisecond': - return true; - default: - return false; - } - } else if (this.switchedDay == true) { - this.switchedDay = false; - switch (this.scale) { - case 'millisecond': - case 'second': - case 'minute': - case 'hour': - return true; - default: - return false; - } - } - - var date = this.moment(this.current); - switch (this.scale) { - case 'millisecond': - return date.milliseconds() == 0; - case 'second': - return date.seconds() == 0; - case 'minute': - return date.hours() == 0 && date.minutes() == 0; - case 'hour': - return date.hours() == 0; - case 'weekday': // intentional fall through - case 'day': - return date.date() == 1; - case 'month': - return date.month() == 0; - case 'year': - return false; - default: - return false; - } - }; - - /** - * Returns formatted text for the minor axislabel, depending on the current - * date and the scale. For example when scale is MINUTE, the current time is - * formatted as "hh:mm". - * @param {Date} [date] custom date. if not provided, current date is taken - */ - TimeStep.prototype.getLabelMinor = function (date) { - if (date == undefined) { - date = this.current; - } - - var format = this.format.minorLabels[this.scale]; - return format && format.length > 0 ? this.moment(date).format(format) : ''; - }; - - /** - * Returns formatted text for the major axis label, depending on the current - * date and the scale. For example when scale is MINUTE, the major scale is - * hours, and the hour will be formatted as "hh". - * @param {Date} [date] custom date. if not provided, current date is taken - */ - TimeStep.prototype.getLabelMajor = function (date) { - if (date == undefined) { - date = this.current; - } - - var format = this.format.majorLabels[this.scale]; - return format && format.length > 0 ? this.moment(date).format(format) : ''; - }; - - TimeStep.prototype.getClassName = function () { - var _moment = this.moment; - var m = this.moment(this.current); - var current = m.locale ? m.locale('en') : m.lang('en'); // old versions of moment have .lang() function - var step = this.step; - - function even(value) { - return value / step % 2 == 0 ? ' vis-even' : ' vis-odd'; - } - - function today(date) { - if (date.isSame(new Date(), 'day')) { - return ' vis-today'; - } - if (date.isSame(_moment().add(1, 'day'), 'day')) { - return ' vis-tomorrow'; - } - if (date.isSame(_moment().add(-1, 'day'), 'day')) { - return ' vis-yesterday'; - } - return ''; - } - - function currentWeek(date) { - return date.isSame(new Date(), 'week') ? ' vis-current-week' : ''; - } - - function currentMonth(date) { - return date.isSame(new Date(), 'month') ? ' vis-current-month' : ''; - } - - function currentYear(date) { - return date.isSame(new Date(), 'year') ? ' vis-current-year' : ''; - } - - switch (this.scale) { - case 'millisecond': - return even(current.milliseconds()).trim(); - - case 'second': - return even(current.seconds()).trim(); - - case 'minute': - return even(current.minutes()).trim(); - - case 'hour': - var hours = current.hours(); - if (this.step == 4) { - hours = hours + '-h' + (hours + 4); - } - return 'vis-h' + hours + today(current) + even(current.hours()); - - case 'weekday': - return 'vis-' + current.format('dddd').toLowerCase() + today(current) + currentWeek(current) + even(current.date()); - - case 'day': - var day = current.date(); - var month = current.format('MMMM').toLowerCase(); - return 'vis-day' + day + ' vis-' + month + currentMonth(current) + even(day - 1); - - case 'month': - return 'vis-' + current.format('MMMM').toLowerCase() + currentMonth(current) + even(current.month()); - - case 'year': - var year = current.year(); - return 'vis-year' + year + currentYear(current) + even(year); - - default: - return ''; - } - }; - - module.exports = TimeStep; - -/***/ }, -/* 31 */ -/***/ function(module, exports, __webpack_require__) { - - 'use strict'; - - var util = __webpack_require__(1); - var stack = __webpack_require__(32); - var RangeItem = __webpack_require__(33); - - /** - * @constructor Group - * @param {Number | String} groupId - * @param {Object} data - * @param {ItemSet} itemSet - */ - function Group(groupId, data, itemSet) { - this.groupId = groupId; - this.subgroups = {}; - this.subgroupIndex = 0; - this.subgroupOrderer = data && data.subgroupOrder; - this.itemSet = itemSet; - - this.dom = {}; - this.props = { - label: { - width: 0, - height: 0 - } - }; - this.className = null; - - this.items = {}; // items filtered by groupId of this group - this.visibleItems = []; // items currently visible in window - this.orderedItems = { - byStart: [], - byEnd: [] - }; - this.checkRangedItems = false; // needed to refresh the ranged items if the window is programatically changed with NO overlap. - var me = this; - this.itemSet.body.emitter.on('checkRangedItems', function () { - me.checkRangedItems = true; - }); - - this._create(); - - this.setData(data); - } - - /** - * Create DOM elements for the group - * @private - */ - Group.prototype._create = function () { - var label = document.createElement('div'); - if (this.itemSet.options.groupEditable.order) { - label.className = 'vis-label draggable'; - } else { - label.className = 'vis-label'; - } - this.dom.label = label; - - var inner = document.createElement('div'); - inner.className = 'vis-inner'; - label.appendChild(inner); - this.dom.inner = inner; - - var foreground = document.createElement('div'); - foreground.className = 'vis-group'; - foreground['timeline-group'] = this; - this.dom.foreground = foreground; - - this.dom.background = document.createElement('div'); - this.dom.background.className = 'vis-group'; - - this.dom.axis = document.createElement('div'); - this.dom.axis.className = 'vis-group'; - - // create a hidden marker to detect when the Timelines container is attached - // to the DOM, or the style of a parent of the Timeline is changed from - // display:none is changed to visible. - this.dom.marker = document.createElement('div'); - this.dom.marker.style.visibility = 'hidden'; - this.dom.marker.innerHTML = '?'; - this.dom.background.appendChild(this.dom.marker); - }; - - /** - * Set the group data for this group - * @param {Object} data Group data, can contain properties content and className - */ - Group.prototype.setData = function (data) { - // update contents - var content; - if (this.itemSet.options && this.itemSet.options.groupTemplate) { - content = this.itemSet.options.groupTemplate(data); - } else { - content = data && data.content; - } - - if (content instanceof Element) { - this.dom.inner.appendChild(content); - while (this.dom.inner.firstChild) { - this.dom.inner.removeChild(this.dom.inner.firstChild); - } - this.dom.inner.appendChild(content); - } else if (content !== undefined && content !== null) { - this.dom.inner.innerHTML = content; - } else { - this.dom.inner.innerHTML = this.groupId || ''; // groupId can be null - } - - // update title - this.dom.label.title = data && data.title || ''; - - if (!this.dom.inner.firstChild) { - util.addClassName(this.dom.inner, 'vis-hidden'); - } else { - util.removeClassName(this.dom.inner, 'vis-hidden'); - } - - // update className - var className = data && data.className || null; - if (className != this.className) { - if (this.className) { - util.removeClassName(this.dom.label, this.className); - util.removeClassName(this.dom.foreground, this.className); - util.removeClassName(this.dom.background, this.className); - util.removeClassName(this.dom.axis, this.className); - } - util.addClassName(this.dom.label, className); - util.addClassName(this.dom.foreground, className); - util.addClassName(this.dom.background, className); - util.addClassName(this.dom.axis, className); - this.className = className; - } - - // update style - if (this.style) { - util.removeCssText(this.dom.label, this.style); - this.style = null; - } - if (data && data.style) { - util.addCssText(this.dom.label, data.style); - this.style = data.style; - } - }; - - /** - * Get the width of the group label - * @return {number} width - */ - Group.prototype.getLabelWidth = function () { - return this.props.label.width; - }; - - /** - * Repaint this group - * @param {{start: number, end: number}} range - * @param {{item: {horizontal: number, vertical: number}, axis: number}} margin - * @param {boolean} [restack=false] Force restacking of all items - * @return {boolean} Returns true if the group is resized - */ - Group.prototype.redraw = function (range, margin, restack) { - var resized = false; + Group.prototype.redraw = function (range, margin, restack) { + var resized = false; // force recalculation of the height of the items when the marker height changed // (due to the Timeline being attached to the DOM or changed from display:none to visible) @@ -18716,749 +17926,1456 @@ return /******/ (function(modules) { // webpackBootstrap }; /** - * this function is very similar to the _checkIfInvisible() but it does not - * return booleans, hides the item if it should not be seen and always adds to - * the visibleItems. - * this one is for brute forcing and hiding. - * - * @param {Item} item - * @param {Array} visibleItems - * @param {{start:number, end:number}} range - * @private + * this function is very similar to the _checkIfInvisible() but it does not + * return booleans, hides the item if it should not be seen and always adds to + * the visibleItems. + * this one is for brute forcing and hiding. + * + * @param {Item} item + * @param {Array} visibleItems + * @param {{start:number, end:number}} range + * @private + */ + Group.prototype._checkIfVisibleWithReference = function (item, visibleItems, visibleItemsLookup, range) { + if (item.isVisible(range)) { + if (visibleItemsLookup[item.id] === undefined) { + visibleItemsLookup[item.id] = true; + visibleItems.push(item); + } + } else { + if (item.displayed) item.hide(); + } + }; + + module.exports = Group; + +/***/ }, +/* 31 */ +/***/ function(module, exports) { + + // Utility functions for ordering and stacking of items + 'use strict'; + + var EPSILON = 0.001; // used when checking collisions, to prevent round-off errors + + /** + * Order items by their start data + * @param {Item[]} items + */ + exports.orderByStart = function (items) { + items.sort(function (a, b) { + return a.data.start - b.data.start; + }); + }; + + /** + * Order items by their end date. If they have no end date, their start date + * is used. + * @param {Item[]} items + */ + exports.orderByEnd = function (items) { + items.sort(function (a, b) { + var aTime = 'end' in a.data ? a.data.end : a.data.start, + bTime = 'end' in b.data ? b.data.end : b.data.start; + + return aTime - bTime; + }); + }; + + /** + * Adjust vertical positions of the items such that they don't overlap each + * other. + * @param {Item[]} items + * All visible items + * @param {{item: {horizontal: number, vertical: number}, axis: number}} margin + * Margins between items and between items and the axis. + * @param {boolean} [force=false] + * If true, all items will be repositioned. If false (default), only + * items having a top===null will be re-stacked + */ + exports.stack = function (items, margin, force) { + var i, iMax; + + if (force) { + // reset top position of all items + for (i = 0, iMax = items.length; i < iMax; i++) { + items[i].top = null; + } + } + + // calculate new, non-overlapping positions + for (i = 0, iMax = items.length; i < iMax; i++) { + var item = items[i]; + if (item.stack && item.top === null) { + // initialize top position + item.top = margin.axis; + + do { + // TODO: optimize checking for overlap. when there is a gap without items, + // you only need to check for items from the next item on, not from zero + var collidingItem = null; + for (var j = 0, jj = items.length; j < jj; j++) { + var other = items[j]; + if (other.top !== null && other !== item && other.stack && exports.collision(item, other, margin.item)) { + collidingItem = other; + break; + } + } + + if (collidingItem != null) { + // There is a collision. Reposition the items above the colliding element + item.top = collidingItem.top + collidingItem.height + margin.item.vertical; + } + } while (collidingItem); + } + } + }; + + /** + * Adjust vertical positions of the items without stacking them + * @param {Item[]} items + * All visible items + * @param {{item: {horizontal: number, vertical: number}, axis: number}} margin + * Margins between items and between items and the axis. + */ + exports.nostack = function (items, margin, subgroups) { + var i, iMax, newTop; + + // reset top position of all items + for (i = 0, iMax = items.length; i < iMax; i++) { + if (items[i].data.subgroup !== undefined) { + newTop = margin.axis; + for (var subgroup in subgroups) { + if (subgroups.hasOwnProperty(subgroup)) { + if (subgroups[subgroup].visible == true && subgroups[subgroup].index < subgroups[items[i].data.subgroup].index) { + newTop += subgroups[subgroup].height + margin.item.vertical; + } + } + } + items[i].top = newTop; + } else { + items[i].top = margin.axis; + } + } + }; + + /** + * Test if the two provided items collide + * The items must have parameters left, width, top, and height. + * @param {Item} a The first item + * @param {Item} b The second item + * @param {{horizontal: number, vertical: number}} margin + * An object containing a horizontal and vertical + * minimum required margin. + * @return {boolean} true if a and b collide, else false + */ + exports.collision = function (a, b, margin) { + return a.left - margin.horizontal + EPSILON < b.left + b.width && a.left + a.width + margin.horizontal - EPSILON > b.left && a.top - margin.vertical + EPSILON < b.top + b.height && a.top + a.height + margin.vertical - EPSILON > b.top; + }; + +/***/ }, +/* 32 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + var Hammer = __webpack_require__(20); + var Item = __webpack_require__(33); + + /** + * @constructor RangeItem + * @extends Item + * @param {Object} data Object containing parameters start, end + * content, className. + * @param {{toScreen: function, toTime: function}} conversion + * Conversion functions from time to screen and vice versa + * @param {Object} [options] Configuration options + * // TODO: describe options + */ + function RangeItem(data, conversion, options) { + this.props = { + content: { + width: 0 + } + }; + this.overflow = false; // if contents can overflow (css styling), this flag is set to true + + // validate data + if (data) { + if (data.start == undefined) { + throw new Error('Property "start" missing in item ' + data.id); + } + if (data.end == undefined) { + throw new Error('Property "end" missing in item ' + data.id); + } + } + + Item.call(this, data, conversion, options); + } + + RangeItem.prototype = new Item(null, null, null); + + RangeItem.prototype.baseClassName = 'vis-item vis-range'; + + /** + * Check whether this item is visible inside given range + * @returns {{start: Number, end: Number}} range with a timestamp for start and end + * @returns {boolean} True if visible + */ + RangeItem.prototype.isVisible = function (range) { + // determine visibility + return this.data.start < range.end && this.data.end > range.start; + }; + + /** + * Repaint the item + */ + RangeItem.prototype.redraw = function () { + var dom = this.dom; + if (!dom) { + // create DOM + this.dom = {}; + dom = this.dom; + + // background box + dom.box = document.createElement('div'); + // className is updated in redraw() + + // frame box (to prevent the item contents from overflowing + dom.frame = document.createElement('div'); + dom.frame.className = 'vis-item-overflow'; + dom.box.appendChild(dom.frame); + + // contents box + dom.content = document.createElement('div'); + dom.content.className = 'vis-item-content'; + dom.frame.appendChild(dom.content); + + // attach this item as attribute + dom.box['timeline-item'] = this; + + this.dirty = true; + } + + // append DOM to parent DOM + if (!this.parent) { + throw new Error('Cannot redraw item: no parent attached'); + } + if (!dom.box.parentNode) { + var foreground = this.parent.dom.foreground; + if (!foreground) { + throw new Error('Cannot redraw item: parent has no foreground container element'); + } + foreground.appendChild(dom.box); + } + this.displayed = true; + + // Update DOM when item is marked dirty. An item is marked dirty when: + // - the item is not yet rendered + // - the item's data is changed + // - the item is selected/deselected + if (this.dirty) { + this._updateContents(this.dom.content); + this._updateTitle(this.dom.box); + this._updateDataAttributes(this.dom.box); + this._updateStyle(this.dom.box); + + var editable = (this.options.editable.updateTime || this.options.editable.updateGroup || this.editable === true) && this.editable !== false; + + // update class + var className = (this.data.className ? ' ' + this.data.className : '') + (this.selected ? ' vis-selected' : '') + (editable ? ' vis-editable' : ' vis-readonly'); + dom.box.className = this.baseClassName + className; + + // determine from css whether this box has overflow + this.overflow = window.getComputedStyle(dom.frame).overflow !== 'hidden'; + + // recalculate size + // turn off max-width to be able to calculate the real width + // this causes an extra browser repaint/reflow, but so be it + this.dom.content.style.maxWidth = 'none'; + this.props.content.width = this.dom.content.offsetWidth; + this.height = this.dom.box.offsetHeight; + this.dom.content.style.maxWidth = ''; + + this.dirty = false; + } + + this._repaintDeleteButton(dom.box); + this._repaintDragLeft(); + this._repaintDragRight(); + }; + + /** + * Show the item in the DOM (when not already visible). The items DOM will + * be created when needed. + */ + RangeItem.prototype.show = function () { + if (!this.displayed) { + this.redraw(); + } + }; + + /** + * Hide the item from the DOM (when visible) + * @return {Boolean} changed + */ + RangeItem.prototype.hide = function () { + if (this.displayed) { + var box = this.dom.box; + + if (box.parentNode) { + box.parentNode.removeChild(box); + } + + this.displayed = false; + } + }; + + /** + * Reposition the item horizontally + * @param {boolean} [limitSize=true] If true (default), the width of the range + * item will be limited, as the browser cannot + * display very wide divs. This means though + * that the applied left and width may + * not correspond to the ranges start and end + * @Override + */ + RangeItem.prototype.repositionX = function (limitSize) { + var parentWidth = this.parent.width; + var start = this.conversion.toScreen(this.data.start); + var end = this.conversion.toScreen(this.data.end); + var contentLeft; + var contentWidth; + + // limit the width of the range, as browsers cannot draw very wide divs + if (limitSize === undefined || limitSize === true) { + if (start < -parentWidth) { + start = -parentWidth; + } + if (end > 2 * parentWidth) { + end = 2 * parentWidth; + } + } + var boxWidth = Math.max(end - start, 1); + + if (this.overflow) { + this.left = start; + this.width = boxWidth + this.props.content.width; + contentWidth = this.props.content.width; + + // Note: The calculation of width is an optimistic calculation, giving + // a width which will not change when moving the Timeline + // So no re-stacking needed, which is nicer for the eye; + } else { + this.left = start; + this.width = boxWidth; + contentWidth = Math.min(end - start, this.props.content.width); + } + + this.dom.box.style.left = this.left + 'px'; + this.dom.box.style.width = boxWidth + 'px'; + + switch (this.options.align) { + case 'left': + this.dom.content.style.left = '0'; + break; + + case 'right': + this.dom.content.style.left = Math.max(boxWidth - contentWidth, 0) + 'px'; + break; + + case 'center': + this.dom.content.style.left = Math.max((boxWidth - contentWidth) / 2, 0) + 'px'; + break; + + default: + // 'auto' + // when range exceeds left of the window, position the contents at the left of the visible area + if (this.overflow) { + if (end > 0) { + contentLeft = Math.max(-start, 0); + } else { + contentLeft = -contentWidth; // ensure it's not visible anymore + } + } else { + if (start < 0) { + contentLeft = -start; + } else { + contentLeft = 0; + } + } + this.dom.content.style.left = contentLeft + 'px'; + } + }; + + /** + * Reposition the item vertically + * @Override + */ + RangeItem.prototype.repositionY = function () { + var orientation = this.options.orientation.item; + var box = this.dom.box; + + if (orientation == 'top') { + box.style.top = this.top + 'px'; + } else { + box.style.top = this.parent.height - this.top - this.height + 'px'; + } + }; + + /** + * Repaint a drag area on the left side of the range when the range is selected + * @protected + */ + RangeItem.prototype._repaintDragLeft = function () { + if (this.selected && this.options.editable.updateTime && !this.dom.dragLeft) { + // create and show drag area + var dragLeft = document.createElement('div'); + dragLeft.className = 'vis-drag-left'; + dragLeft.dragLeftItem = this; + + this.dom.box.appendChild(dragLeft); + this.dom.dragLeft = dragLeft; + } else if (!this.selected && this.dom.dragLeft) { + // delete drag area + if (this.dom.dragLeft.parentNode) { + this.dom.dragLeft.parentNode.removeChild(this.dom.dragLeft); + } + this.dom.dragLeft = null; + } + }; + + /** + * Repaint a drag area on the right side of the range when the range is selected + * @protected + */ + RangeItem.prototype._repaintDragRight = function () { + if (this.selected && this.options.editable.updateTime && !this.dom.dragRight) { + // create and show drag area + var dragRight = document.createElement('div'); + dragRight.className = 'vis-drag-right'; + dragRight.dragRightItem = this; + + this.dom.box.appendChild(dragRight); + this.dom.dragRight = dragRight; + } else if (!this.selected && this.dom.dragRight) { + // delete drag area + if (this.dom.dragRight.parentNode) { + this.dom.dragRight.parentNode.removeChild(this.dom.dragRight); + } + this.dom.dragRight = null; + } + }; + + module.exports = RangeItem; + +/***/ }, +/* 33 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + var Hammer = __webpack_require__(20); + var util = __webpack_require__(1); + + /** + * @constructor Item + * @param {Object} data Object containing (optional) parameters type, + * start, end, content, group, className. + * @param {{toScreen: function, toTime: function}} conversion + * Conversion functions from time to screen and vice versa + * @param {Object} options Configuration options + * // TODO: describe available options + */ + function Item(data, conversion, options) { + this.id = null; + this.parent = null; + this.data = data; + this.dom = null; + this.conversion = conversion || {}; + this.options = options || {}; + + this.selected = false; + this.displayed = false; + this.dirty = true; + + this.top = null; + this.left = null; + this.width = null; + this.height = null; + + this.editable = null; + if (this.data && this.data.hasOwnProperty('editable') && typeof this.data.editable === 'boolean') { + this.editable = data.editable; + } + } + + Item.prototype.stack = true; + + /** + * Select current item + */ + Item.prototype.select = function () { + this.selected = true; + this.dirty = true; + if (this.displayed) this.redraw(); + }; + + /** + * Unselect current item + */ + Item.prototype.unselect = function () { + this.selected = false; + this.dirty = true; + if (this.displayed) this.redraw(); + }; + + /** + * Set data for the item. Existing data will be updated. The id should not + * be changed. When the item is displayed, it will be redrawn immediately. + * @param {Object} data + */ + Item.prototype.setData = function (data) { + var groupChanged = data.group != undefined && this.data.group != data.group; + if (groupChanged) { + this.parent.itemSet._moveToGroup(this, data.group); + } + + if (data.hasOwnProperty('editable') && typeof data.editable === 'boolean') { + this.editable = data.editable; + } + + this.data = data; + this.dirty = true; + if (this.displayed) this.redraw(); + }; + + /** + * Set a parent for the item + * @param {ItemSet | Group} parent */ - Group.prototype._checkIfVisibleWithReference = function (item, visibleItems, visibleItemsLookup, range) { - if (item.isVisible(range)) { - if (visibleItemsLookup[item.id] === undefined) { - visibleItemsLookup[item.id] = true; - visibleItems.push(item); + Item.prototype.setParent = function (parent) { + if (this.displayed) { + this.hide(); + this.parent = parent; + if (this.parent) { + this.show(); } } else { - if (item.displayed) item.hide(); + this.parent = parent; } }; - module.exports = Group; - -/***/ }, -/* 32 */ -/***/ function(module, exports) { + /** + * Check whether this item is visible inside given range + * @returns {{start: Number, end: Number}} range with a timestamp for start and end + * @returns {boolean} True if visible + */ + Item.prototype.isVisible = function (range) { + // Should be implemented by Item implementations + return false; + }; - // Utility functions for ordering and stacking of items - 'use strict'; + /** + * Show the Item in the DOM (when not already visible) + * @return {Boolean} changed + */ + Item.prototype.show = function () { + return false; + }; - var EPSILON = 0.001; // used when checking collisions, to prevent round-off errors + /** + * Hide the Item from the DOM (when visible) + * @return {Boolean} changed + */ + Item.prototype.hide = function () { + return false; + }; /** - * Order items by their start data - * @param {Item[]} items + * Repaint the item */ - exports.orderByStart = function (items) { - items.sort(function (a, b) { - return a.data.start - b.data.start; - }); + Item.prototype.redraw = function () { + // should be implemented by the item }; /** - * Order items by their end date. If they have no end date, their start date - * is used. - * @param {Item[]} items + * Reposition the Item horizontally */ - exports.orderByEnd = function (items) { - items.sort(function (a, b) { - var aTime = 'end' in a.data ? a.data.end : a.data.start, - bTime = 'end' in b.data ? b.data.end : b.data.start; + Item.prototype.repositionX = function () { + // should be implemented by the item + }; - return aTime - bTime; - }); + /** + * Reposition the Item vertically + */ + Item.prototype.repositionY = function () { + // should be implemented by the item }; /** - * Adjust vertical positions of the items such that they don't overlap each - * other. - * @param {Item[]} items - * All visible items - * @param {{item: {horizontal: number, vertical: number}, axis: number}} margin - * Margins between items and between items and the axis. - * @param {boolean} [force=false] - * If true, all items will be repositioned. If false (default), only - * items having a top===null will be re-stacked + * Repaint a delete button on the top right of the item when the item is selected + * @param {HTMLElement} anchor + * @protected */ - exports.stack = function (items, margin, force) { - var i, iMax; + Item.prototype._repaintDeleteButton = function (anchor) { + var editable = (this.options.editable.remove || this.data.editable === true) && this.data.editable !== false; - if (force) { - // reset top position of all items - for (i = 0, iMax = items.length; i < iMax; i++) { - items[i].top = null; - } - } + if (this.selected && editable && !this.dom.deleteButton) { + // create and show button + var me = this; - // calculate new, non-overlapping positions - for (i = 0, iMax = items.length; i < iMax; i++) { - var item = items[i]; - if (item.stack && item.top === null) { - // initialize top position - item.top = margin.axis; + var deleteButton = document.createElement('div'); + deleteButton.className = 'vis-delete'; + deleteButton.title = 'Delete this item'; - do { - // TODO: optimize checking for overlap. when there is a gap without items, - // you only need to check for items from the next item on, not from zero - var collidingItem = null; - for (var j = 0, jj = items.length; j < jj; j++) { - var other = items[j]; - if (other.top !== null && other !== item && other.stack && exports.collision(item, other, margin.item)) { - collidingItem = other; - break; - } - } + // TODO: be able to destroy the delete button + new Hammer(deleteButton).on('tap', function (event) { + event.stopPropagation(); + me.parent.removeFromDataSet(me); + }); - if (collidingItem != null) { - // There is a collision. Reposition the items above the colliding element - item.top = collidingItem.top + collidingItem.height + margin.item.vertical; - } - } while (collidingItem); + anchor.appendChild(deleteButton); + this.dom.deleteButton = deleteButton; + } else if (!this.selected && this.dom.deleteButton) { + // remove button + if (this.dom.deleteButton.parentNode) { + this.dom.deleteButton.parentNode.removeChild(this.dom.deleteButton); } + this.dom.deleteButton = null; } }; /** - * Adjust vertical positions of the items without stacking them - * @param {Item[]} items - * All visible items - * @param {{item: {horizontal: number, vertical: number}, axis: number}} margin - * Margins between items and between items and the axis. + * Set HTML contents for the item + * @param {Element} element HTML element to fill with the contents + * @private */ - exports.nostack = function (items, margin, subgroups) { - var i, iMax, newTop; + Item.prototype._updateContents = function (element) { + var content; + if (this.options.template) { + var itemData = this.parent.itemSet.itemsData.get(this.id); // get a clone of the data from the dataset + content = this.options.template(itemData); + } else { + content = this.data.content; + } - // reset top position of all items - for (i = 0, iMax = items.length; i < iMax; i++) { - if (items[i].data.subgroup !== undefined) { - newTop = margin.axis; - for (var subgroup in subgroups) { - if (subgroups.hasOwnProperty(subgroup)) { - if (subgroups[subgroup].visible == true && subgroups[subgroup].index < subgroups[items[i].data.subgroup].index) { - newTop += subgroups[subgroup].height + margin.item.vertical; - } - } - } - items[i].top = newTop; + var changed = this._contentToString(this.content) !== this._contentToString(content); + if (changed) { + // only replace the content when changed + if (content instanceof Element) { + element.innerHTML = ''; + element.appendChild(content); + } else if (content != undefined) { + element.innerHTML = content; } else { - items[i].top = margin.axis; + if (!(this.data.type == 'background' && this.data.content === undefined)) { + throw new Error('Property "content" missing in item ' + this.id); + } } + + this.content = content; } }; /** - * Test if the two provided items collide - * The items must have parameters left, width, top, and height. - * @param {Item} a The first item - * @param {Item} b The second item - * @param {{horizontal: number, vertical: number}} margin - * An object containing a horizontal and vertical - * minimum required margin. - * @return {boolean} true if a and b collide, else false + * Set HTML contents for the item + * @param {Element} element HTML element to fill with the contents + * @private */ - exports.collision = function (a, b, margin) { - return a.left - margin.horizontal + EPSILON < b.left + b.width && a.left + a.width + margin.horizontal - EPSILON > b.left && a.top - margin.vertical + EPSILON < b.top + b.height && a.top + a.height + margin.vertical - EPSILON > b.top; + Item.prototype._updateTitle = function (element) { + if (this.data.title != null) { + element.title = this.data.title || ''; + } else { + element.removeAttribute('vis-title'); + } }; -/***/ }, -/* 33 */ -/***/ function(module, exports, __webpack_require__) { - - 'use strict'; - - var Hammer = __webpack_require__(20); - var Item = __webpack_require__(34); - /** - * @constructor RangeItem - * @extends Item - * @param {Object} data Object containing parameters start, end - * content, className. - * @param {{toScreen: function, toTime: function}} conversion - * Conversion functions from time to screen and vice versa - * @param {Object} [options] Configuration options - * // TODO: describe options + * Process dataAttributes timeline option and set as data- attributes on dom.content + * @param {Element} element HTML element to which the attributes will be attached + * @private */ - function RangeItem(data, conversion, options) { - this.props = { - content: { - width: 0 - } - }; - this.overflow = false; // if contents can overflow (css styling), this flag is set to true + Item.prototype._updateDataAttributes = function (element) { + if (this.options.dataAttributes && this.options.dataAttributes.length > 0) { + var attributes = []; - // validate data - if (data) { - if (data.start == undefined) { - throw new Error('Property "start" missing in item ' + data.id); + if (Array.isArray(this.options.dataAttributes)) { + attributes = this.options.dataAttributes; + } else if (this.options.dataAttributes == 'all') { + attributes = Object.keys(this.data); + } else { + return; } - if (data.end == undefined) { - throw new Error('Property "end" missing in item ' + data.id); + + for (var i = 0; i < attributes.length; i++) { + var name = attributes[i]; + var value = this.data[name]; + + if (value != null) { + element.setAttribute('data-' + name, value); + } else { + element.removeAttribute('data-' + name); + } } } + }; - Item.call(this, data, conversion, options); - } + /** + * Update custom styles of the element + * @param element + * @private + */ + Item.prototype._updateStyle = function (element) { + // remove old styles + if (this.style) { + util.removeCssText(element, this.style); + this.style = null; + } - RangeItem.prototype = new Item(null, null, null); + // append new styles + if (this.data.style) { + util.addCssText(element, this.data.style); + this.style = this.data.style; + } + }; - RangeItem.prototype.baseClassName = 'vis-item vis-range'; + /** + * Stringify the items contents + * @param {string | Element | undefined} content + * @returns {string | undefined} + * @private + */ + Item.prototype._contentToString = function (content) { + if (typeof content === 'string') return content; + if (content && 'outerHTML' in content) return content.outerHTML; + return content; + }; /** - * Check whether this item is visible inside given range - * @returns {{start: Number, end: Number}} range with a timestamp for start and end - * @returns {boolean} True if visible + * Return the width of the item left from its start date + * @return {number} */ - RangeItem.prototype.isVisible = function (range) { - // determine visibility - return this.data.start < range.end && this.data.end > range.start; + Item.prototype.getWidthLeft = function () { + return 0; }; /** - * Repaint the item + * Return the width of the item right from the max of its start and end date + * @return {number} */ - RangeItem.prototype.redraw = function () { - var dom = this.dom; - if (!dom) { - // create DOM - this.dom = {}; - dom = this.dom; + Item.prototype.getWidthRight = function () { + return 0; + }; - // background box - dom.box = document.createElement('div'); - // className is updated in redraw() + module.exports = Item; - // frame box (to prevent the item contents from overflowing - dom.frame = document.createElement('div'); - dom.frame.className = 'vis-item-overflow'; - dom.box.appendChild(dom.frame); +/***/ }, +/* 34 */ +/***/ function(module, exports, __webpack_require__) { - // contents box - dom.content = document.createElement('div'); - dom.content.className = 'vis-item-content'; - dom.frame.appendChild(dom.content); + 'use strict'; - // attach this item as attribute - dom.box['timeline-item'] = this; + var moment = __webpack_require__(2); + var DateUtil = __webpack_require__(27); + var util = __webpack_require__(1); - this.dirty = true; - } + /** + * @constructor TimeStep + * The class TimeStep is an iterator for dates. You provide a start date and an + * end date. The class itself determines the best scale (step size) based on the + * provided start Date, end Date, and minimumStep. + * + * If minimumStep is provided, the step size is chosen as close as possible + * to the minimumStep but larger than minimumStep. If minimumStep is not + * provided, the scale is set to 1 DAY. + * The minimumStep should correspond with the onscreen size of about 6 characters + * + * Alternatively, you can set a scale by hand. + * After creation, you can initialize the class by executing first(). Then you + * can iterate from the start date to the end date via next(). You can check if + * the end date is reached with the function hasNext(). After each step, you can + * retrieve the current date via getCurrent(). + * The TimeStep has scales ranging from milliseconds, seconds, minutes, hours, + * days, to years. + * + * Version: 1.2 + * + * @param {Date} [start] The start date, for example new Date(2010, 9, 21) + * or new Date(2010, 9, 21, 23, 45, 00) + * @param {Date} [end] The end date + * @param {Number} [minimumStep] Optional. Minimum step size in milliseconds + */ + function TimeStep(start, end, minimumStep, hiddenDates) { + this.moment = moment; - // append DOM to parent DOM - if (!this.parent) { - throw new Error('Cannot redraw item: no parent attached'); + // variables + this.current = this.moment(); + this._start = this.moment(); + this._end = this.moment(); + + this.autoScale = true; + this.scale = 'day'; + this.step = 1; + + // initialize the range + this.setRange(start, end, minimumStep); + + // hidden Dates options + this.switchedDay = false; + this.switchedMonth = false; + this.switchedYear = false; + this.hiddenDates = hiddenDates; + if (hiddenDates === undefined) { + this.hiddenDates = []; } - if (!dom.box.parentNode) { - var foreground = this.parent.dom.foreground; - if (!foreground) { - throw new Error('Cannot redraw item: parent has no foreground container element'); - } - foreground.appendChild(dom.box); + + this.format = TimeStep.FORMAT; // default formatting + } + + // Time formatting + TimeStep.FORMAT = { + minorLabels: { + millisecond: 'SSS', + second: 's', + minute: 'HH:mm', + hour: 'HH:mm', + weekday: 'ddd D', + day: 'D', + month: 'MMM', + year: 'YYYY' + }, + majorLabels: { + millisecond: 'HH:mm:ss', + second: 'D MMMM HH:mm', + minute: 'ddd D MMMM', + hour: 'ddd D MMMM', + weekday: 'MMMM YYYY', + day: 'MMMM YYYY', + month: 'YYYY', + year: '' } - this.displayed = true; + }; - // Update DOM when item is marked dirty. An item is marked dirty when: - // - the item is not yet rendered - // - the item's data is changed - // - the item is selected/deselected - if (this.dirty) { - this._updateContents(this.dom.content); - this._updateTitle(this.dom.box); - this._updateDataAttributes(this.dom.box); - this._updateStyle(this.dom.box); + /** + * Set custom constructor function for moment. Can be used to set dates + * to UTC or to set a utcOffset. + * @param {function} moment + */ + TimeStep.prototype.setMoment = function (moment) { + this.moment = moment; - var editable = (this.options.editable.updateTime || this.options.editable.updateGroup || this.editable === true) && this.editable !== false; + // update the date properties, can have a new utcOffset + this.current = this.moment(this.current); + this._start = this.moment(this._start); + this._end = this.moment(this._end); + }; - // update class - var className = (this.data.className ? ' ' + this.data.className : '') + (this.selected ? ' vis-selected' : '') + (editable ? ' vis-editable' : ' vis-readonly'); - dom.box.className = this.baseClassName + className; + /** + * Set custom formatting for the minor an major labels of the TimeStep. + * Both `minorLabels` and `majorLabels` are an Object with properties: + * 'millisecond', 'second', 'minute', 'hour', 'weekday', 'day', 'month', 'year'. + * @param {{minorLabels: Object, majorLabels: Object}} format + */ + TimeStep.prototype.setFormat = function (format) { + var defaultFormat = util.deepExtend({}, TimeStep.FORMAT); + this.format = util.deepExtend(defaultFormat, format); + }; - // determine from css whether this box has overflow - this.overflow = window.getComputedStyle(dom.frame).overflow !== 'hidden'; + /** + * Set a new range + * If minimumStep is provided, the step size is chosen as close as possible + * to the minimumStep but larger than minimumStep. If minimumStep is not + * provided, the scale is set to 1 DAY. + * The minimumStep should correspond with the onscreen size of about 6 characters + * @param {Date} [start] The start date and time. + * @param {Date} [end] The end date and time. + * @param {int} [minimumStep] Optional. Minimum step size in milliseconds + */ + TimeStep.prototype.setRange = function (start, end, minimumStep) { + if (!(start instanceof Date) || !(end instanceof Date)) { + throw "No legal start or end date in method setRange"; + } - // recalculate size - // turn off max-width to be able to calculate the real width - // this causes an extra browser repaint/reflow, but so be it - this.dom.content.style.maxWidth = 'none'; - this.props.content.width = this.dom.content.offsetWidth; - this.height = this.dom.box.offsetHeight; - this.dom.content.style.maxWidth = ''; + this._start = start != undefined ? this.moment(start.valueOf()) : new Date(); + this._end = end != undefined ? this.moment(end.valueOf()) : new Date(); - this.dirty = false; + if (this.autoScale) { + this.setMinimumStep(minimumStep); + } + }; + + /** + * Set the range iterator to the start date. + */ + TimeStep.prototype.start = function () { + this.current = this._start.clone(); + this.roundToMinor(); + }; + + /** + * Round the current date to the first minor date value + * This must be executed once when the current date is set to start Date + */ + TimeStep.prototype.roundToMinor = function () { + // round to floor + // IMPORTANT: we have no breaks in this switch! (this is no bug) + // noinspection FallThroughInSwitchStatementJS + switch (this.scale) { + case 'year': + this.current.year(this.step * Math.floor(this.current.year() / this.step)); + this.current.month(0); + case 'month': + this.current.date(1); + case 'day': // intentional fall through + case 'weekday': + this.current.hours(0); + case 'hour': + this.current.minutes(0); + case 'minute': + this.current.seconds(0); + case 'second': + this.current.milliseconds(0); + //case 'millisecond': // nothing to do for milliseconds } - this._repaintDeleteButton(dom.box); - this._repaintDragLeft(); - this._repaintDragRight(); - }; - - /** - * Show the item in the DOM (when not already visible). The items DOM will - * be created when needed. - */ - RangeItem.prototype.show = function () { - if (!this.displayed) { - this.redraw(); + if (this.step != 1) { + // round down to the first minor value that is a multiple of the current step size + switch (this.scale) { + case 'millisecond': + this.current.subtract(this.current.milliseconds() % this.step, 'milliseconds');break; + case 'second': + this.current.subtract(this.current.seconds() % this.step, 'seconds');break; + case 'minute': + this.current.subtract(this.current.minutes() % this.step, 'minutes');break; + case 'hour': + this.current.subtract(this.current.hours() % this.step, 'hours');break; + case 'weekday': // intentional fall through + case 'day': + this.current.subtract((this.current.date() - 1) % this.step, 'day');break; + case 'month': + this.current.subtract(this.current.month() % this.step, 'month');break; + case 'year': + this.current.subtract(this.current.year() % this.step, 'year');break; + default: + break; + } } }; /** - * Hide the item from the DOM (when visible) - * @return {Boolean} changed + * Check if the there is a next step + * @return {boolean} true if the current date has not passed the end date */ - RangeItem.prototype.hide = function () { - if (this.displayed) { - var box = this.dom.box; - - if (box.parentNode) { - box.parentNode.removeChild(box); - } - - this.displayed = false; - } + TimeStep.prototype.hasNext = function () { + return this.current.valueOf() <= this._end.valueOf(); }; /** - * Reposition the item horizontally - * @param {boolean} [limitSize=true] If true (default), the width of the range - * item will be limited, as the browser cannot - * display very wide divs. This means though - * that the applied left and width may - * not correspond to the ranges start and end - * @Override + * Do the next step */ - RangeItem.prototype.repositionX = function (limitSize) { - var parentWidth = this.parent.width; - var start = this.conversion.toScreen(this.data.start); - var end = this.conversion.toScreen(this.data.end); - var contentLeft; - var contentWidth; + TimeStep.prototype.next = function () { + var prev = this.current.valueOf(); - // limit the width of the range, as browsers cannot draw very wide divs - if (limitSize === undefined || limitSize === true) { - if (start < -parentWidth) { - start = -parentWidth; + // Two cases, needed to prevent issues with switching daylight savings + // (end of March and end of October) + if (this.current.month() < 6) { + switch (this.scale) { + case 'millisecond': + this.current.add(this.step, 'millisecond');break; + case 'second': + this.current.add(this.step, 'second');break; + case 'minute': + this.current.add(this.step, 'minute');break; + case 'hour': + this.current.add(this.step, 'hour'); + // in case of skipping an hour for daylight savings, adjust the hour again (else you get: 0h 5h 9h ... instead of 0h 4h 8h ...) + // TODO: is this still needed now we use the function of moment.js? + this.current.subtract(this.current.hours() % this.step, 'hour'); + break; + case 'weekday': // intentional fall through + case 'day': + this.current.add(this.step, 'day');break; + case 'month': + this.current.add(this.step, 'month');break; + case 'year': + this.current.add(this.step, 'year');break; + default: + break; } - if (end > 2 * parentWidth) { - end = 2 * parentWidth; + } else { + switch (this.scale) { + case 'millisecond': + this.current.add(this.step, 'millisecond');break; + case 'second': + this.current.add(this.step, 'second');break; + case 'minute': + this.current.add(this.step, 'minute');break; + case 'hour': + this.current.add(this.step, 'hour');break; + case 'weekday': // intentional fall through + case 'day': + this.current.add(this.step, 'day');break; + case 'month': + this.current.add(this.step, 'month');break; + case 'year': + this.current.add(this.step, 'year');break; + default: + break; } } - var boxWidth = Math.max(end - start, 1); - - if (this.overflow) { - this.left = start; - this.width = boxWidth + this.props.content.width; - contentWidth = this.props.content.width; - // Note: The calculation of width is an optimistic calculation, giving - // a width which will not change when moving the Timeline - // So no re-stacking needed, which is nicer for the eye; - } else { - this.left = start; - this.width = boxWidth; - contentWidth = Math.min(end - start, this.props.content.width); + if (this.step != 1) { + // round down to the correct major value + switch (this.scale) { + case 'millisecond': + if (this.current.milliseconds() < this.step) this.current.milliseconds(0);break; + case 'second': + if (this.current.seconds() < this.step) this.current.seconds(0);break; + case 'minute': + if (this.current.minutes() < this.step) this.current.minutes(0);break; + case 'hour': + if (this.current.hours() < this.step) this.current.hours(0);break; + case 'weekday': // intentional fall through + case 'day': + if (this.current.date() < this.step + 1) this.current.date(1);break; + case 'month': + if (this.current.month() < this.step) this.current.month(0);break; + case 'year': + break; // nothing to do for year + default: + break; + } } - this.dom.box.style.left = this.left + 'px'; - this.dom.box.style.width = boxWidth + 'px'; - - switch (this.options.align) { - case 'left': - this.dom.content.style.left = '0'; - break; - - case 'right': - this.dom.content.style.left = Math.max(boxWidth - contentWidth, 0) + 'px'; - break; - - case 'center': - this.dom.content.style.left = Math.max((boxWidth - contentWidth) / 2, 0) + 'px'; - break; - - default: - // 'auto' - // when range exceeds left of the window, position the contents at the left of the visible area - if (this.overflow) { - if (end > 0) { - contentLeft = Math.max(-start, 0); - } else { - contentLeft = -contentWidth; // ensure it's not visible anymore - } - } else { - if (start < 0) { - contentLeft = -start; - } else { - contentLeft = 0; - } - } - this.dom.content.style.left = contentLeft + 'px'; + // safety mechanism: if current time is still unchanged, move to the end + if (this.current.valueOf() == prev) { + this.current = this._end.clone(); } + + DateUtil.stepOverHiddenDates(this.moment, this, prev); }; /** - * Reposition the item vertically - * @Override + * Get the current datetime + * @return {Moment} current The current date */ - RangeItem.prototype.repositionY = function () { - var orientation = this.options.orientation.item; - var box = this.dom.box; - - if (orientation == 'top') { - box.style.top = this.top + 'px'; - } else { - box.style.top = this.parent.height - this.top - this.height + 'px'; - } + TimeStep.prototype.getCurrent = function () { + return this.current; }; /** - * Repaint a drag area on the left side of the range when the range is selected - * @protected + * Set a custom scale. Autoscaling will be disabled. + * For example setScale('minute', 5) will result + * in minor steps of 5 minutes, and major steps of an hour. + * + * @param {{scale: string, step: number}} params + * An object containing two properties: + * - A string 'scale'. Choose from 'millisecond', 'second', + * 'minute', 'hour', 'weekday', 'day', 'month', 'year'. + * - A number 'step'. A step size, by default 1. + * Choose for example 1, 2, 5, or 10. */ - RangeItem.prototype._repaintDragLeft = function () { - if (this.selected && this.options.editable.updateTime && !this.dom.dragLeft) { - // create and show drag area - var dragLeft = document.createElement('div'); - dragLeft.className = 'vis-drag-left'; - dragLeft.dragLeftItem = this; - - this.dom.box.appendChild(dragLeft); - this.dom.dragLeft = dragLeft; - } else if (!this.selected && this.dom.dragLeft) { - // delete drag area - if (this.dom.dragLeft.parentNode) { - this.dom.dragLeft.parentNode.removeChild(this.dom.dragLeft); - } - this.dom.dragLeft = null; + TimeStep.prototype.setScale = function (params) { + if (params && typeof params.scale == 'string') { + this.scale = params.scale; + this.step = params.step > 0 ? params.step : 1; + this.autoScale = false; } }; /** - * Repaint a drag area on the right side of the range when the range is selected - * @protected + * Enable or disable autoscaling + * @param {boolean} enable If true, autoascaling is set true */ - RangeItem.prototype._repaintDragRight = function () { - if (this.selected && this.options.editable.updateTime && !this.dom.dragRight) { - // create and show drag area - var dragRight = document.createElement('div'); - dragRight.className = 'vis-drag-right'; - dragRight.dragRightItem = this; - - this.dom.box.appendChild(dragRight); - this.dom.dragRight = dragRight; - } else if (!this.selected && this.dom.dragRight) { - // delete drag area - if (this.dom.dragRight.parentNode) { - this.dom.dragRight.parentNode.removeChild(this.dom.dragRight); - } - this.dom.dragRight = null; - } + TimeStep.prototype.setAutoScale = function (enable) { + this.autoScale = enable; }; - module.exports = RangeItem; - -/***/ }, -/* 34 */ -/***/ function(module, exports, __webpack_require__) { - - 'use strict'; - - var Hammer = __webpack_require__(20); - var util = __webpack_require__(1); - /** - * @constructor Item - * @param {Object} data Object containing (optional) parameters type, - * start, end, content, group, className. - * @param {{toScreen: function, toTime: function}} conversion - * Conversion functions from time to screen and vice versa - * @param {Object} options Configuration options - * // TODO: describe available options + * Automatically determine the scale that bests fits the provided minimum step + * @param {Number} [minimumStep] The minimum step size in milliseconds */ - function Item(data, conversion, options) { - this.id = null; - this.parent = null; - this.data = data; - this.dom = null; - this.conversion = conversion || {}; - this.options = options || {}; + TimeStep.prototype.setMinimumStep = function (minimumStep) { + if (minimumStep == undefined) { + return; + } - this.selected = false; - this.displayed = false; - this.dirty = true; + //var b = asc + ds; - this.top = null; - this.left = null; - this.width = null; - this.height = null; + var stepYear = 1000 * 60 * 60 * 24 * 30 * 12; + var stepMonth = 1000 * 60 * 60 * 24 * 30; + var stepDay = 1000 * 60 * 60 * 24; + var stepHour = 1000 * 60 * 60; + var stepMinute = 1000 * 60; + var stepSecond = 1000; + var stepMillisecond = 1; - this.editable = null; - if (this.data && this.data.hasOwnProperty('editable') && typeof this.data.editable === 'boolean') { - this.editable = data.editable; + // find the smallest step that is larger than the provided minimumStep + if (stepYear * 1000 > minimumStep) { + this.scale = 'year';this.step = 1000; + } + if (stepYear * 500 > minimumStep) { + this.scale = 'year';this.step = 500; + } + if (stepYear * 100 > minimumStep) { + this.scale = 'year';this.step = 100; + } + if (stepYear * 50 > minimumStep) { + this.scale = 'year';this.step = 50; + } + if (stepYear * 10 > minimumStep) { + this.scale = 'year';this.step = 10; + } + if (stepYear * 5 > minimumStep) { + this.scale = 'year';this.step = 5; + } + if (stepYear > minimumStep) { + this.scale = 'year';this.step = 1; + } + if (stepMonth * 3 > minimumStep) { + this.scale = 'month';this.step = 3; + } + if (stepMonth > minimumStep) { + this.scale = 'month';this.step = 1; + } + if (stepDay * 5 > minimumStep) { + this.scale = 'day';this.step = 5; + } + if (stepDay * 2 > minimumStep) { + this.scale = 'day';this.step = 2; + } + if (stepDay > minimumStep) { + this.scale = 'day';this.step = 1; + } + if (stepDay / 2 > minimumStep) { + this.scale = 'weekday';this.step = 1; + } + if (stepHour * 4 > minimumStep) { + this.scale = 'hour';this.step = 4; + } + if (stepHour > minimumStep) { + this.scale = 'hour';this.step = 1; + } + if (stepMinute * 15 > minimumStep) { + this.scale = 'minute';this.step = 15; + } + if (stepMinute * 10 > minimumStep) { + this.scale = 'minute';this.step = 10; + } + if (stepMinute * 5 > minimumStep) { + this.scale = 'minute';this.step = 5; + } + if (stepMinute > minimumStep) { + this.scale = 'minute';this.step = 1; + } + if (stepSecond * 15 > minimumStep) { + this.scale = 'second';this.step = 15; + } + if (stepSecond * 10 > minimumStep) { + this.scale = 'second';this.step = 10; + } + if (stepSecond * 5 > minimumStep) { + this.scale = 'second';this.step = 5; + } + if (stepSecond > minimumStep) { + this.scale = 'second';this.step = 1; + } + if (stepMillisecond * 200 > minimumStep) { + this.scale = 'millisecond';this.step = 200; + } + if (stepMillisecond * 100 > minimumStep) { + this.scale = 'millisecond';this.step = 100; + } + if (stepMillisecond * 50 > minimumStep) { + this.scale = 'millisecond';this.step = 50; + } + if (stepMillisecond * 10 > minimumStep) { + this.scale = 'millisecond';this.step = 10; + } + if (stepMillisecond * 5 > minimumStep) { + this.scale = 'millisecond';this.step = 5; + } + if (stepMillisecond > minimumStep) { + this.scale = 'millisecond';this.step = 1; } - } - - Item.prototype.stack = true; - - /** - * Select current item - */ - Item.prototype.select = function () { - this.selected = true; - this.dirty = true; - if (this.displayed) this.redraw(); }; /** - * Unselect current item + * Snap a date to a rounded value. + * The snap intervals are dependent on the current scale and step. + * Static function + * @param {Date} date the date to be snapped. + * @param {string} scale Current scale, can be 'millisecond', 'second', + * 'minute', 'hour', 'weekday, 'day', 'month', 'year'. + * @param {number} step Current step (1, 2, 4, 5, ... + * @return {Date} snappedDate */ - Item.prototype.unselect = function () { - this.selected = false; - this.dirty = true; - if (this.displayed) this.redraw(); - }; + TimeStep.snap = function (date, scale, step) { + var clone = moment(date); - /** - * Set data for the item. Existing data will be updated. The id should not - * be changed. When the item is displayed, it will be redrawn immediately. - * @param {Object} data - */ - Item.prototype.setData = function (data) { - var groupChanged = data.group != undefined && this.data.group != data.group; - if (groupChanged) { - this.parent.itemSet._moveToGroup(this, data.group); - } + if (scale == 'year') { + var year = clone.year() + Math.round(clone.month() / 12); + clone.year(Math.round(year / step) * step); + clone.month(0); + clone.date(0); + clone.hours(0); + clone.minutes(0); + clone.seconds(0); + clone.milliseconds(0); + } else if (scale == 'month') { + if (clone.date() > 15) { + clone.date(1); + clone.add(1, 'month'); + // important: first set Date to 1, after that change the month. + } else { + clone.date(1); + } - if (data.hasOwnProperty('editable') && typeof data.editable === 'boolean') { - this.editable = data.editable; + clone.hours(0); + clone.minutes(0); + clone.seconds(0); + clone.milliseconds(0); + } else if (scale == 'day') { + //noinspection FallthroughInSwitchStatementJS + switch (step) { + case 5: + case 2: + clone.hours(Math.round(clone.hours() / 24) * 24);break; + default: + clone.hours(Math.round(clone.hours() / 12) * 12);break; + } + clone.minutes(0); + clone.seconds(0); + clone.milliseconds(0); + } else if (scale == 'weekday') { + //noinspection FallthroughInSwitchStatementJS + switch (step) { + case 5: + case 2: + clone.hours(Math.round(clone.hours() / 12) * 12);break; + default: + clone.hours(Math.round(clone.hours() / 6) * 6);break; + } + clone.minutes(0); + clone.seconds(0); + clone.milliseconds(0); + } else if (scale == 'hour') { + switch (step) { + case 4: + clone.minutes(Math.round(clone.minutes() / 60) * 60);break; + default: + clone.minutes(Math.round(clone.minutes() / 30) * 30);break; + } + clone.seconds(0); + clone.milliseconds(0); + } else if (scale == 'minute') { + //noinspection FallthroughInSwitchStatementJS + switch (step) { + case 15: + case 10: + clone.minutes(Math.round(clone.minutes() / 5) * 5); + clone.seconds(0); + break; + case 5: + clone.seconds(Math.round(clone.seconds() / 60) * 60);break; + default: + clone.seconds(Math.round(clone.seconds() / 30) * 30);break; + } + clone.milliseconds(0); + } else if (scale == 'second') { + //noinspection FallthroughInSwitchStatementJS + switch (step) { + case 15: + case 10: + clone.seconds(Math.round(clone.seconds() / 5) * 5); + clone.milliseconds(0); + break; + case 5: + clone.milliseconds(Math.round(clone.milliseconds() / 1000) * 1000);break; + default: + clone.milliseconds(Math.round(clone.milliseconds() / 500) * 500);break; + } + } else if (scale == 'millisecond') { + var _step = step > 5 ? step / 2 : 1; + clone.milliseconds(Math.round(clone.milliseconds() / _step) * _step); } - this.data = data; - this.dirty = true; - if (this.displayed) this.redraw(); + return clone; }; /** - * Set a parent for the item - * @param {ItemSet | Group} parent + * Check if the current value is a major value (for example when the step + * is DAY, a major value is each first day of the MONTH) + * @return {boolean} true if current date is major, else false. */ - Item.prototype.setParent = function (parent) { - if (this.displayed) { - this.hide(); - this.parent = parent; - if (this.parent) { - this.show(); + TimeStep.prototype.isMajor = function () { + if (this.switchedYear == true) { + this.switchedYear = false; + switch (this.scale) { + case 'year': + case 'month': + case 'weekday': + case 'day': + case 'hour': + case 'minute': + case 'second': + case 'millisecond': + return true; + default: + return false; + } + } else if (this.switchedMonth == true) { + this.switchedMonth = false; + switch (this.scale) { + case 'weekday': + case 'day': + case 'hour': + case 'minute': + case 'second': + case 'millisecond': + return true; + default: + return false; + } + } else if (this.switchedDay == true) { + this.switchedDay = false; + switch (this.scale) { + case 'millisecond': + case 'second': + case 'minute': + case 'hour': + return true; + default: + return false; } - } else { - this.parent = parent; } - }; - /** - * Check whether this item is visible inside given range - * @returns {{start: Number, end: Number}} range with a timestamp for start and end - * @returns {boolean} True if visible - */ - Item.prototype.isVisible = function (range) { - // Should be implemented by Item implementations - return false; + var date = this.moment(this.current); + switch (this.scale) { + case 'millisecond': + return date.milliseconds() == 0; + case 'second': + return date.seconds() == 0; + case 'minute': + return date.hours() == 0 && date.minutes() == 0; + case 'hour': + return date.hours() == 0; + case 'weekday': // intentional fall through + case 'day': + return date.date() == 1; + case 'month': + return date.month() == 0; + case 'year': + return false; + default: + return false; + } }; /** - * Show the Item in the DOM (when not already visible) - * @return {Boolean} changed + * Returns formatted text for the minor axislabel, depending on the current + * date and the scale. For example when scale is MINUTE, the current time is + * formatted as "hh:mm". + * @param {Date} [date] custom date. if not provided, current date is taken */ - Item.prototype.show = function () { - return false; - }; + TimeStep.prototype.getLabelMinor = function (date) { + if (date == undefined) { + date = this.current; + } - /** - * Hide the Item from the DOM (when visible) - * @return {Boolean} changed - */ - Item.prototype.hide = function () { - return false; + var format = this.format.minorLabels[this.scale]; + return format && format.length > 0 ? this.moment(date).format(format) : ''; }; /** - * Repaint the item - */ - Item.prototype.redraw = function () {}; - - /** - * Reposition the Item horizontally - */ - Item.prototype.repositionX = function () {}; - - /** - * Reposition the Item vertically - */ - Item.prototype.repositionY = function () {}; - - /** - * Repaint a delete button on the top right of the item when the item is selected - * @param {HTMLElement} anchor - * @protected + * Returns formatted text for the major axis label, depending on the current + * date and the scale. For example when scale is MINUTE, the major scale is + * hours, and the hour will be formatted as "hh". + * @param {Date} [date] custom date. if not provided, current date is taken */ - Item.prototype._repaintDeleteButton = function (anchor) { - var editable = (this.options.editable.remove || this.data.editable === true) && this.data.editable !== false; + TimeStep.prototype.getLabelMajor = function (date) { + if (date == undefined) { + date = this.current; + } - if (this.selected && editable && !this.dom.deleteButton) { - // create and show button - var me = this; + var format = this.format.majorLabels[this.scale]; + return format && format.length > 0 ? this.moment(date).format(format) : ''; + }; - var deleteButton = document.createElement('div'); - deleteButton.className = 'vis-delete'; - deleteButton.title = 'Delete this item'; + TimeStep.prototype.getClassName = function () { + var _moment = this.moment; + var m = this.moment(this.current); + var current = m.locale ? m.locale('en') : m.lang('en'); // old versions of moment have .lang() function + var step = this.step; - // TODO: be able to destroy the delete button - new Hammer(deleteButton).on('tap', function (event) { - event.stopPropagation(); - me.parent.removeFromDataSet(me); - }); + function even(value) { + return value / step % 2 == 0 ? ' vis-even' : ' vis-odd'; + } - anchor.appendChild(deleteButton); - this.dom.deleteButton = deleteButton; - } else if (!this.selected && this.dom.deleteButton) { - // remove button - if (this.dom.deleteButton.parentNode) { - this.dom.deleteButton.parentNode.removeChild(this.dom.deleteButton); + function today(date) { + if (date.isSame(new Date(), 'day')) { + return ' vis-today'; } - this.dom.deleteButton = null; + if (date.isSame(_moment().add(1, 'day'), 'day')) { + return ' vis-tomorrow'; + } + if (date.isSame(_moment().add(-1, 'day'), 'day')) { + return ' vis-yesterday'; + } + return ''; } - }; - /** - * Set HTML contents for the item - * @param {Element} element HTML element to fill with the contents - * @private - */ - Item.prototype._updateContents = function (element) { - var content; - if (this.options.template) { - var itemData = this.parent.itemSet.itemsData.get(this.id); // get a clone of the data from the dataset - content = this.options.template(itemData); - } else { - content = this.data.content; + function currentWeek(date) { + return date.isSame(new Date(), 'week') ? ' vis-current-week' : ''; } - var changed = this._contentToString(this.content) !== this._contentToString(content); - if (changed) { - // only replace the content when changed - if (content instanceof Element) { - element.innerHTML = ''; - element.appendChild(content); - } else if (content != undefined) { - element.innerHTML = content; - } else { - if (!(this.data.type == 'background' && this.data.content === undefined)) { - throw new Error('Property "content" missing in item ' + this.id); - } - } - - this.content = content; + function currentMonth(date) { + return date.isSame(new Date(), 'month') ? ' vis-current-month' : ''; } - }; - /** - * Set HTML contents for the item - * @param {Element} element HTML element to fill with the contents - * @private - */ - Item.prototype._updateTitle = function (element) { - if (this.data.title != null) { - element.title = this.data.title || ''; - } else { - element.removeAttribute('vis-title'); + function currentYear(date) { + return date.isSame(new Date(), 'year') ? ' vis-current-year' : ''; } - }; - /** - * Process dataAttributes timeline option and set as data- attributes on dom.content - * @param {Element} element HTML element to which the attributes will be attached - * @private - */ - Item.prototype._updateDataAttributes = function (element) { - if (this.options.dataAttributes && this.options.dataAttributes.length > 0) { - var attributes = []; + switch (this.scale) { + case 'millisecond': + return even(current.milliseconds()).trim(); - if (Array.isArray(this.options.dataAttributes)) { - attributes = this.options.dataAttributes; - } else if (this.options.dataAttributes == 'all') { - attributes = Object.keys(this.data); - } else { - return; - } + case 'second': + return even(current.seconds()).trim(); - for (var i = 0; i < attributes.length; i++) { - var name = attributes[i]; - var value = this.data[name]; + case 'minute': + return even(current.minutes()).trim(); - if (value != null) { - element.setAttribute('data-' + name, value); - } else { - element.removeAttribute('data-' + name); + case 'hour': + var hours = current.hours(); + if (this.step == 4) { + hours = hours + '-h' + (hours + 4); } - } - } - }; + return 'vis-h' + hours + today(current) + even(current.hours()); - /** - * Update custom styles of the element - * @param element - * @private - */ - Item.prototype._updateStyle = function (element) { - // remove old styles - if (this.style) { - util.removeCssText(element, this.style); - this.style = null; - } + case 'weekday': + return 'vis-' + current.format('dddd').toLowerCase() + today(current) + currentWeek(current) + even(current.date()); - // append new styles - if (this.data.style) { - util.addCssText(element, this.data.style); - this.style = this.data.style; - } - }; + case 'day': + var day = current.date(); + var month = current.format('MMMM').toLowerCase(); + return 'vis-day' + day + ' vis-' + month + currentMonth(current) + even(day - 1); - /** - * Stringify the items contents - * @param {string | Element | undefined} content - * @returns {string | undefined} - * @private - */ - Item.prototype._contentToString = function (content) { - if (typeof content === 'string') return content; - if (content && 'outerHTML' in content) return content.outerHTML; - return content; - }; + case 'month': + return 'vis-' + current.format('MMMM').toLowerCase() + currentMonth(current) + even(current.month()); - /** - * Return the width of the item left from its start date - * @return {number} - */ - Item.prototype.getWidthLeft = function () { - return 0; - }; + case 'year': + var year = current.year(); + return 'vis-year' + year + currentYear(current) + even(year); - /** - * Return the width of the item right from the max of its start and end date - * @return {number} - */ - Item.prototype.getWidthRight = function () { - return 0; + default: + return ''; + } }; - module.exports = Item; - - // should be implemented by the item - - // should be implemented by the item - - // should be implemented by the item + module.exports = TimeStep; /***/ }, /* 35 */ @@ -19467,7 +19384,7 @@ return /******/ (function(modules) { // webpackBootstrap 'use strict'; var util = __webpack_require__(1); - var Group = __webpack_require__(31); + var Group = __webpack_require__(30); /** * @constructor BackgroundGroup @@ -19530,7 +19447,7 @@ return /******/ (function(modules) { // webpackBootstrap 'use strict'; - var Item = __webpack_require__(34); + var Item = __webpack_require__(33); var util = __webpack_require__(1); /** @@ -19770,7 +19687,7 @@ return /******/ (function(modules) { // webpackBootstrap 'use strict'; - var Item = __webpack_require__(34); + var Item = __webpack_require__(33); /** * @constructor PointItem @@ -19976,9 +19893,9 @@ return /******/ (function(modules) { // webpackBootstrap 'use strict'; var Hammer = __webpack_require__(20); - var Item = __webpack_require__(34); + var Item = __webpack_require__(33); var BackgroundGroup = __webpack_require__(35); - var RangeItem = __webpack_require__(33); + var RangeItem = __webpack_require__(32); /** * @constructor BackgroundItem @@ -20152,23 +20069,23 @@ return /******/ (function(modules) { // webpackBootstrap } // and when the orientation is bottom: else { - var newTop = this.parent.top; - var totalHeight = 0; - for (var subgroup in subgroups) { - if (subgroups.hasOwnProperty(subgroup)) { - if (subgroups[subgroup].visible == true) { - var newHeight = subgroups[subgroup].height + margin.item.vertical; - totalHeight += newHeight; - if (subgroups[subgroup].index > subgroupIndex) { - newTop += newHeight; + var newTop = this.parent.top; + var totalHeight = 0; + for (var subgroup in subgroups) { + if (subgroups.hasOwnProperty(subgroup)) { + if (subgroups[subgroup].visible == true) { + var newHeight = subgroups[subgroup].height + margin.item.vertical; + totalHeight += newHeight; + if (subgroups[subgroup].index > subgroupIndex) { + newTop += newHeight; + } } } } + height = this.parent.subgroups[itemSubgroup].height + margin.item.vertical; + this.dom.box.style.top = this.parent.height - totalHeight + newTop + 'px'; + this.dom.box.style.bottom = ''; } - height = this.parent.subgroups[itemSubgroup].height + margin.item.vertical; - this.dom.box.style.top = this.parent.height - totalHeight + newTop + 'px'; - this.dom.box.style.bottom = ''; - } } // and in the case of no subgroups: else { @@ -20198,7 +20115,7 @@ return /******/ (function(modules) { // webpackBootstrap var util = __webpack_require__(1); var Component = __webpack_require__(26); - var TimeStep = __webpack_require__(30); + var TimeStep = __webpack_require__(34); var DateUtil = __webpack_require__(27); var moment = __webpack_require__(2); @@ -20659,7 +20576,7 @@ return /******/ (function(modules) { // webpackBootstrap 'use strict'; var keycharm = __webpack_require__(41); - var Emitter = __webpack_require__(12); + var Emitter = __webpack_require__(13); var Hammer = __webpack_require__(20); var util = __webpack_require__(1); @@ -21465,10 +21382,6 @@ return /******/ (function(modules) { // webpackBootstrap var _ColorPicker = __webpack_require__(46); - var _ColorPicker2 = _interopRequireDefault(_ColorPicker); - - var util = __webpack_require__(1); - /** * The way this works is for all properties of this.possible options, you can supply the property name in any form to list the options. * Boolean options are recognised as Boolean @@ -21484,6 +21397,10 @@ return /******/ (function(modules) { // webpackBootstrap * @param pixelRatio | canvas pixel ratio */ + var _ColorPicker2 = _interopRequireDefault(_ColorPicker); + + var util = __webpack_require__(1); + var Configurator = (function () { function Configurator(parentModule, defaultContainer, configureOptions) { var pixelRatio = arguments.length <= 3 || arguments[3] === undefined ? 1 : arguments[3]; @@ -21516,15 +21433,15 @@ return /******/ (function(modules) { // webpackBootstrap this.wrapper = undefined; } + /** + * refresh all options. + * Because all modules parse their options by themselves, we just use their options. We copy them here. + * + * @param options + */ + _createClass(Configurator, [{ key: 'setOptions', - - /** - * refresh all options. - * Because all modules parse their options by themselves, we just use their options. We copy them here. - * - * @param options - */ value: function setOptions(options) { if (options !== undefined) { // reset the popup history because the indices may have been changed. @@ -21576,13 +21493,13 @@ return /******/ (function(modules) { // webpackBootstrap this._create(); } } - }, { - key: '_create', /** * Create all DOM elements * @private */ + }, { + key: '_create', value: function _create() { var _this = this; @@ -21646,13 +21563,13 @@ return /******/ (function(modules) { // webpackBootstrap this._push(); this.colorPicker.insertTo(this.container); } - }, { - key: '_push', /** * draw all DOM elements on the screen * @private */ + }, { + key: '_push', value: function _push() { this.wrapper = document.createElement('div'); this.wrapper.className = 'vis-configuration-wrapper'; @@ -21663,13 +21580,13 @@ return /******/ (function(modules) { // webpackBootstrap this._showPopupIfNeeded(); } - }, { - key: '_clean', /** * delete all DOM elements * @private */ + }, { + key: '_clean', value: function _clean() { for (var i = 0; i < this.domElements.length; i++) { this.wrapper.removeChild(this.domElements[i]); @@ -21683,8 +21600,6 @@ return /******/ (function(modules) { // webpackBootstrap this._removePopup(); } - }, { - key: '_getValue', /** * get the value from the actualOptions if it exists @@ -21692,6 +21607,8 @@ return /******/ (function(modules) { // webpackBootstrap * @returns {*} * @private */ + }, { + key: '_getValue', value: function _getValue(path) { var base = this.moduleOptions; for (var i = 0; i < path.length; i++) { @@ -21704,8 +21621,6 @@ return /******/ (function(modules) { // webpackBootstrap } return base; } - }, { - key: '_makeItem', /** * all option elements are wrapped in an item @@ -21713,6 +21628,8 @@ return /******/ (function(modules) { // webpackBootstrap * @param domElements * @private */ + }, { + key: '_makeItem', value: function _makeItem(path) { var _arguments = arguments, _this2 = this; @@ -21741,22 +21658,20 @@ return /******/ (function(modules) { // webpackBootstrap } return 0; } - }, { - key: '_makeHeader', /** * header for major subjects * @param name * @private */ + }, { + key: '_makeHeader', value: function _makeHeader(name) { var div = document.createElement('div'); div.className = 'vis-configuration vis-config-header'; div.innerHTML = name; this._makeItem([], div); } - }, { - key: '_makeLabel', /** * make a label, if it is an object label, it gets different styling. @@ -21766,6 +21681,8 @@ return /******/ (function(modules) { // webpackBootstrap * @returns {HTMLElement} * @private */ + }, { + key: '_makeLabel', value: function _makeLabel(name, path) { var objectLabel = arguments.length <= 2 || arguments[2] === undefined ? false : arguments[2]; @@ -21778,8 +21695,6 @@ return /******/ (function(modules) { // webpackBootstrap } return div; } - }, { - key: '_makeDropdown', /** * make a dropdown list for multiple possible string optoins @@ -21788,6 +21703,8 @@ return /******/ (function(modules) { // webpackBootstrap * @param path * @private */ + }, { + key: '_makeDropdown', value: function _makeDropdown(arr, value, path) { var select = document.createElement('select'); select.className = 'vis-configuration vis-config-select'; @@ -21816,8 +21733,6 @@ return /******/ (function(modules) { // webpackBootstrap var label = this._makeLabel(path[path.length - 1], path); this._makeItem(path, label, select); } - }, { - key: '_makeRange', /** * make a range object for numeric options @@ -21826,6 +21741,8 @@ return /******/ (function(modules) { // webpackBootstrap * @param path * @private */ + }, { + key: '_makeRange', value: function _makeRange(arr, value, path) { var defaultValue = arr[0]; var min = arr[1]; @@ -21886,8 +21803,6 @@ return /******/ (function(modules) { // webpackBootstrap this._setupPopup(popupString, itemIndex); } } - }, { - key: '_setupPopup', /** * prepare the popup @@ -21895,13 +21810,15 @@ return /******/ (function(modules) { // webpackBootstrap * @param index * @private */ + }, { + key: '_setupPopup', value: function _setupPopup(string, index) { var _this3 = this; if (this.initialized === true && this.allowCreation === true && this.popupCounter < this.popupLimit) { - var div = document.createElement('div'); - div.id = 'vis-configuration-popup'; - div.className = 'vis-configuration-popup'; + var div = document.createElement("div"); + div.id = "vis-configuration-popup"; + div.className = "vis-configuration-popup"; div.innerHTML = string; div.onclick = function () { _this3._removePopup(); @@ -21910,13 +21827,13 @@ return /******/ (function(modules) { // webpackBootstrap this.popupDiv = { html: div, index: index }; } } - }, { - key: '_removePopup', /** * remove the popup from the dom * @private */ + }, { + key: '_removePopup', value: function _removePopup() { if (this.popupDiv.html !== undefined) { this.popupDiv.html.parentNode.removeChild(this.popupDiv.html); @@ -21925,21 +21842,21 @@ return /******/ (function(modules) { // webpackBootstrap this.popupDiv = {}; } } - }, { - key: '_showPopupIfNeeded', /** * Show the popup if it is needed. * @private */ + }, { + key: '_showPopupIfNeeded', value: function _showPopupIfNeeded() { var _this4 = this; if (this.popupDiv.html !== undefined) { var correspondingElement = this.domElements[this.popupDiv.index]; var rect = correspondingElement.getBoundingClientRect(); - this.popupDiv.html.style.left = rect.left + 'px'; - this.popupDiv.html.style.top = rect.top - 30 + 'px'; // 30 is the height; + this.popupDiv.html.style.left = rect.left + "px"; + this.popupDiv.html.style.top = rect.top - 30 + "px"; // 30 is the height; document.body.appendChild(this.popupDiv.html); this.popupDiv.hideTimeout = setTimeout(function () { _this4.popupDiv.html.style.opacity = 0; @@ -21949,8 +21866,6 @@ return /******/ (function(modules) { // webpackBootstrap }, 1800); } } - }, { - key: '_makeCheckbox', /** * make a checkbox for boolean options. @@ -21959,6 +21874,8 @@ return /******/ (function(modules) { // webpackBootstrap * @param path * @private */ + }, { + key: '_makeCheckbox', value: function _makeCheckbox(defaultValue, value, path) { var checkbox = document.createElement('input'); checkbox.type = 'checkbox'; @@ -21985,8 +21902,6 @@ return /******/ (function(modules) { // webpackBootstrap var label = this._makeLabel(path[path.length - 1], path); this._makeItem(path, label, checkbox); } - }, { - key: '_makeTextInput', /** * make a text input field for string options. @@ -21995,6 +21910,8 @@ return /******/ (function(modules) { // webpackBootstrap * @param path * @private */ + }, { + key: '_makeTextInput', value: function _makeTextInput(defaultValue, value, path) { var checkbox = document.createElement('input'); checkbox.type = 'text'; @@ -22012,8 +21929,6 @@ return /******/ (function(modules) { // webpackBootstrap var label = this._makeLabel(path[path.length - 1], path); this._makeItem(path, label, checkbox); } - }, { - key: '_makeColorField', /** * make a color field with a color picker for color fields @@ -22022,6 +21937,8 @@ return /******/ (function(modules) { // webpackBootstrap * @param path * @private */ + }, { + key: '_makeColorField', value: function _makeColorField(arr, value, path) { var _this5 = this; @@ -22044,8 +21961,6 @@ return /******/ (function(modules) { // webpackBootstrap var label = this._makeLabel(path[path.length - 1], path); this._makeItem(path, label, div); } - }, { - key: '_showColorPicker', /** * used by the color buttons to call the color picker. @@ -22055,6 +21970,8 @@ return /******/ (function(modules) { // webpackBootstrap * @param path * @private */ + }, { + key: '_showColorPicker', value: function _showColorPicker(value, div, path) { var _this6 = this; @@ -22070,8 +21987,6 @@ return /******/ (function(modules) { // webpackBootstrap _this6._update(colorString, path); }); } - }, { - key: '_handleObject', /** * parse an object and draw the correct items @@ -22079,6 +21994,8 @@ return /******/ (function(modules) { // webpackBootstrap * @param path * @private */ + }, { + key: '_handleObject', value: function _handleObject(obj) { var path = arguments.length <= 1 || arguments[1] === undefined ? [] : arguments[1]; var checkOnly = arguments.length <= 2 || arguments[2] === undefined ? false : arguments[2]; @@ -22149,8 +22066,6 @@ return /******/ (function(modules) { // webpackBootstrap } return visibleInSet; } - }, { - key: '_handleArray', /** * handle the array type of option @@ -22160,6 +22075,8 @@ return /******/ (function(modules) { // webpackBootstrap * @param path * @private */ + }, { + key: '_handleArray', value: function _handleArray(arr, value, path) { if (typeof arr[0] === 'string' && arr[0] === 'color') { this._makeColorField(arr, value, path); @@ -22178,8 +22095,6 @@ return /******/ (function(modules) { // webpackBootstrap } } } - }, { - key: '_update', /** * called to update the network with the new settings. @@ -22187,11 +22102,13 @@ return /******/ (function(modules) { // webpackBootstrap * @param path * @private */ + }, { + key: '_update', value: function _update(value, path) { var options = this._constructOptions(value, path); if (this.parent.body && this.parent.body.emitter && this.parent.body.emitter.emit) { - this.parent.body.emitter.emit('configChange', options); + this.parent.body.emitter.emit("configChange", options); } this.initialized = true; this.parent.setOptions(options); @@ -22285,13 +22202,13 @@ return /******/ (function(modules) { // webpackBootstrap this._create(); } + /** + * this inserts the colorPicker into a div from the DOM + * @param container + */ + _createClass(ColorPicker, [{ key: 'insertTo', - - /** - * this inserts the colorPicker into a div from the DOM - * @param container - */ value: function insertTo(container) { if (this.hammer !== undefined) { this.hammer.destroy(); @@ -22303,18 +22220,18 @@ return /******/ (function(modules) { // webpackBootstrap this._setSize(); } - }, { - key: 'setCallback', /** * the callback is executed on apply and save. Bind it to the application * @param callback */ + }, { + key: 'setCallback', value: function setCallback(callback) { if (typeof callback === 'function') { this.updateCallback = callback; } else { - throw new Error('Function attempted to set as colorPicker callback is not a function.'); + throw new Error("Function attempted to set as colorPicker callback is not a function."); } } }, { @@ -22325,8 +22242,6 @@ return /******/ (function(modules) { // webpackBootstrap return htmlColors[color]; } } - }, { - key: 'setColor', /** * Set the color of the colorPicker @@ -22340,6 +22255,8 @@ return /******/ (function(modules) { // webpackBootstrap * @param color * @param setInitial */ + }, { + key: 'setColor', value: function setColor(color) { var setInitial = arguments.length <= 1 || arguments[1] === undefined ? true : arguments[1]; @@ -22378,19 +22295,19 @@ return /******/ (function(modules) { // webpackBootstrap // set color if (rgba === undefined) { - throw new Error('Unknown color passed to the colorPicker. Supported are strings: rgb, hex, rgba. Object: rgb ({r:r,g:g,b:b,[a:a]}). Supplied: ' + JSON.stringify(color)); + throw new Error("Unknown color passed to the colorPicker. Supported are strings: rgb, hex, rgba. Object: rgb ({r:r,g:g,b:b,[a:a]}). Supplied: " + JSON.stringify(color)); } else { this._setColor(rgba, setInitial); } } - }, { - key: 'show', /** * this shows the color picker at a location. The hue circle is constructed once and stored. * @param x * @param y */ + }, { + key: 'show', value: function show(x, y) { this.applied = false; this.frame.style.display = 'block'; @@ -22398,8 +22315,6 @@ return /******/ (function(modules) { // webpackBootstrap this.frame.style.left = x + 'px'; this._generateHueCircle(); } - }, { - key: '_hide', // ------------------------------------------ PRIVATE ----------------------------- // @@ -22409,6 +22324,8 @@ return /******/ (function(modules) { // webpackBootstrap * @param storePrevious * @private */ + }, { + key: '_hide', value: function _hide() { var storePrevious = arguments.length <= 0 || arguments[0] === undefined ? true : arguments[0]; @@ -22423,46 +22340,44 @@ return /******/ (function(modules) { // webpackBootstrap this.frame.style.display = 'none'; } - }, { - key: '_save', /** * bound to the save button. Saves and hides. * @private */ + }, { + key: '_save', value: function _save() { this.updateCallback(this.color); this.applied = false; this._hide(); } - }, { - key: '_apply', /** * Bound to apply button. Saves but does not close. Is undone by the cancel button. * @private */ + }, { + key: '_apply', value: function _apply() { this.applied = true; this.updateCallback(this.color); this._updatePicker(this.color); } - }, { - key: '_loadLast', /** * load the color from the previous session. * @private */ + }, { + key: '_loadLast', value: function _loadLast() { if (this.previousColor !== undefined) { this.setColor(this.previousColor, false); } else { - alert('There is no last color to load...'); + alert("There is no last color to load..."); } } - }, { - key: '_setColor', /** * set the color, place the picker @@ -22470,6 +22385,8 @@ return /******/ (function(modules) { // webpackBootstrap * @param setInitial * @private */ + }, { + key: '_setColor', value: function _setColor(rgba) { var setInitial = arguments.length <= 1 || arguments[1] === undefined ? true : arguments[1]; @@ -22491,26 +22408,26 @@ return /******/ (function(modules) { // webpackBootstrap this._updatePicker(rgba); } - }, { - key: '_setOpacity', /** * bound to opacity control * @param value * @private */ + }, { + key: '_setOpacity', value: function _setOpacity(value) { this.color.a = value / 100; this._updatePicker(this.color); } - }, { - key: '_setBrightness', /** * bound to brightness control * @param value * @private */ + }, { + key: '_setBrightness', value: function _setBrightness(value) { var hsv = util.RGBToHSV(this.color.r, this.color.g, this.color.b); hsv.v = value / 100; @@ -22519,14 +22436,14 @@ return /******/ (function(modules) { // webpackBootstrap this.color = rgba; this._updatePicker(); } - }, { - key: '_updatePicker', /** * update the colorpicker. A black circle overlays the hue circle to mimic the brightness decreasing. * @param rgba * @private */ + }, { + key: '_updatePicker', value: function _updatePicker() { var rgba = arguments.length <= 0 || arguments[0] === undefined ? this.color : arguments[0]; @@ -22553,13 +22470,13 @@ return /******/ (function(modules) { // webpackBootstrap this.initialColorDiv.style.backgroundColor = 'rgba(' + this.initialColor.r + ',' + this.initialColor.g + ',' + this.initialColor.b + ',' + this.initialColor.a + ')'; this.newColorDiv.style.backgroundColor = 'rgba(' + this.color.r + ',' + this.color.g + ',' + this.color.b + ',' + this.color.a + ')'; } - }, { - key: '_setSize', /** * used by create to set the size of the canvas. * @private */ + }, { + key: '_setSize', value: function _setSize() { this.colorPickerCanvas.style.width = '100%'; this.colorPickerCanvas.style.height = '100%'; @@ -22567,14 +22484,14 @@ return /******/ (function(modules) { // webpackBootstrap this.colorPickerCanvas.width = 289 * this.pixelRatio; this.colorPickerCanvas.height = 289 * this.pixelRatio; } - }, { - key: '_create', /** * create all dom elements * TODO: cleanup, lots of similar dom elements * @private */ + }, { + key: '_create', value: function _create() { this.frame = document.createElement('div'); this.frame.className = 'vis-color-picker'; @@ -22595,10 +22512,10 @@ return /******/ (function(modules) { // webpackBootstrap noCanvas.innerHTML = 'Error: your browser does not support HTML canvas'; this.colorPickerCanvas.appendChild(noCanvas); } else { - var ctx = this.colorPickerCanvas.getContext('2d'); + var ctx = this.colorPickerCanvas.getContext("2d"); this.pixelRatio = (window.devicePixelRatio || 1) / (ctx.webkitBackingStorePixelRatio || ctx.mozBackingStorePixelRatio || ctx.msBackingStorePixelRatio || ctx.oBackingStorePixelRatio || ctx.backingStorePixelRatio || 1); - this.colorPickerCanvas.getContext('2d').setTransform(this.pixelRatio, 0, 0, this.pixelRatio, 0, 0); + this.colorPickerCanvas.getContext("2d").setTransform(this.pixelRatio, 0, 0, this.pixelRatio, 0, 0); } this.colorPickerDiv.className = 'vis-color'; @@ -22647,39 +22564,39 @@ return /******/ (function(modules) { // webpackBootstrap me._setBrightness(this.value); }; - this.brightnessLabel = document.createElement('div'); - this.brightnessLabel.className = 'vis-label vis-brightness'; + this.brightnessLabel = document.createElement("div"); + this.brightnessLabel.className = "vis-label vis-brightness"; this.brightnessLabel.innerHTML = 'brightness:'; - this.opacityLabel = document.createElement('div'); - this.opacityLabel.className = 'vis-label vis-opacity'; + this.opacityLabel = document.createElement("div"); + this.opacityLabel.className = "vis-label vis-opacity"; this.opacityLabel.innerHTML = 'opacity:'; - this.newColorDiv = document.createElement('div'); - this.newColorDiv.className = 'vis-new-color'; + this.newColorDiv = document.createElement("div"); + this.newColorDiv.className = "vis-new-color"; this.newColorDiv.innerHTML = 'new'; - this.initialColorDiv = document.createElement('div'); - this.initialColorDiv.className = 'vis-initial-color'; + this.initialColorDiv = document.createElement("div"); + this.initialColorDiv.className = "vis-initial-color"; this.initialColorDiv.innerHTML = 'initial'; - this.cancelButton = document.createElement('div'); - this.cancelButton.className = 'vis-button vis-cancel'; + this.cancelButton = document.createElement("div"); + this.cancelButton.className = "vis-button vis-cancel"; this.cancelButton.innerHTML = 'cancel'; this.cancelButton.onclick = this._hide.bind(this, false); - this.applyButton = document.createElement('div'); - this.applyButton.className = 'vis-button vis-apply'; + this.applyButton = document.createElement("div"); + this.applyButton.className = "vis-button vis-apply"; this.applyButton.innerHTML = 'apply'; this.applyButton.onclick = this._apply.bind(this); - this.saveButton = document.createElement('div'); - this.saveButton.className = 'vis-button vis-save'; + this.saveButton = document.createElement("div"); + this.saveButton.className = "vis-button vis-save"; this.saveButton.innerHTML = 'save'; this.saveButton.onclick = this._save.bind(this); - this.loadButton = document.createElement('div'); - this.loadButton.className = 'vis-button vis-load'; + this.loadButton = document.createElement("div"); + this.loadButton.className = "vis-button vis-load"; this.loadButton.innerHTML = 'load last'; this.loadButton.onclick = this._loadLast.bind(this); @@ -22697,13 +22614,13 @@ return /******/ (function(modules) { // webpackBootstrap this.frame.appendChild(this.saveButton); this.frame.appendChild(this.loadButton); } - }, { - key: '_bindHammer', /** * bind hammer to the color picker * @private */ + }, { + key: '_bindHammer', value: function _bindHammer() { var _this = this; @@ -22728,13 +22645,13 @@ return /******/ (function(modules) { // webpackBootstrap _this._moveSelector(event); }); } - }, { - key: '_generateHueCircle', /** * generate the hue circle. This is relatively heavy (200ms) and is done only once on the first time it is shown. * @private */ + }, { + key: '_generateHueCircle', value: function _generateHueCircle() { if (this.generated === false) { var ctx = this.colorPickerCanvas.getContext('2d'); @@ -22776,8 +22693,6 @@ return /******/ (function(modules) { // webpackBootstrap } this.generated = true; } - }, { - key: '_moveSelector', /** * move the selector. This is called by hammer functions. @@ -22785,6 +22700,8 @@ return /******/ (function(modules) { // webpackBootstrap * @param event * @private */ + }, { + key: '_moveSelector', value: function _moveSelector(event) { var rect = this.colorPickerDiv.getBoundingClientRect(); var left = event.center.x - rect.left; @@ -22856,15 +22773,15 @@ return /******/ (function(modules) { // webpackBootstrap _classCallCheck(this, Validator); } + /** + * Main function to be called + * @param options + * @param subObject + * @returns {boolean} + */ + _createClass(Validator, null, [{ key: 'validate', - - /** - * Main function to be called - * @param options - * @param subObject - * @returns {boolean} - */ value: function validate(options, referenceOptions, subObject) { errorFound = false; allOptions = referenceOptions; @@ -22875,8 +22792,6 @@ return /******/ (function(modules) { // webpackBootstrap Validator.parse(options, usedOptions, []); return errorFound; } - }, { - key: 'parse', /** * Will traverse an object recursively and check every value @@ -22884,6 +22799,8 @@ return /******/ (function(modules) { // webpackBootstrap * @param referenceOptions * @param path */ + }, { + key: 'parse', value: function parse(options, referenceOptions, path) { for (var option in options) { if (options.hasOwnProperty(option)) { @@ -22891,8 +22808,6 @@ return /******/ (function(modules) { // webpackBootstrap } } } - }, { - key: 'check', /** * Check every value. If the value is an object, call the parse function on that object. @@ -22901,6 +22816,8 @@ return /******/ (function(modules) { // webpackBootstrap * @param referenceOptions * @param path */ + }, { + key: 'check', value: function check(option, options, referenceOptions, path) { if (referenceOptions[option] === undefined && referenceOptions.__any__ === undefined) { Validator.getSuggestion(option, referenceOptions, path); @@ -22922,8 +22839,6 @@ return /******/ (function(modules) { // webpackBootstrap } } } - }, { - key: 'checkFields', /** * @@ -22934,6 +22849,8 @@ return /******/ (function(modules) { // webpackBootstrap * @param {String} refOptionType | This is the type object from the reference options * @param {Array} path | where in the object is the option */ + }, { + key: 'checkFields', value: function checkFields(option, options, referenceOptions, referenceOption, refOptionObj, path) { var optionType = Validator.getType(options[option]); var refOptionType = refOptionObj[optionType]; @@ -22943,11 +22860,11 @@ return /******/ (function(modules) { // webpackBootstrap if (refOptionType.indexOf(options[option]) === -1) { console.log('%cInvalid option detected in "' + option + '".' + ' Allowed values are:' + Validator.print(refOptionType) + ' not "' + options[option] + '". ' + Validator.printLocation(path, option), printStyle); errorFound = true; - } else if (optionType === 'object' && referenceOption !== '__any__') { + } else if (optionType === 'object' && referenceOption !== "__any__") { path = util.copyAndExtendArray(path, option); Validator.parse(options[option], referenceOptions[referenceOption], path); } - } else if (optionType === 'object' && referenceOption !== '__any__') { + } else if (optionType === 'object' && referenceOption !== "__any__") { path = util.copyAndExtendArray(path, option); Validator.parse(options[option], referenceOptions[referenceOption], path); } @@ -23020,8 +22937,6 @@ return /******/ (function(modules) { // webpackBootstrap errorFound = true; } - }, { - key: 'findInOptions', /** * traverse the options in search for a match. @@ -23031,6 +22946,8 @@ return /******/ (function(modules) { // webpackBootstrap * @param recursive * @returns {{closestMatch: string, path: Array, distance: number}} */ + }, { + key: 'findInOptions', value: function findInOptions(option, options, path) { var recursive = arguments.length <= 3 || arguments[3] === undefined ? false : arguments[3]; @@ -23090,10 +23007,8 @@ return /******/ (function(modules) { // webpackBootstrap }, { key: 'print', value: function print(options) { - return JSON.stringify(options).replace(/(\")|(\[)|(\])|(,"__type__")/g, '').replace(/(\,)/g, ', '); + return JSON.stringify(options).replace(/(\")|(\[)|(\])|(,"__type__")/g, "").replace(/(\,)/g, ', '); } - }, { - key: 'levenshteinDistance', // Compute the edit distance between the two given strings // http://en.wikibooks.org/wiki/Algorithm_Implementation/Strings/Levenshtein_distance#JavaScript @@ -23103,6 +23018,8 @@ return /******/ (function(modules) { // webpackBootstrap The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + }, { + key: 'levenshteinDistance', value: function levenshteinDistance(a, b) { if (a.length === 0) return b.length; if (b.length === 0) return a.length; @@ -23381,7 +23298,7 @@ return /******/ (function(modules) { // webpackBootstrap 'use strict'; - var Emitter = __webpack_require__(12); + var Emitter = __webpack_require__(13); var Hammer = __webpack_require__(20); var moment = __webpack_require__(2); var util = __webpack_require__(1); @@ -23597,7 +23514,7 @@ return /******/ (function(modules) { // webpackBootstrap if (this.linegraph.groups[groupId] !== undefined) { return this.linegraph.groups[groupId].getLegend(width, height); } else { - return 'cannot find group:' + groupId; + return "cannot find group:" + groupId; } }; @@ -23914,7 +23831,7 @@ return /******/ (function(modules) { // webpackBootstrap this.updateSVGheight = true; this.updateSVGheightOnResize = true; } else if (this.body.domProps.centerContainer.height !== undefined && options.graphHeight !== undefined) { - if (parseInt((options.graphHeight + '').replace('px', '')) < this.body.domProps.centerContainer.height) { + if (parseInt((options.graphHeight + '').replace("px", '')) < this.body.domProps.centerContainer.height) { this.updateSVGheight = true; } } @@ -24268,7 +24185,7 @@ return /******/ (function(modules) { // webpackBootstrap this.svg.style.left = util.option.asSize(-this.props.width); // if the height of the graph is set as proportional, change the height of the svg - if ((this.options.height + '').indexOf('%') != -1 || this.updateSVGheightOnResize == true) { + if ((this.options.height + '').indexOf("%") != -1 || this.updateSVGheightOnResize == true) { this.updateSVGheight = true; } } @@ -24360,7 +24277,7 @@ return /******/ (function(modules) { // webpackBootstrap return true; } else { if (this.COUNTER > MAX_CYCLES) { - console.log('WARNING: there may be an infinite loop in the _updateGraph emitter cycle.'); + console.log("WARNING: there may be an infinite loop in the _updateGraph emitter cycle."); } this.COUNTER = 0; this.abortedGraphUpdate = false; @@ -24759,7 +24676,7 @@ return /******/ (function(modules) { // webpackBootstrap this.conversionFactor = 1; this.setOptions(options); - this.width = Number(('' + this.options.width).replace('px', '')); + this.width = Number(('' + this.options.width).replace("px", "")); this.minWidth = this.width; this.height = this.linegraphSVG.offsetHeight; this.hidden = false; @@ -24780,7 +24697,7 @@ return /******/ (function(modules) { // webpackBootstrap this._create(); var me = this; - this.body.emitter.on('verticalDrag', function () { + this.body.emitter.on("verticalDrag", function () { me.dom.lineContainer.style.top = me.body.domProps.scrollTop + 'px'; }); } @@ -24814,7 +24731,7 @@ return /******/ (function(modules) { // webpackBootstrap var fields = ['orientation', 'showMinorLabels', 'showMajorLabels', 'icons', 'majorLinesOffset', 'minorLinesOffset', 'labelOffsetX', 'labelOffsetY', 'iconWidth', 'width', 'visible', 'left', 'right', 'alignZeros']; util.selectiveExtend(fields, this.options, options); - this.minWidth = Number(('' + this.options.width).replace('px', '')); + this.minWidth = Number(('' + this.options.width).replace("px", "")); if (redraw === true && this.dom.frame) { this.hide(); @@ -24837,12 +24754,12 @@ return /******/ (function(modules) { // webpackBootstrap this.dom.lineContainer.style.position = 'relative'; // create svg element for graph drawing. - this.svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg'); - this.svg.style.position = 'absolute'; + this.svg = document.createElementNS('http://www.w3.org/2000/svg', "svg"); + this.svg.style.position = "absolute"; this.svg.style.top = '0px'; this.svg.style.height = '100%'; this.svg.style.width = '100%'; - this.svg.style.display = 'block'; + this.svg.style.display = "block"; this.dom.frame.appendChild(this.svg); }; @@ -24956,11 +24873,11 @@ return /******/ (function(modules) { // webpackBootstrap this.hide(); } else { this.show(); - this.height = Number(this.linegraphSVG.style.height.replace('px', '')); + this.height = Number(this.linegraphSVG.style.height.replace("px", "")); // svg offsetheight did not work in firefox and explorer... this.dom.lineContainer.style.height = this.height + 'px'; - this.width = this.options.visible === true ? Number(('' + this.options.width).replace('px', '')) : 0; + this.width = this.options.visible === true ? Number(('' + this.options.width).replace("px", "")) : 0; var props = this.props; var frame = this.dom.frame; @@ -24990,7 +24907,7 @@ return /******/ (function(modules) { // webpackBootstrap frame.style.left = '0'; frame.style.bottom = ''; frame.style.width = this.width + 'px'; - frame.style.height = this.height + 'px'; + frame.style.height = this.height + "px"; this.props.width = this.body.domProps.left.width; this.props.height = this.body.domProps.left.height; } else { @@ -24999,7 +24916,7 @@ return /******/ (function(modules) { // webpackBootstrap frame.style.bottom = '0'; frame.style.left = '0'; frame.style.width = this.width + 'px'; - frame.style.height = this.height + 'px'; + frame.style.height = this.height + "px"; this.props.width = this.body.domProps.right.width; this.props.height = this.body.domProps.right.height; } @@ -25123,7 +25040,7 @@ return /******/ (function(modules) { // webpackBootstrap // this will resize the yAxis to accommodate the labels. if (this.maxLabelSize > this.width - offset && this.options.visible === true) { this.width = this.maxLabelSize + offset; - this.options.width = this.width + 'px'; + this.options.width = this.width + "px"; DOMutil.cleanupElements(this.DOMelements.lines); DOMutil.cleanupElements(this.DOMelements.labels); this.redraw(); @@ -25131,17 +25048,17 @@ return /******/ (function(modules) { // webpackBootstrap } // this will resize the yAxis if it is too big for the labels. else if (this.maxLabelSize < this.width - offset && this.options.visible === true && this.width > this.minWidth) { - this.width = Math.max(this.minWidth, this.maxLabelSize + offset); - this.options.width = this.width + 'px'; - DOMutil.cleanupElements(this.DOMelements.lines); - DOMutil.cleanupElements(this.DOMelements.labels); - this.redraw(); - resized = true; - } else { - DOMutil.cleanupElements(this.DOMelements.lines); - DOMutil.cleanupElements(this.DOMelements.labels); - resized = false; - } + this.width = Math.max(this.minWidth, this.maxLabelSize + offset); + this.options.width = this.width + "px"; + DOMutil.cleanupElements(this.DOMelements.lines); + DOMutil.cleanupElements(this.DOMelements.labels); + this.redraw(); + resized = true; + } else { + DOMutil.cleanupElements(this.DOMelements.lines); + DOMutil.cleanupElements(this.DOMelements.labels); + resized = false; + } return resized; }; @@ -25172,10 +25089,10 @@ return /******/ (function(modules) { // webpackBootstrap label.innerHTML = text; if (orientation === 'left') { label.style.left = '-' + this.options.labelOffsetX + 'px'; - label.style.textAlign = 'right'; + label.style.textAlign = "right"; } else { label.style.right = '-' + this.options.labelOffsetX + 'px'; - label.style.textAlign = 'left'; + label.style.textAlign = "left"; } label.style.top = y - 0.5 * characterHeight + this.options.labelOffsetY + 'px'; @@ -25659,29 +25576,29 @@ return /******/ (function(modules) { // webpackBootstrap var fillHeight = iconHeight * 0.5; var path, fillPath; - var outline = DOMutil.getSVGElement('rect', JSONcontainer, SVGcontainer); - outline.setAttributeNS(null, 'x', x); - outline.setAttributeNS(null, 'y', y - fillHeight); - outline.setAttributeNS(null, 'width', iconWidth); - outline.setAttributeNS(null, 'height', 2 * fillHeight); - outline.setAttributeNS(null, 'class', 'vis-outline'); + var outline = DOMutil.getSVGElement("rect", JSONcontainer, SVGcontainer); + outline.setAttributeNS(null, "x", x); + outline.setAttributeNS(null, "y", y - fillHeight); + outline.setAttributeNS(null, "width", iconWidth); + outline.setAttributeNS(null, "height", 2 * fillHeight); + outline.setAttributeNS(null, "class", "vis-outline"); if (this.options.style == 'line') { - path = DOMutil.getSVGElement('path', JSONcontainer, SVGcontainer); - path.setAttributeNS(null, 'class', this.className); + path = DOMutil.getSVGElement("path", JSONcontainer, SVGcontainer); + path.setAttributeNS(null, "class", this.className); if (this.style !== undefined) { - path.setAttributeNS(null, 'style', 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 + ""); if (this.options.shaded.enabled == true) { - fillPath = DOMutil.getSVGElement('path', JSONcontainer, SVGcontainer); + fillPath = DOMutil.getSVGElement("path", JSONcontainer, SVGcontainer); if (this.options.shaded.orientation == 'top') { - fillPath.setAttributeNS(null, 'd', 'M' + x + ', ' + (y - fillHeight) + 'L' + x + ',' + y + ' L' + (x + iconWidth) + ',' + y + ' L' + (x + iconWidth) + ',' + (y - fillHeight)); + fillPath.setAttributeNS(null, "d", "M" + x + ", " + (y - fillHeight) + "L" + x + "," + y + " L" + (x + iconWidth) + "," + y + " L" + (x + iconWidth) + "," + (y - fillHeight)); } else { - fillPath.setAttributeNS(null, 'd', 'M' + x + ',' + y + ' ' + 'L' + x + ',' + (y + fillHeight) + ' ' + 'L' + (x + iconWidth) + ',' + (y + fillHeight) + 'L' + (x + iconWidth) + ',' + y); + fillPath.setAttributeNS(null, "d", "M" + x + "," + y + " " + "L" + x + "," + (y + fillHeight) + " " + "L" + (x + iconWidth) + "," + (y + fillHeight) + "L" + (x + iconWidth) + "," + y); } - fillPath.setAttributeNS(null, 'class', this.className + ' vis-icon-fill'); + fillPath.setAttributeNS(null, "class", this.className + " vis-icon-fill"); } if (this.options.drawPoints.enabled == true) { @@ -25712,7 +25629,7 @@ return /******/ (function(modules) { // webpackBootstrap * @returns {{icon: HTMLElement, label: (group.content|*|string), orientation: (.options.yAxisOrientation|*)}} */ GraphGroup.prototype.getLegend = function (iconWidth, iconHeight) { - var svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg'); + var svg = document.createElementNS('http://www.w3.org/2000/svg', "svg"); this.drawIcon(0, 0.5 * iconHeight, [], svg, iconWidth, iconHeight); return { icon: svg, label: this.content, orientation: this.options.yAxisOrientation }; }; @@ -25852,9 +25769,9 @@ return /******/ (function(modules) { // webpackBootstrap var path, d; var svgHeight = Number(framework.svg.style.height.replace('px', '')); path = DOMutil.getSVGElement('path', framework.svgElements, framework.svg); - path.setAttributeNS(null, 'class', group.className); + path.setAttributeNS(null, "class", group.className); if (group.style !== undefined) { - path.setAttributeNS(null, 'style', group.style); + path.setAttributeNS(null, "style", group.style); } // construct path from dataset @@ -26433,16 +26350,16 @@ return /******/ (function(modules) { // webpackBootstrap Legend.prototype._create = function () { this.dom.frame = document.createElement('div'); this.dom.frame.className = 'vis-legend'; - this.dom.frame.style.position = 'absolute'; - this.dom.frame.style.top = '10px'; - this.dom.frame.style.display = 'block'; + this.dom.frame.style.position = "absolute"; + this.dom.frame.style.top = "10px"; + this.dom.frame.style.display = "block"; this.dom.textArea = document.createElement('div'); this.dom.textArea.className = 'vis-legend-text'; - this.dom.textArea.style.position = 'relative'; - this.dom.textArea.style.top = '0px'; + this.dom.textArea.style.position = "relative"; + this.dom.textArea.style.top = "0px"; - this.svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg'); + this.svg = document.createElementNS('http://www.w3.org/2000/svg', "svg"); this.svg.style.position = 'absolute'; this.svg.style.top = 0 + 'px'; this.svg.style.width = this.options.iconSize + 5 + 'px'; @@ -26498,16 +26415,16 @@ return /******/ (function(modules) { // webpackBootstrap this.show(); if (this.options[this.side].position == 'top-left' || this.options[this.side].position == 'bottom-left') { this.dom.frame.style.left = '4px'; - this.dom.frame.style.textAlign = 'left'; - this.dom.textArea.style.textAlign = 'left'; + this.dom.frame.style.textAlign = "left"; + this.dom.textArea.style.textAlign = "left"; this.dom.textArea.style.left = this.options.iconSize + 15 + 'px'; this.dom.textArea.style.right = ''; this.svg.style.left = 0 + 'px'; this.svg.style.right = ''; } else { this.dom.frame.style.right = '4px'; - this.dom.frame.style.textAlign = 'right'; - this.dom.textArea.style.textAlign = 'right'; + this.dom.frame.style.textAlign = "right"; + this.dom.textArea.style.textAlign = "right"; this.dom.textArea.style.right = this.options.iconSize + 15 + 'px'; this.dom.textArea.style.left = ''; this.svg.style.right = 0 + 'px'; @@ -26515,11 +26432,11 @@ return /******/ (function(modules) { // webpackBootstrap } if (this.options[this.side].position == 'top-left' || this.options[this.side].position == 'top-right') { - this.dom.frame.style.top = 4 - Number(this.body.dom.center.style.top.replace('px', '')) + 'px'; + this.dom.frame.style.top = 4 - Number(this.body.dom.center.style.top.replace("px", "")) + 'px'; this.dom.frame.style.bottom = ''; } else { var scrollableHeight = this.body.domProps.center.height - this.body.domProps.centerContainer.height; - this.dom.frame.style.bottom = 4 + scrollableHeight + Number(this.body.dom.center.style.top.replace('px', '')) + 'px'; + this.dom.frame.style.bottom = 4 + scrollableHeight + Number(this.body.dom.center.style.top.replace("px", "")) + 'px'; this.dom.frame.style.top = ''; } @@ -26891,19 +26808,19 @@ return /******/ (function(modules) { // webpackBootstrap var _modulesView2 = _interopRequireDefault(_modulesView); - var _modulesInteractionHandler = __webpack_require__(104); + var _modulesInteractionHandler = __webpack_require__(105); var _modulesInteractionHandler2 = _interopRequireDefault(_modulesInteractionHandler); - var _modulesSelectionHandler = __webpack_require__(107); + var _modulesSelectionHandler = __webpack_require__(108); var _modulesSelectionHandler2 = _interopRequireDefault(_modulesSelectionHandler); - var _modulesLayoutEngine = __webpack_require__(108); + var _modulesLayoutEngine = __webpack_require__(109); var _modulesLayoutEngine2 = _interopRequireDefault(_modulesLayoutEngine); - var _modulesManipulationSystem = __webpack_require__(109); + var _modulesManipulationSystem = __webpack_require__(110); var _modulesManipulationSystem2 = _interopRequireDefault(_modulesManipulationSystem); @@ -26915,24 +26832,9 @@ return /******/ (function(modules) { // webpackBootstrap var _sharedValidator2 = _interopRequireDefault(_sharedValidator); - var _optionsJs = __webpack_require__(110); - - var _modulesKamadaKawaiJs = __webpack_require__(111); - - var _modulesKamadaKawaiJs2 = _interopRequireDefault(_modulesKamadaKawaiJs); + var _optionsJs = __webpack_require__(111); - __webpack_require__(113); - - var Emitter = __webpack_require__(12); - var Hammer = __webpack_require__(20); - var util = __webpack_require__(1); - var DataSet = __webpack_require__(8); - var DataView = __webpack_require__(10); - var dotparser = __webpack_require__(114); - var gephiParser = __webpack_require__(115); - var Images = __webpack_require__(116); - var Activator = __webpack_require__(40); - var locales = __webpack_require__(117); + var _modulesKamadaKawaiJs = __webpack_require__(112); /** * @constructor Network @@ -26945,6 +26847,22 @@ return /******/ (function(modules) { // webpackBootstrap * {Array} edges * @param {Object} options Options */ + + var _modulesKamadaKawaiJs2 = _interopRequireDefault(_modulesKamadaKawaiJs); + + __webpack_require__(114); + + var Emitter = __webpack_require__(13); + var Hammer = __webpack_require__(20); + var util = __webpack_require__(1); + var DataSet = __webpack_require__(8); + var DataView = __webpack_require__(10); + var dotparser = __webpack_require__(115); + var gephiParser = __webpack_require__(116); + var Images = __webpack_require__(117); + var Activator = __webpack_require__(40); + var locales = __webpack_require__(118); + function Network(container, data, options) { var _this = this; @@ -27009,7 +26927,7 @@ return /******/ (function(modules) { // webpackBootstrap // setting up all modules this.images = new Images(function () { - return _this.body.emitter.emit('_requestRedraw'); + return _this.body.emitter.emit("_requestRedraw"); }); // object with images this.groups = new _modulesGroups2['default'](); // object with groups this.canvas = new _modulesCanvas2['default'](this.body); // DOM handler @@ -27025,8 +26943,8 @@ return /******/ (function(modules) { // webpackBootstrap this.nodesHandler = new _modulesNodesHandler2['default'](this.body, this.images, this.groups, this.layoutEngine); // Handle adding, deleting and updating of nodes as well as global options this.edgesHandler = new _modulesEdgesHandler2['default'](this.body, this.images, this.groups); // Handle adding, deleting and updating of edges as well as global options - this.body.modules['kamadaKawai'] = new _modulesKamadaKawaiJs2['default'](this.body, 150, 0.05); // Layouting algorithm. - this.body.modules['clustering'] = this.clustering; + this.body.modules["kamadaKawai"] = new _modulesKamadaKawaiJs2['default'](this.body, 150, 0.05); // Layouting algorithm. + this.body.modules["clustering"] = this.clustering; // create the DOM elements this.canvas._create(); @@ -27077,7 +26995,7 @@ return /******/ (function(modules) { // webpackBootstrap // reload the settings of the nodes to apply changes in groups that are not referenced by pointer. if (options.groups !== undefined) { - this.body.emitter.emit('refreshNodes'); + this.body.emitter.emit("refreshNodes"); } // these two do not have options at the moment, here for completeness //this.view.setOptions(options.view); @@ -27118,7 +27036,7 @@ return /******/ (function(modules) { // webpackBootstrap if (this.activator === undefined) { this.activator = new Activator(this.canvas.frame); this.activator.on('change', function () { - _this2.body.emitter.emit('activate'); + _this2.body.emitter.emit("activate"); }); } } else { @@ -27126,15 +27044,15 @@ return /******/ (function(modules) { // webpackBootstrap this.activator.destroy(); delete this.activator; } - this.body.emitter.emit('activate'); + this.body.emitter.emit("activate"); } } else { - this.body.emitter.emit('activate'); + this.body.emitter.emit("activate"); } this.canvas.setSize(); // start the physics simulation. Can be safely called multiple times. - this.body.emitter.emit('startSimulation'); + this.body.emitter.emit("startSimulation"); } }; @@ -27172,23 +27090,23 @@ return /******/ (function(modules) { // webpackBootstrap var _this3 = this; // this event will trigger a rebuilding of the cache everything. Used when nodes or edges have been added or removed. - this.body.emitter.on('_dataChanged', function () { + this.body.emitter.on("_dataChanged", function () { // update shortcut lists _this3._updateVisibleIndices(); _this3.physics.updatePhysicsData(); - _this3.body.emitter.emit('_requestRedraw'); + _this3.body.emitter.emit("_requestRedraw"); // call the dataUpdated event because the only difference between the two is the updating of the indices - _this3.body.emitter.emit('_dataUpdated'); + _this3.body.emitter.emit("_dataUpdated"); }); // this is called when options of EXISTING nodes or edges have changed. - this.body.emitter.on('_dataUpdated', function () { + this.body.emitter.on("_dataUpdated", function () { // update values _this3._updateValueRange(_this3.body.nodes); _this3._updateValueRange(_this3.body.edges); // start simulation (can be called safely, even if already running) - _this3.body.emitter.emit('startSimulation'); - _this3.body.emitter.emit('_requestRedraw'); + _this3.body.emitter.emit("startSimulation"); + _this3.body.emitter.emit("_requestRedraw"); }); }; @@ -27204,8 +27122,8 @@ return /******/ (function(modules) { // webpackBootstrap */ Network.prototype.setData = function (data) { // reset the physics engine. - this.body.emitter.emit('resetPhysics'); - this.body.emitter.emit('_resetData'); + this.body.emitter.emit("resetPhysics"); + this.body.emitter.emit("_resetData"); // unselect all to ensure no selections from old data are carried over. this.selectionHandler.unselectAll(); @@ -27235,13 +27153,13 @@ return /******/ (function(modules) { // webpackBootstrap } // emit change in data - this.body.emitter.emit('_dataChanged'); + this.body.emitter.emit("_dataChanged"); // emit data loaded - this.body.emitter.emit('_dataLoaded'); + this.body.emitter.emit("_dataLoaded"); // find a stable position or start animating to a stable position - this.body.emitter.emit('initPhysics'); + this.body.emitter.emit("initPhysics"); }; /** @@ -27251,7 +27169,7 @@ return /******/ (function(modules) { // webpackBootstrap * network = null; */ Network.prototype.destroy = function () { - this.body.emitter.emit('destroy'); + this.body.emitter.emit("destroy"); // clear events this.body.emitter.off(); this.off(); @@ -27376,7 +27294,7 @@ return /******/ (function(modules) { // webpackBootstrap return this.manipulation.editNode.apply(this.manipulation, arguments); }; Network.prototype.editNodeMode = function () { - console.log('Deprecated: Please use editNode instead of editNodeMode.');return this.manipulation.editNode.apply(this.manipulation, arguments); + console.log("Deprecated: Please use editNode instead of editNodeMode.");return this.manipulation.editNode.apply(this.manipulation, arguments); }; Network.prototype.addEdgeMode = function () { return this.manipulation.addEdgeMode.apply(this.manipulation, arguments); @@ -27546,7 +27464,7 @@ return /******/ (function(modules) { // webpackBootstrap _createClass(Groups, [{ key: "setOptions", value: function setOptions(options) { - var optionFields = ["useDefaultGroups"]; + var optionFields = ['useDefaultGroups']; if (options !== undefined) { for (var groupName in options) { @@ -27559,18 +27477,16 @@ return /******/ (function(modules) { // webpackBootstrap } } } - }, { - key: "clear", /** * Clear all groups */ + }, { + key: "clear", value: function clear() { this.groups = {}; this.groupsArray = []; } - }, { - key: "get", /** * get group options of a groupname. If groupname is not found, a new group @@ -27578,6 +27494,8 @@ return /******/ (function(modules) { // webpackBootstrap * @param {*} groupname Can be a number, string, Date, etc. * @return {Object} group The created group, containing all group options */ + }, { + key: "get", value: function get(groupname) { var group = this.groups[groupname]; if (group === undefined) { @@ -27600,8 +27518,6 @@ return /******/ (function(modules) { // webpackBootstrap return group; } - }, { - key: "add", /** * Add a custom group style @@ -27610,6 +27526,8 @@ return /******/ (function(modules) { // webpackBootstrap * backgroundColor, etc. * @return {Object} group The created group object */ + }, { + key: "add", value: function add(groupName, style) { this.groups[groupName] = style; this.groupsArray.push(groupName); @@ -27820,14 +27738,14 @@ return /******/ (function(modules) { // webpackBootstrap } } } - }, { - key: 'setData', /** * Set a data set with nodes for the network * @param {Array | DataSet | DataView} nodes The data containing the nodes. * @private */ + }, { + key: 'setData', value: function setData(nodes) { var _this3 = this; @@ -27871,17 +27789,17 @@ return /******/ (function(modules) { // webpackBootstrap } if (doNotEmit === false) { - this.body.emitter.emit('_dataChanged'); + this.body.emitter.emit("_dataChanged"); } } - }, { - key: 'add', /** * Add nodes * @param {Number[] | String[]} ids * @private */ + }, { + key: 'add', value: function add(ids) { var doNotEmit = arguments.length <= 1 || arguments[1] === undefined ? false : arguments[1]; @@ -27898,17 +27816,17 @@ return /******/ (function(modules) { // webpackBootstrap this.layoutEngine.positionInitially(newNodes); if (doNotEmit === false) { - this.body.emitter.emit('_dataChanged'); + this.body.emitter.emit("_dataChanged"); } } - }, { - key: 'update', /** * Update existing nodes, or create them when not yet existing * @param {Number[] | String[]} ids * @private */ + }, { + key: 'update', value: function update(ids, changedData) { var nodes = this.body.nodes; var dataChanged = false; @@ -27927,19 +27845,19 @@ return /******/ (function(modules) { // webpackBootstrap } } if (dataChanged === true) { - this.body.emitter.emit('_dataChanged'); + this.body.emitter.emit("_dataChanged"); } else { - this.body.emitter.emit('_dataUpdated'); + this.body.emitter.emit("_dataUpdated"); } } - }, { - key: 'remove', /** * Remove existing nodes. If nodes do not exist, the method will just ignore it. * @param {Number[] | String[]} ids * @private */ + }, { + key: 'remove', value: function remove(ids) { var nodes = this.body.nodes; @@ -27948,16 +27866,16 @@ return /******/ (function(modules) { // webpackBootstrap delete nodes[id]; } - this.body.emitter.emit('_dataChanged'); + this.body.emitter.emit("_dataChanged"); } - }, { - key: 'create', /** * create a node * @param properties * @param constructorClass */ + }, { + key: 'create', value: function create(properties) { var constructorClass = arguments.length <= 1 || arguments[1] === undefined ? _componentsNode2['default'] : arguments[1]; @@ -27984,14 +27902,14 @@ return /******/ (function(modules) { // webpackBootstrap } } } - }, { - key: 'getPositions', /** * Returns the positions of the nodes. * @param ids --> optional, can be array of nodeIds, can be string * @returns {{}} */ + }, { + key: 'getPositions', value: function getPositions(ids) { var dataArray = {}; if (ids !== undefined) { @@ -28016,12 +27934,12 @@ return /******/ (function(modules) { // webpackBootstrap } return dataArray; } - }, { - key: 'storePositions', /** * Load the XY positions of the nodes into the dataset. */ + }, { + key: 'storePositions', value: function storePositions() { // todo: add support for clusters and hierarchical. var dataArray = []; @@ -28037,27 +27955,27 @@ return /******/ (function(modules) { // webpackBootstrap } dataset.update(dataArray); } - }, { - key: 'getBoundingBox', /** * get the bounding box of a node. * @param nodeId * @returns {j|*} */ + }, { + key: 'getBoundingBox', value: function getBoundingBox(nodeId) { if (this.body.nodes[nodeId] !== undefined) { return this.body.nodes[nodeId].shape.boundingBox; } } - }, { - key: 'getConnectedNodes', /** * Get the Ids of nodes connected to this node. * @param nodeId * @returns {Array} */ + }, { + key: 'getConnectedNodes', value: function getConnectedNodes(nodeId) { var nodeList = []; if (this.body.nodes[nodeId] !== undefined) { @@ -28082,14 +28000,14 @@ return /******/ (function(modules) { // webpackBootstrap } return nodeList; } - }, { - key: 'getConnectedEdges', /** * Get the ids of the edges connected to this node. * @param nodeId * @returns {*} */ + }, { + key: 'getConnectedEdges', value: function getConnectedEdges(nodeId) { var edgeList = []; if (this.body.nodes[nodeId] !== undefined) { @@ -28098,12 +28016,10 @@ return /******/ (function(modules) { // webpackBootstrap edgeList.push(node.edges[i].id); } } else { - console.log('NodeId provided for getConnectedEdges does not exist. Provided: ', nodeId); + console.log("NodeId provided for getConnectedEdges does not exist. Provided: ", nodeId); } return edgeList; } - }, { - key: 'moveNode', /** * Move a node. @@ -28111,6 +28027,8 @@ return /******/ (function(modules) { // webpackBootstrap * @param Number x * @param Number y */ + }, { + key: 'moveNode', value: function moveNode(nodeId, x, y) { var _this4 = this; @@ -28118,10 +28036,10 @@ return /******/ (function(modules) { // webpackBootstrap this.body.nodes[nodeId].x = Number(x); this.body.nodes[nodeId].y = Number(y); setTimeout(function () { - _this4.body.emitter.emit('startSimulation'); + _this4.body.emitter.emit("startSimulation"); }, 0); } else { - console.log('Node id supplied to moveNode does not exist. Provided: ', nodeId); + console.log("Node id supplied to moveNode does not exist. Provided: ", nodeId); } } }]); @@ -28267,39 +28185,39 @@ return /******/ (function(modules) { // webpackBootstrap this.setOptions(options); } + /** + * Attach a edge to the node + * @param {Edge} edge + */ + _createClass(Node, [{ key: 'attachEdge', - - /** - * Attach a edge to the node - * @param {Edge} edge - */ value: function attachEdge(edge) { if (this.edges.indexOf(edge) === -1) { this.edges.push(edge); } } - }, { - key: 'detachEdge', /** * Detach a edge from the node * @param {Edge} edge */ + }, { + key: 'detachEdge', value: function detachEdge(edge) { var index = this.edges.indexOf(edge); if (index != -1) { this.edges.splice(index, 1); } } - }, { - key: 'setOptions', /** * Set or overwrite options for the node * @param {Object} options an object with options * @param {Object} constants and object with default, global options */ + }, { + key: 'setOptions', value: function setOptions(options) { var currentShape = this.options.shape; if (!options) { @@ -28311,7 +28229,7 @@ return /******/ (function(modules) { // webpackBootstrap } if (this.id === undefined) { - throw 'Node must have an id'; + throw "Node must have an id"; } // set these options locally @@ -28353,7 +28271,7 @@ return /******/ (function(modules) { // webpackBootstrap if (this.imagelist) { this.imageObj = this.imagelist.load(this.options.image, this.options.brokenImage, this.id); } else { - throw 'No imagelist provided'; + throw "No imagelist provided"; } } @@ -28365,6 +28283,13 @@ return /******/ (function(modules) { // webpackBootstrap } return false; } + + /** + * This process all possible shorthands in the new options and makes sure that the parentOptions are fully defined. + * Static so it can also be used by the handler. + * @param parentOptions + * @param newOptions + */ }, { key: 'updateLabelModule', value: function updateLabelModule() { @@ -28433,50 +28358,48 @@ return /******/ (function(modules) { // webpackBootstrap } this._reset(); } - }, { - key: 'select', /** * select this node */ + }, { + key: 'select', value: function select() { this.selected = true; this._reset(); } - }, { - key: 'unselect', /** * unselect this node */ + }, { + key: 'unselect', value: function unselect() { this.selected = false; this._reset(); } - }, { - key: '_reset', /** * Reset the calculated size of the node, forces it to recalculate its size * @private */ + }, { + key: '_reset', value: function _reset() { this.shape.width = undefined; this.shape.height = undefined; } - }, { - key: 'getTitle', /** * get the title of this node. * @return {string} title The title of the node, or undefined when no title * has been set. */ + }, { + key: 'getTitle', value: function getTitle() { return this.options.title; } - }, { - key: 'distanceToBorder', /** * Calculate the distance to the border of the Node @@ -28484,41 +28407,41 @@ return /******/ (function(modules) { // webpackBootstrap * @param {Number} angle Angle in radians * @returns {number} distance Distance to the border in pixels */ + }, { + key: 'distanceToBorder', value: function distanceToBorder(ctx, angle) { return this.shape.distanceToBorder(ctx, angle); } - }, { - key: 'isFixed', /** * Check if this node has a fixed x and y position * @return {boolean} true if fixed, false if not */ + }, { + key: 'isFixed', value: function isFixed() { return this.options.fixed.x && this.options.fixed.y; } - }, { - key: 'isSelected', /** * check if this node is selecte * @return {boolean} selected True if node is selected, else false */ + }, { + key: 'isSelected', value: function isSelected() { return this.selected; } - }, { - key: 'getValue', /** * Retrieve the value of the node. Can be undefined * @return {Number} value */ + }, { + key: 'getValue', value: function getValue() { return this.options.value; } - }, { - key: 'setValueRange', /** * Adjust the value range of the node. The node will adjust it's size @@ -28526,6 +28449,8 @@ return /******/ (function(modules) { // webpackBootstrap * @param {Number} min * @param {Number} max */ + }, { + key: 'setValueRange', value: function setValueRange(min, max, total) { if (this.options.value !== undefined) { var scale = this.options.scaling.customScalingFunction(min, max, total, this.options.value); @@ -28540,68 +28465,61 @@ return /******/ (function(modules) { // webpackBootstrap this.options.font.size = this.baseFontSize; } } - }, { - key: 'draw', /** * Draw this node in the given canvas * The 2d context of a HTML canvas can be retrieved by canvas.getContext("2d"); * @param {CanvasRenderingContext2D} ctx */ + }, { + key: 'draw', value: function draw(ctx) { this.shape.draw(ctx, this.x, this.y, this.selected, this.hover); } - }, { - key: 'updateBoundingBox', /** * Update the bounding box of the shape */ + }, { + key: 'updateBoundingBox', value: function updateBoundingBox(ctx) { this.shape.updateBoundingBox(this.x, this.y, ctx); } - }, { - key: 'resize', /** * Recalculate the size of this node in the given canvas * The 2d context of a HTML canvas can be retrieved by canvas.getContext("2d"); * @param {CanvasRenderingContext2D} ctx */ + }, { + key: 'resize', value: function resize(ctx) { this.shape.resize(ctx, this.selected); } - }, { - key: 'isOverlappingWith', /** * Check if this object is overlapping with the provided object * @param {Object} obj an object with parameters left, top, right, bottom * @return {boolean} True if location is located on node */ + }, { + key: 'isOverlappingWith', value: function isOverlappingWith(obj) { return this.shape.left < obj.right && this.shape.left + this.shape.width > obj.left && this.shape.top < obj.bottom && this.shape.top + this.shape.height > obj.top; } - }, { - key: 'isBoundingBoxOverlappingWith', /** * Check if this object is overlapping with the provided object * @param {Object} obj an object with parameters left, top, right, bottom * @return {boolean} True if location is located on node */ + }, { + key: 'isBoundingBoxOverlappingWith', value: function isBoundingBoxOverlappingWith(obj) { return this.shape.boundingBox.left < obj.right && this.shape.boundingBox.right > obj.left && this.shape.boundingBox.top < obj.bottom && this.shape.boundingBox.bottom > obj.top; } }], [{ key: 'parseOptions', - - /** - * This process all possible shorthands in the new options and makes sure that the parentOptions are fully defined. - * Static so it can also be used by the handler. - * @param parentOptions - * @param newOptions - */ value: function parseOptions(parentOptions, newOptions) { var allowDeletion = arguments.length <= 2 || arguments[2] === undefined ? false : arguments[2]; @@ -28739,16 +28657,16 @@ return /******/ (function(modules) { // webpackBootstrap // draw text this._drawText(ctx, selected, x, y, baseline); } - }, { - key: '_drawBackground', /** * Draws the label background * @param {CanvasRenderingContext2D} ctx * @private */ + }, { + key: '_drawBackground', value: function _drawBackground(ctx) { - if (this.fontOptions.background !== undefined && this.fontOptions.background !== 'none') { + if (this.fontOptions.background !== undefined && this.fontOptions.background !== "none") { ctx.fillStyle = this.fontOptions.background; var lineMargin = 2; @@ -28769,8 +28687,6 @@ return /******/ (function(modules) { // webpackBootstrap } } } - }, { - key: '_drawText', /** * @@ -28779,6 +28695,8 @@ return /******/ (function(modules) { // webpackBootstrap * @param baseline * @private */ + }, { + key: '_drawText', value: function _drawText(ctx, selected, x, y) { var baseline = arguments.length <= 4 || arguments[4] === undefined ? 'middle' : arguments[4]; @@ -28798,15 +28716,15 @@ return /******/ (function(modules) { // webpackBootstrap var fontColor = _getColor22[0]; var strokeColor = _getColor22[1]; + // configure context for drawing the text + var _setAlignment2 = this._setAlignment(ctx, x, yLine, baseline); var _setAlignment22 = _slicedToArray(_setAlignment2, 2); x = _setAlignment22[0]; yLine = _setAlignment22[1]; - - // configure context for drawing the text - ctx.font = (selected && this.nodeOptions.labelHighlightBold ? 'bold ' : '') + fontSize + 'px ' + this.fontOptions.face; + ctx.font = (selected && this.nodeOptions.labelHighlightBold ? 'bold ' : '') + fontSize + "px " + this.fontOptions.face; ctx.fillStyle = fontColor; ctx.textAlign = 'center'; @@ -28840,19 +28758,17 @@ return /******/ (function(modules) { // webpackBootstrap ctx.textBaseline = 'alphabetic'; yLine -= 2 * lineMargin; // distance from edge, required because we use alphabetic. Alphabetic has less difference between browsers } else if (this.fontOptions.align === 'bottom') { - ctx.textBaseline = 'hanging'; - yLine += 2 * lineMargin; // distance from edge, required because we use hanging. Hanging has less difference between browsers - } else { - ctx.textBaseline = 'middle'; - } + ctx.textBaseline = 'hanging'; + yLine += 2 * lineMargin; // distance from edge, required because we use hanging. Hanging has less difference between browsers + } else { + ctx.textBaseline = 'middle'; + } } else { ctx.textBaseline = baseline; } return [x, yLine]; } - }, { - key: '_getColor', /** * fade in when relative scale is between threshold and threshold - 1. @@ -28862,6 +28778,8 @@ return /******/ (function(modules) { // webpackBootstrap * @returns {*[]} * @private */ + }, { + key: '_getColor', value: function _getColor(viewFontSize) { var fontColor = this.fontOptions.color || '#000000'; var strokeColor = this.fontOptions.strokeColor || '#ffffff'; @@ -28872,8 +28790,6 @@ return /******/ (function(modules) { // webpackBootstrap } return [fontColor, strokeColor]; } - }, { - key: 'getTextSize', /** * @@ -28881,6 +28797,8 @@ return /******/ (function(modules) { // webpackBootstrap * @param selected * @returns {{width: number, height: number}} */ + }, { + key: 'getTextSize', value: function getTextSize(ctx) { var selected = arguments.length <= 1 || arguments[1] === undefined ? false : arguments[1]; @@ -28891,8 +28809,6 @@ return /******/ (function(modules) { // webpackBootstrap }; return size; } - }, { - key: 'calculateLabelSize', /** * @@ -28902,6 +28818,8 @@ return /******/ (function(modules) { // webpackBootstrap * @param y * @param baseline */ + }, { + key: 'calculateLabelSize', value: function calculateLabelSize(ctx, selected) { var x = arguments.length <= 2 || arguments[2] === undefined ? 0 : arguments[2]; var y = arguments.length <= 3 || arguments[3] === undefined ? 0 : arguments[3]; @@ -28914,7 +28832,7 @@ return /******/ (function(modules) { // webpackBootstrap this.size.left = x - this.size.width * 0.5; this.size.top = y - this.size.height * 0.5; this.size.yLine = y + (1 - this.lineCount) * 0.5 * this.fontOptions.size; - if (baseline === 'hanging') { + if (baseline === "hanging") { this.size.top += 0.5 * this.fontOptions.size; this.size.top += 4; // distance from node, required because we use hanging. Hanging has less difference between browsers this.size.yLine += 4; // distance from node @@ -28922,8 +28840,6 @@ return /******/ (function(modules) { // webpackBootstrap this.labelDirty = false; } - }, { - key: '_processLabel', /** * This calculates the width as well as explodes the label string and calculates the amount of lines. @@ -28932,6 +28848,8 @@ return /******/ (function(modules) { // webpackBootstrap * @returns {number} * @private */ + }, { + key: '_processLabel', value: function _processLabel(ctx, selected) { var width = 0; var lines = ['']; @@ -28939,7 +28857,7 @@ return /******/ (function(modules) { // webpackBootstrap if (this.nodeOptions.label !== undefined) { lines = String(this.nodeOptions.label).split('\n'); lineCount = lines.length; - ctx.font = (selected && this.nodeOptions.labelHighlightBold ? 'bold ' : '') + this.fontOptions.size + 'px ' + this.fontOptions.face; + ctx.font = (selected && this.nodeOptions.labelHighlightBold ? 'bold ' : '') + this.fontOptions.size + "px " + this.fontOptions.face; width = ctx.measureText(lines[0]).width; for (var i = 1; i < lineCount; i++) { var lineWidth = ctx.measureText(lines[i]).width; @@ -28957,8 +28875,8 @@ return /******/ (function(modules) { // webpackBootstrap var allowDeletion = arguments.length <= 2 || arguments[2] === undefined ? false : arguments[2]; if (typeof newOptions.font === 'string') { - var newOptionsArray = newOptions.font.split(' '); - parentOptions.size = newOptionsArray[0].replace('px', ''); + var newOptionsArray = newOptions.font.split(" "); + parentOptions.size = newOptionsArray[0].replace("px", ''); parentOptions.face = newOptionsArray[1]; parentOptions.color = newOptionsArray[2]; } else if (typeof newOptions.font === 'object') { @@ -29157,7 +29075,7 @@ return /******/ (function(modules) { // webpackBootstrap } ctx.setLineDash(dashes); } else { - console.warn('setLineDash is not supported in this browser. The dashed borders cannot be used.'); + console.warn("setLineDash is not supported in this browser. The dashed borders cannot be used."); this.options.shapeProperties.borderDashes = false; } } @@ -29169,7 +29087,7 @@ return /******/ (function(modules) { // webpackBootstrap if (ctx.setLineDash !== undefined) { ctx.setLineDash([0]); } else { - console.warn('setLineDash is not supported in this browser. The dashed borders cannot be used.'); + console.warn("setLineDash is not supported in this browser. The dashed borders cannot be used."); this.options.shapeProperties.borderDashes = false; } } @@ -29315,8 +29233,6 @@ return /******/ (function(modules) { // webpackBootstrap this.imageObj = imageObj; } } - }, { - key: '_resizeImage', /** * This function resizes the image by the options size when the image has not yet loaded. If the image has loaded, we @@ -29324,6 +29240,8 @@ return /******/ (function(modules) { // webpackBootstrap * * @private */ + }, { + key: '_resizeImage', value: function _resizeImage() { var force = false; if (!this.imageObj.width || !this.imageObj.height) { @@ -30081,12 +29999,12 @@ return /******/ (function(modules) { // webpackBootstrap var iconSize = Number(this.options.icon.size); if (this.options.icon.code !== undefined) { - ctx.font = (selected ? 'bold ' : '') + iconSize + 'px ' + this.options.icon.face; + ctx.font = (selected ? "bold " : "") + iconSize + "px " + this.options.icon.face; // draw icon - ctx.fillStyle = this.options.icon.color || 'black'; - ctx.textAlign = 'center'; - ctx.textBaseline = 'middle'; + ctx.fillStyle = this.options.icon.color || "black"; + ctx.textAlign = "center"; + ctx.textBaseline = "middle"; // draw shadow if enabled this.enableShadow(ctx); @@ -30624,7 +30542,7 @@ return /******/ (function(modules) { // webpackBootstrap }, smooth: { enabled: true, - type: 'dynamic', + type: "dynamic", forceDirection: 'none', roundness: 0.5 }, @@ -30644,7 +30562,7 @@ return /******/ (function(modules) { // webpackBootstrap var _this2 = this; // this allows external modules to force all dynamic curves to turn static. - this.body.emitter.on('_forceDisableDynamicCurves', function (type) { + this.body.emitter.on("_forceDisableDynamicCurves", function (type) { if (type === 'dynamic') { type = 'continuous'; } @@ -30672,20 +30590,20 @@ return /******/ (function(modules) { // webpackBootstrap } } if (emitChange === true) { - _this2.body.emitter.emit('_dataChanged'); + _this2.body.emitter.emit("_dataChanged"); } }); // this is called when options of EXISTING nodes or edges have changed. - this.body.emitter.on('_dataUpdated', function () { + this.body.emitter.on("_dataUpdated", function () { _this2.reconnectEdges(); _this2.markAllEdgesAsDirty(); }); // refresh the edges. Used when reverting from hierarchical layout - this.body.emitter.on('refreshEdges', this.refresh.bind(this)); - this.body.emitter.on('refresh', this.refresh.bind(this)); - this.body.emitter.on('destroy', function () { + this.body.emitter.on("refreshEdges", this.refresh.bind(this)); + this.body.emitter.on("refresh", this.refresh.bind(this)); + this.body.emitter.on("destroy", function () { delete _this2.body.functions.createEdge; delete _this2.edgesListeners.add; delete _this2.edgesListeners.update; @@ -30732,8 +30650,6 @@ return /******/ (function(modules) { // webpackBootstrap } } } - }, { - key: 'setData', /** * Load edges by reading the data table @@ -30741,6 +30657,8 @@ return /******/ (function(modules) { // webpackBootstrap * @private * @private */ + }, { + key: 'setData', value: function setData(edges) { var _this3 = this; @@ -30783,17 +30701,17 @@ return /******/ (function(modules) { // webpackBootstrap } if (doNotEmit === false) { - this.body.emitter.emit('_dataChanged'); + this.body.emitter.emit("_dataChanged"); } } - }, { - key: 'add', /** * Add edges * @param {Number[] | String[]} ids * @private */ + }, { + key: 'add', value: function add(ids) { var doNotEmit = arguments.length <= 1 || arguments[1] === undefined ? false : arguments[1]; @@ -30808,22 +30726,22 @@ return /******/ (function(modules) { // webpackBootstrap oldEdge.disconnect(); } - var data = edgesData.get(id, { 'showInternalIds': true }); + var data = edgesData.get(id, { "showInternalIds": true }); edges[id] = this.create(data); } if (doNotEmit === false) { - this.body.emitter.emit('_dataChanged'); + this.body.emitter.emit("_dataChanged"); } } - }, { - key: 'update', /** * Update existing edges, or create them when not yet existing * @param {Number[] | String[]} ids * @private */ + }, { + key: 'update', value: function update(ids) { var edges = this.body.edges; var edgesData = this.body.data.edges; @@ -30845,19 +30763,19 @@ return /******/ (function(modules) { // webpackBootstrap } if (dataChanged === true) { - this.body.emitter.emit('_dataChanged'); + this.body.emitter.emit("_dataChanged"); } else { - this.body.emitter.emit('_dataUpdated'); + this.body.emitter.emit("_dataUpdated"); } } - }, { - key: 'remove', /** * Remove existing edges. Non existing ids will be ignored * @param {Number[] | String[]} ids * @private */ + }, { + key: 'remove', value: function remove(ids) { var edges = this.body.edges; for (var i = 0; i < ids.length; i++) { @@ -30870,7 +30788,7 @@ return /******/ (function(modules) { // webpackBootstrap } } - this.body.emitter.emit('_dataChanged'); + this.body.emitter.emit("_dataChanged"); } }, { key: 'refresh', @@ -30899,13 +30817,13 @@ return /******/ (function(modules) { // webpackBootstrap this.body.edges[edgeId].edgeType.colorDirty = true; } } - }, { - key: 'reconnectEdges', /** * Reconnect all edges * @private */ + }, { + key: 'reconnectEdges', value: function reconnectEdges() { var id; var nodes = this.body.nodes; @@ -30969,24 +30887,20 @@ return /******/ (function(modules) { // webpackBootstrap var _sharedLabel2 = _interopRequireDefault(_sharedLabel); - var _edgesCubicBezierEdge = __webpack_require__(83); + var _edgesCubicBezierEdge = __webpack_require__(86); var _edgesCubicBezierEdge2 = _interopRequireDefault(_edgesCubicBezierEdge); - var _edgesBezierEdgeDynamic = __webpack_require__(87); + var _edgesBezierEdgeDynamic = __webpack_require__(88); var _edgesBezierEdgeDynamic2 = _interopRequireDefault(_edgesBezierEdgeDynamic); - var _edgesBezierEdgeStatic = __webpack_require__(88); + var _edgesBezierEdgeStatic = __webpack_require__(83); var _edgesBezierEdgeStatic2 = _interopRequireDefault(_edgesBezierEdgeStatic); var _edgesStraightEdge = __webpack_require__(89); - var _edgesStraightEdge2 = _interopRequireDefault(_edgesStraightEdge); - - var util = __webpack_require__(1); - /** * @class Edge * @@ -31003,12 +30917,16 @@ return /******/ (function(modules) { // webpackBootstrap * example for the color */ + var _edgesStraightEdge2 = _interopRequireDefault(_edgesStraightEdge); + + var util = __webpack_require__(1); + var Edge = (function () { function Edge(options, body, globalOptions) { _classCallCheck(this, Edge); if (body === undefined) { - throw 'No body provided'; + throw "No body provided"; } this.options = util.bridgeObject(globalOptions); this.body = body; @@ -31037,14 +30955,14 @@ return /******/ (function(modules) { // webpackBootstrap this.setOptions(options); } + /** + * Set or overwrite options for the edge + * @param {Object} options an object with options + * @param doNotEmit + */ + _createClass(Edge, [{ key: 'setOptions', - - /** - * Set or overwrite options for the edge - * @param {Object} options an object with options - * @param doNotEmit - */ value: function setOptions(options) { if (!options) { return; @@ -31098,13 +31016,13 @@ return /******/ (function(modules) { // webpackBootstrap this.baseFontSize = this.labelModule.baseSize; } } - }, { - key: 'updateEdgeType', /** * update the edge type, set the options * @returns {boolean} */ + }, { + key: 'updateEdgeType', value: function updateEdgeType() { var dataChanged = false; var changeInType = true; @@ -31148,12 +31066,12 @@ return /******/ (function(modules) { // webpackBootstrap return dataChanged; } - }, { - key: 'connect', /** * Connect an edge to its nodes */ + }, { + key: 'connect', value: function connect() { this.disconnect(); @@ -31175,12 +31093,12 @@ return /******/ (function(modules) { // webpackBootstrap this.edgeType.connect(); } - }, { - key: 'disconnect', /** * Disconnect an edge from its nodes */ + }, { + key: 'disconnect', value: function disconnect() { if (this.from) { this.from.detachEdge(this); @@ -31193,39 +31111,37 @@ return /******/ (function(modules) { // webpackBootstrap this.connected = false; } - }, { - key: 'getTitle', /** * get the title of this edge. * @return {string} title The title of the edge, or undefined when no title * has been set. */ + }, { + key: 'getTitle', value: function getTitle() { return this.title; } - }, { - key: 'isSelected', /** * check if this node is selecte * @return {boolean} selected True if node is selected, else false */ + }, { + key: 'isSelected', value: function isSelected() { return this.selected; } - }, { - key: 'getValue', /** * Retrieve the value of the edge. Can be undefined * @return {Number} value */ + }, { + key: 'getValue', value: function getValue() { return this.options.value; } - }, { - key: 'setValueRange', /** * Adjust the value range of the edge. The edge will adjust it's width @@ -31234,6 +31150,8 @@ return /******/ (function(modules) { // webpackBootstrap * @param {Number} max * @param total */ + }, { + key: 'setValueRange', value: function setValueRange(min, max, total) { if (this.options.value !== undefined) { var scale = this.options.scaling.customScalingFunction(min, max, total, this.options.value); @@ -31265,8 +31183,6 @@ return /******/ (function(modules) { // webpackBootstrap this.edgeType.selectionWidth = this.options.selectionWidth + this.options.width; } } - }, { - key: 'draw', /** * Redraw a edge @@ -31274,6 +31190,8 @@ return /******/ (function(modules) { // webpackBootstrap * The 2d context of a HTML canvas can be retrieved by canvas.getContext("2d"); * @param {CanvasRenderingContext2D} ctx */ + }, { + key: 'draw', value: function draw(ctx) { var via = this.edgeType.drawLine(ctx, this.selected, this.hover); this.drawArrows(ctx, via); @@ -31306,7 +31224,7 @@ return /******/ (function(modules) { // webpackBootstrap ctx.save(); // if the label has to be rotated: - if (this.options.font.align !== 'horizontal') { + if (this.options.font.align !== "horizontal") { this.labelModule.calculateLabelSize(ctx, selected, point.x, point.y); ctx.translate(point.x, this.labelModule.size.yLine); this._rotateForLabelAlignment(ctx); @@ -31332,14 +31250,14 @@ return /******/ (function(modules) { // webpackBootstrap } } } - }, { - key: 'isOverlappingWith', /** * Check if this object is overlapping with the provided object * @param {Object} obj an object with parameters left, top * @return {boolean} True if location is located on the edge */ + }, { + key: 'isOverlappingWith', value: function isOverlappingWith(obj) { if (this.connected) { var distMax = 10; @@ -31357,14 +31275,14 @@ return /******/ (function(modules) { // webpackBootstrap return false; } } - }, { - key: '_rotateForLabelAlignment', /** * Rotates the canvas so the text is most readable * @param {CanvasRenderingContext2D} ctx * @private */ + }, { + key: '_rotateForLabelAlignment', value: function _rotateForLabelAlignment(ctx) { var dy = this.from.y - this.to.y; var dx = this.from.x - this.to.x; @@ -31377,8 +31295,6 @@ return /******/ (function(modules) { // webpackBootstrap ctx.rotate(angleInDegrees); } - }, { - key: '_pointOnCircle', /** * Get a point on a circle @@ -31389,6 +31305,8 @@ return /******/ (function(modules) { // webpackBootstrap * @return {Object} point * @private */ + }, { + key: '_pointOnCircle', value: function _pointOnCircle(x, y, radius, percentage) { var angle = percentage * 2 * Math.PI; return { @@ -31406,13 +31324,13 @@ return /******/ (function(modules) { // webpackBootstrap value: function unselect() { this.selected = false; } - }, { - key: 'cleanup', /** * cleans all required things on delete * @returns {*} */ + }, { + key: 'cleanup', value: function cleanup() { return this.edgeType.cleanup(); } @@ -31454,13 +31372,13 @@ return /******/ (function(modules) { // webpackBootstrap if (newOptions.arrows !== undefined && newOptions.arrows !== null) { if (typeof newOptions.arrows === 'string') { var arrows = newOptions.arrows.toLowerCase(); - if (arrows.indexOf('to') != -1) { + if (arrows.indexOf("to") != -1) { parentOptions.arrows.to.enabled = true; } - if (arrows.indexOf('middle') != -1) { + if (arrows.indexOf("middle") != -1) { parentOptions.arrows.middle.enabled = true; } - if (arrows.indexOf('from') != -1) { + if (arrows.indexOf("from") != -1) { parentOptions.arrows.from.enabled = true; } } else if (typeof newOptions.arrows === 'object') { @@ -31468,7 +31386,7 @@ return /******/ (function(modules) { // webpackBootstrap util.mergeOptions(parentOptions.arrows, newOptions.arrows, 'middle'); util.mergeOptions(parentOptions.arrows, newOptions.arrows, 'from'); } else { - throw new Error('The arrow newOptions can only be an object or a string. Refer to the documentation. You used:' + JSON.stringify(newOptions.arrows)); + throw new Error("The arrow newOptions can only be an object or a string. Refer to the documentation. You used:" + JSON.stringify(newOptions.arrows)); } } else if (allowDeletion === true && newOptions.arrows === null) { parentOptions.arrows = undefined; @@ -31532,11 +31450,9 @@ return /******/ (function(modules) { // webpackBootstrap value: true }); - var _slicedToArray = (function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i['return']) _i['return'](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError('Invalid attempt to destructure non-iterable instance'); } }; })(); - 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 _get = function get(_x3, _x4, _x5) { var _again = true; _function: while (_again) { var object = _x3, property = _x4, receiver = _x5; desc = parent = getter = undefined; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x3 = parent; _x4 = property; _x5 = receiver; _again = true; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; + var _get = function get(_x4, _x5, _x6) { var _again = true; _function: while (_again) { var object = _x4, property = _x5, receiver = _x6; desc = parent = getter = undefined; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x4 = parent; _x5 = property; _x6 = receiver; _again = true; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } @@ -31544,49 +31460,40 @@ return /******/ (function(modules) { // webpackBootstrap function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; } - var _utilCubicBezierEdgeBase = __webpack_require__(84); + var _utilBezierEdgeBase = __webpack_require__(84); - var _utilCubicBezierEdgeBase2 = _interopRequireDefault(_utilCubicBezierEdgeBase); + var _utilBezierEdgeBase2 = _interopRequireDefault(_utilBezierEdgeBase); - var CubicBezierEdge = (function (_CubicBezierEdgeBase) { - _inherits(CubicBezierEdge, _CubicBezierEdgeBase); + var BezierEdgeStatic = (function (_BezierEdgeBase) { + _inherits(BezierEdgeStatic, _BezierEdgeBase); - function CubicBezierEdge(options, body, labelModule) { - _classCallCheck(this, CubicBezierEdge); + function BezierEdgeStatic(options, body, labelModule) { + _classCallCheck(this, BezierEdgeStatic); - _get(Object.getPrototypeOf(CubicBezierEdge.prototype), 'constructor', this).call(this, options, body, labelModule); + _get(Object.getPrototypeOf(BezierEdgeStatic.prototype), 'constructor', this).call(this, options, body, labelModule); } - _createClass(CubicBezierEdge, [{ - key: '_line', + /** + * Draw a line between two nodes + * @param {CanvasRenderingContext2D} ctx + * @private + */ - /** - * Draw a line between two nodes - * @param {CanvasRenderingContext2D} ctx - * @private - */ + _createClass(BezierEdgeStatic, [{ + key: '_line', value: function _line(ctx) { - // get the coordinates of the support points. - - var _getViaCoordinates2 = this._getViaCoordinates(); - - var _getViaCoordinates22 = _slicedToArray(_getViaCoordinates2, 2); - - var via1 = _getViaCoordinates22[0]; - var via2 = _getViaCoordinates22[1]; - - var returnValue = [via1, via2]; - - // start drawing the line. + // draw a straight line ctx.beginPath(); ctx.moveTo(this.from.x, this.from.y); + var via = this._getViaCoordinates(); + var returnValue = via; // fallback to normal straight edges - if (via1.x === undefined) { + if (via.x === undefined) { ctx.lineTo(this.to.x, this.to.y); returnValue = undefined; } else { - ctx.bezierCurveTo(via1.x, via1.y, via2.x, via2.y, this.to.x, this.to.y); + ctx.quadraticCurveTo(via.x, via.y, this.to.x, this.to.y); } // draw shadow if enabled this.enableShadow(ctx); @@ -31597,49 +31504,174 @@ return /******/ (function(modules) { // webpackBootstrap }, { key: '_getViaCoordinates', value: function _getViaCoordinates() { - var dx = this.from.x - this.to.x; - var dy = this.from.y - this.to.y; + var xVia = undefined; + var yVia = undefined; + var factor = this.options.smooth.roundness; + var type = this.options.smooth.type; + var dx = Math.abs(this.from.x - this.to.x); + var dy = Math.abs(this.from.y - this.to.y); + if (type === 'discrete' || type === 'diagonalCross') { + if (Math.abs(this.from.x - this.to.x) <= Math.abs(this.from.y - this.to.y)) { + if (this.from.y >= this.to.y) { + if (this.from.x <= this.to.x) { + xVia = this.from.x + factor * dy; + yVia = this.from.y - factor * dy; + } else if (this.from.x > this.to.x) { + xVia = this.from.x - factor * dy; + yVia = this.from.y - factor * dy; + } + } else if (this.from.y < this.to.y) { + if (this.from.x <= this.to.x) { + xVia = this.from.x + factor * dy; + yVia = this.from.y + factor * dy; + } else if (this.from.x > this.to.x) { + xVia = this.from.x - factor * dy; + yVia = this.from.y + factor * dy; + } + } + if (type === "discrete") { + xVia = dx < factor * dy ? this.from.x : xVia; + } + } else if (Math.abs(this.from.x - this.to.x) > Math.abs(this.from.y - this.to.y)) { + if (this.from.y >= this.to.y) { + if (this.from.x <= this.to.x) { + xVia = this.from.x + factor * dx; + yVia = this.from.y - factor * dx; + } else if (this.from.x > this.to.x) { + xVia = this.from.x - factor * dx; + yVia = this.from.y - factor * dx; + } + } else if (this.from.y < this.to.y) { + if (this.from.x <= this.to.x) { + xVia = this.from.x + factor * dx; + yVia = this.from.y + factor * dx; + } else if (this.from.x > this.to.x) { + xVia = this.from.x - factor * dx; + yVia = this.from.y + factor * dx; + } + } + if (type === "discrete") { + yVia = dy < factor * dx ? this.from.y : yVia; + } + } + } else if (type === "straightCross") { + if (Math.abs(this.from.x - this.to.x) <= Math.abs(this.from.y - this.to.y)) { + // up - down + xVia = this.from.x; + if (this.from.y < this.to.y) { + yVia = this.to.y - (1 - factor) * dy; + } else { + yVia = this.to.y + (1 - factor) * dy; + } + } else if (Math.abs(this.from.x - this.to.x) > Math.abs(this.from.y - this.to.y)) { + // left - right + if (this.from.x < this.to.x) { + xVia = this.to.x - (1 - factor) * dx; + } else { + xVia = this.to.x + (1 - factor) * dx; + } + yVia = this.from.y; + } + } else if (type === 'horizontal') { + if (this.from.x < this.to.x) { + xVia = this.to.x - (1 - factor) * dx; + } else { + xVia = this.to.x + (1 - factor) * dx; + } + yVia = this.from.y; + } else if (type === 'vertical') { + xVia = this.from.x; + if (this.from.y < this.to.y) { + yVia = this.to.y - (1 - factor) * dy; + } else { + yVia = this.to.y + (1 - factor) * dy; + } + } else if (type === 'curvedCW') { + dx = this.to.x - this.from.x; + dy = this.from.y - this.to.y; + var radius = Math.sqrt(dx * dx + dy * dy); + var pi = Math.PI; - var x1 = undefined, - y1 = undefined, - x2 = undefined, - y2 = undefined; - var roundness = this.options.smooth.roundness;; + var originalAngle = Math.atan2(dy, dx); + var myAngle = (originalAngle + (factor * 0.5 + 0.5) * pi) % (2 * pi); - // horizontal if x > y or if direction is forced or if direction is horizontal - if ((Math.abs(dx) > Math.abs(dy) || this.options.smooth.forceDirection === true || this.options.smooth.forceDirection === 'horizontal') && this.options.smooth.forceDirection !== 'vertical') { - y1 = this.from.y; - y2 = this.to.y; - x1 = this.from.x - roundness * dx; - x2 = this.to.x + roundness * dx; + xVia = this.from.x + (factor * 0.5 + 0.5) * radius * Math.sin(myAngle); + yVia = this.from.y + (factor * 0.5 + 0.5) * radius * Math.cos(myAngle); + } else if (type === 'curvedCCW') { + dx = this.to.x - this.from.x; + dy = this.from.y - this.to.y; + var radius = Math.sqrt(dx * dx + dy * dy); + var pi = Math.PI; + + var originalAngle = Math.atan2(dy, dx); + var myAngle = (originalAngle + (-factor * 0.5 + 0.5) * pi) % (2 * pi); + + xVia = this.from.x + (factor * 0.5 + 0.5) * radius * Math.sin(myAngle); + yVia = this.from.y + (factor * 0.5 + 0.5) * radius * Math.cos(myAngle); } else { - y1 = this.from.y - roundness * dy; - y2 = this.to.y + roundness * dy; - x1 = this.from.x; - x2 = this.to.x; + // continuous + if (Math.abs(this.from.x - this.to.x) <= Math.abs(this.from.y - this.to.y)) { + if (this.from.y >= this.to.y) { + if (this.from.x <= this.to.x) { + xVia = this.from.x + factor * dy; + yVia = this.from.y - factor * dy; + xVia = this.to.x < xVia ? this.to.x : xVia; + } else if (this.from.x > this.to.x) { + xVia = this.from.x - factor * dy; + yVia = this.from.y - factor * dy; + xVia = this.to.x > xVia ? this.to.x : xVia; + } + } else if (this.from.y < this.to.y) { + if (this.from.x <= this.to.x) { + xVia = this.from.x + factor * dy; + yVia = this.from.y + factor * dy; + xVia = this.to.x < xVia ? this.to.x : xVia; + } else if (this.from.x > this.to.x) { + xVia = this.from.x - factor * dy; + yVia = this.from.y + factor * dy; + xVia = this.to.x > xVia ? this.to.x : xVia; + } + } + } else if (Math.abs(this.from.x - this.to.x) > Math.abs(this.from.y - this.to.y)) { + if (this.from.y >= this.to.y) { + if (this.from.x <= this.to.x) { + xVia = this.from.x + factor * dx; + yVia = this.from.y - factor * dx; + yVia = this.to.y > yVia ? this.to.y : yVia; + } else if (this.from.x > this.to.x) { + xVia = this.from.x - factor * dx; + yVia = this.from.y - factor * dx; + yVia = this.to.y > yVia ? this.to.y : yVia; + } + } else if (this.from.y < this.to.y) { + if (this.from.x <= this.to.x) { + xVia = this.from.x + factor * dx; + yVia = this.from.y + factor * dx; + yVia = this.to.y < yVia ? this.to.y : yVia; + } else if (this.from.x > this.to.x) { + xVia = this.from.x - factor * dx; + yVia = this.from.y + factor * dx; + yVia = this.to.y < yVia ? this.to.y : yVia; + } + } + } } - - return [{ x: x1, y: y1 }, { x: x2, y: y2 }]; + return { x: xVia, y: yVia }; } }, { key: '_findBorderPosition', value: function _findBorderPosition(nearNode, ctx) { - return this._findBorderPositionBezier(nearNode, ctx); + var options = arguments.length <= 2 || arguments[2] === undefined ? {} : arguments[2]; + + return this._findBorderPositionBezier(nearNode, ctx, options.via); } }, { key: '_getDistanceToEdge', value: function _getDistanceToEdge(x1, y1, x2, y2, x3, y3) { - var _ref = arguments.length <= 6 || arguments[6] === undefined ? this._getViaCoordinates() : arguments[6]; - - var _ref2 = _slicedToArray(_ref, 2); - - var via1 = _ref2[0]; - var via2 = _ref2[1]; + var via = arguments.length <= 6 || arguments[6] === undefined ? this._getViaCoordinates() : arguments[6]; // x3,y3 is the point - return this._getDistanceToBezierEdge(x1, y1, x2, y2, x3, y3, via1, via2); + return this._getDistanceToBezierEdge(x1, y1, x2, y2, x3, y3, via); } - }, { - key: 'getPoint', /** * Combined function of pointOnLine and pointOnBezier. This gives the coordinates of a point on the line at a certain percentage of the way @@ -31648,31 +31680,23 @@ return /******/ (function(modules) { // webpackBootstrap * @returns {{x: number, y: number}} * @private */ + }, { + key: 'getPoint', value: function getPoint(percentage) { - var _ref3 = arguments.length <= 1 || arguments[1] === undefined ? this._getViaCoordinates() : arguments[1]; - - var _ref32 = _slicedToArray(_ref3, 2); - - var via1 = _ref32[0]; - var via2 = _ref32[1]; + var via = arguments.length <= 1 || arguments[1] === undefined ? this._getViaCoordinates() : arguments[1]; var t = percentage; - var vec = []; - vec[0] = Math.pow(1 - t, 3); - vec[1] = 3 * t * Math.pow(1 - t, 2); - vec[2] = 3 * Math.pow(t, 2) * (1 - t); - vec[3] = Math.pow(t, 3); - var x = vec[0] * this.from.x + vec[1] * via1.x + vec[2] * via2.x + vec[3] * this.to.x; - var y = vec[0] * this.from.y + vec[1] * via1.y + vec[2] * via2.y + vec[3] * this.to.y; + var x = Math.pow(1 - t, 2) * this.from.x + 2 * t * (1 - t) * via.x + Math.pow(t, 2) * this.to.x; + var y = Math.pow(1 - t, 2) * this.from.y + 2 * t * (1 - t) * via.y + Math.pow(t, 2) * this.to.y; return { x: x, y: y }; } }]); - return CubicBezierEdge; - })(_utilCubicBezierEdgeBase2['default']); + return BezierEdgeStatic; + })(_utilBezierEdgeBase2['default']); - exports['default'] = CubicBezierEdge; + exports['default'] = BezierEdgeStatic; module.exports = exports['default']; /***/ }, @@ -31687,92 +31711,6 @@ return /******/ (function(modules) { // webpackBootstrap 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 _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; desc = parent = getter = undefined; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; - - function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } - - function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } - - function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; } - - var _BezierEdgeBase2 = __webpack_require__(85); - - var _BezierEdgeBase3 = _interopRequireDefault(_BezierEdgeBase2); - - var CubicBezierEdgeBase = (function (_BezierEdgeBase) { - _inherits(CubicBezierEdgeBase, _BezierEdgeBase); - - function CubicBezierEdgeBase(options, body, labelModule) { - _classCallCheck(this, CubicBezierEdgeBase); - - _get(Object.getPrototypeOf(CubicBezierEdgeBase.prototype), 'constructor', this).call(this, options, body, labelModule); - } - - _createClass(CubicBezierEdgeBase, [{ - key: '_getDistanceToBezierEdge', - - /** - * Calculate the distance between a point (x3,y3) and a line segment from - * (x1,y1) to (x2,y2). - * http://stackoverflow.com/questions/849211/shortest-distancae-between-a-point-and-a-line-segment - * https://en.wikipedia.org/wiki/B%C3%A9zier_curve - * @param {number} x1 from x - * @param {number} y1 from y - * @param {number} x2 to x - * @param {number} y2 to y - * @param {number} x3 point to check x - * @param {number} y3 point to check y - * @private - */ - value: function _getDistanceToBezierEdge(x1, y1, x2, y2, x3, y3, via1, via2) { - // x3,y3 is the point - var minDistance = 1e9; - var distance = undefined; - var i = undefined, - t = undefined, - x = undefined, - y = undefined; - var lastX = x1; - var lastY = y1; - var vec = [0, 0, 0, 0]; - for (i = 1; i < 10; i++) { - t = 0.1 * i; - vec[0] = Math.pow(1 - t, 3); - vec[1] = 3 * t * Math.pow(1 - t, 2); - vec[2] = 3 * Math.pow(t, 2) * (1 - t); - vec[3] = Math.pow(t, 3); - x = vec[0] * x1 + vec[1] * via1.x + vec[2] * via2.x + vec[3] * x2; - y = vec[0] * y1 + vec[1] * via1.y + vec[2] * via2.y + vec[3] * y2; - if (i > 0) { - distance = this._getDistanceToLine(lastX, lastY, x, y, x3, y3); - minDistance = distance < minDistance ? distance : minDistance; - } - lastX = x; - lastY = y; - } - - return minDistance; - } - }]); - - return CubicBezierEdgeBase; - })(_BezierEdgeBase3['default']); - - exports['default'] = CubicBezierEdgeBase; - module.exports = exports['default']; - -/***/ }, -/* 85 */ -/***/ function(module, exports, __webpack_require__) { - - 'use strict'; - - Object.defineProperty(exports, '__esModule', { - 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 _get = function get(_x2, _x3, _x4) { var _again = true; _function: while (_again) { var object = _x2, property = _x3, receiver = _x4; desc = parent = getter = undefined; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x2 = parent; _x3 = property; _x4 = receiver; _again = true; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } @@ -31781,7 +31719,7 @@ return /******/ (function(modules) { // webpackBootstrap function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; } - var _EdgeBase2 = __webpack_require__(86); + var _EdgeBase2 = __webpack_require__(85); var _EdgeBase3 = _interopRequireDefault(_EdgeBase2); @@ -31794,22 +31732,22 @@ return /******/ (function(modules) { // webpackBootstrap _get(Object.getPrototypeOf(BezierEdgeBase.prototype), 'constructor', this).call(this, options, body, labelModule); } + /** + * This function uses binary search to look for the point where the bezier curve crosses the border of the node. + * + * @param nearNode + * @param ctx + * @param viaNode + * @param nearNode + * @param ctx + * @param viaNode + * @param nearNode + * @param ctx + * @param viaNode + */ + _createClass(BezierEdgeBase, [{ key: '_findBorderPositionBezier', - - /** - * This function uses binary search to look for the point where the bezier curve crosses the border of the node. - * - * @param nearNode - * @param ctx - * @param viaNode - * @param nearNode - * @param ctx - * @param viaNode - * @param nearNode - * @param ctx - * @param viaNode - */ value: function _findBorderPositionBezier(nearNode, ctx) { var viaNode = arguments.length <= 2 || arguments[2] === undefined ? this._getViaCoordinates() : arguments[2]; @@ -31837,19 +31775,19 @@ return /******/ (function(modules) { // webpackBootstrap if (Math.abs(difference) < threshold) { break; // found } else if (difference < 0) { - // distance to nodes is larger than distance to border --> t needs to be bigger if we're looking at the to node. - if (from === false) { - low = middle; - } else { - high = middle; - } - } else { - if (from === false) { - high = middle; + // distance to nodes is larger than distance to border --> t needs to be bigger if we're looking at the to node. + if (from === false) { + low = middle; + } else { + high = middle; + } } else { - low = middle; + if (from === false) { + high = middle; + } else { + low = middle; + } } - } iteration++; } @@ -31857,8 +31795,6 @@ return /******/ (function(modules) { // webpackBootstrap return pos; } - }, { - key: '_getDistanceToBezierEdge', /** * Calculate the distance between a point (x3,y3) and a line segment from @@ -31872,6 +31808,8 @@ return /******/ (function(modules) { // webpackBootstrap * @param {number} y3 point to check y * @private */ + }, { + key: '_getDistanceToBezierEdge', value: function _getDistanceToBezierEdge(x1, y1, x2, y2, x3, y3, via) { // x3,y3 is the point var minDistance = 1e9; @@ -31905,7 +31843,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = exports['default']; /***/ }, -/* 86 */ +/* 85 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; @@ -31954,8 +31892,6 @@ return /******/ (function(modules) { // webpackBootstrap this.to = this.body.nodes[this.options.to]; this.id = this.options.id; } - }, { - key: 'drawLine', /** * Redraw a edge as a line @@ -31964,6 +31900,8 @@ return /******/ (function(modules) { // webpackBootstrap * @param {CanvasRenderingContext2D} ctx * @private */ + }, { + key: 'drawLine', value: function drawLine(ctx, selected, hover) { // set style ctx.strokeStyle = this.getColor(ctx, selected, hover); @@ -32115,8 +32053,6 @@ return /******/ (function(modules) { // webpackBootstrap } return [x, y, radius]; } - }, { - key: '_pointOnCircle', /** * Get a point on a circle @@ -32127,6 +32063,8 @@ return /******/ (function(modules) { // webpackBootstrap * @return {Object} point * @private */ + }, { + key: '_pointOnCircle', value: function _pointOnCircle(x, y, radius, percentage) { var angle = percentage * 2 * Math.PI; return { @@ -32134,8 +32072,6 @@ return /******/ (function(modules) { // webpackBootstrap y: y - radius * Math.sin(angle) }; } - }, { - key: '_findBorderPositionCircle', /** * This function uses binary search to look for the point where the circle crosses the border of the node. @@ -32145,6 +32081,8 @@ return /******/ (function(modules) { // webpackBootstrap * @returns {*} * @private */ + }, { + key: '_findBorderPositionCircle', value: function _findBorderPositionCircle(node, ctx, options) { var x = options.x; var y = options.y; @@ -32174,27 +32112,25 @@ return /******/ (function(modules) { // webpackBootstrap if (Math.abs(difference) < threshold) { break; // found } else if (difference > 0) { - // distance to nodes is larger than distance to border --> t needs to be bigger if we're looking at the to node. - if (direction > 0) { - low = middle; - } else { - high = middle; - } - } else { - if (direction > 0) { - high = middle; + // distance to nodes is larger than distance to border --> t needs to be bigger if we're looking at the to node. + if (direction > 0) { + low = middle; + } else { + high = middle; + } } else { - low = middle; + if (direction > 0) { + high = middle; + } else { + low = middle; + } } - } iteration++; } pos.t = middle; return pos; } - }, { - key: 'getLineWidth', /** * Get the line width of the edge. Depends on width and whether one of the @@ -32202,6 +32138,8 @@ return /******/ (function(modules) { // webpackBootstrap * @return {Number} width * @private */ + }, { + key: 'getLineWidth', value: function getLineWidth(selected, hover) { if (selected === true) { return Math.max(this.selectionWidth, 0.3 / this.body.view.scale); @@ -32242,7 +32180,7 @@ return /******/ (function(modules) { // webpackBootstrap } if (this.colorDirty === true) { - if (colorOptions.inherit === 'to') { + if (colorOptions.inherit === "to") { this.color.highlight = this.to.options.color.highlight.border; this.color.hover = this.to.options.color.hover.border; this.color.color = util.overrideOpacity(this.to.options.color.border, colorOptions.opacity); @@ -32270,8 +32208,6 @@ return /******/ (function(modules) { // webpackBootstrap return this.color.color; } } - }, { - key: '_circle', /** * Draw a line from a node to itself, a circle @@ -32281,6 +32217,8 @@ return /******/ (function(modules) { // webpackBootstrap * @param {Number} radius * @private */ + }, { + key: '_circle', value: function _circle(ctx, x, y, radius) { // draw shadow if enabled this.enableShadow(ctx); @@ -32293,8 +32231,6 @@ return /******/ (function(modules) { // webpackBootstrap // disable shadows for other elements. this.disableShadow(ctx); } - }, { - key: 'getDistanceToEdge', /** * Calculate the distance between a point (x3,y3) and a line segment from @@ -32308,6 +32244,8 @@ return /******/ (function(modules) { // webpackBootstrap * @param {number} y3 * @private */ + }, { + key: 'getDistanceToEdge', value: function getDistanceToEdge(x1, y1, x2, y2, x3, y3, via) { // x3,y3 is the point var returnValue = 0; @@ -32360,8 +32298,6 @@ return /******/ (function(modules) { // webpackBootstrap return Math.sqrt(dx * dx + dy * dy); } - }, { - key: 'drawArrowHead', /** * @@ -32369,6 +32305,8 @@ return /******/ (function(modules) { // webpackBootstrap * @param position * @param viaNode */ + }, { + key: 'drawArrowHead', value: function drawArrowHead(ctx, position, viaNode, selected, hover) { // set style ctx.strokeStyle = this.getColor(ctx, selected, hover); @@ -32492,8 +32430,247 @@ return /******/ (function(modules) { // webpackBootstrap exports['default'] = EdgeBase; module.exports = exports['default']; +/***/ }, +/* 86 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + Object.defineProperty(exports, '__esModule', { + value: true + }); + + var _slicedToArray = (function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i['return']) _i['return'](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError('Invalid attempt to destructure non-iterable instance'); } }; })(); + + 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 _get = function get(_x3, _x4, _x5) { var _again = true; _function: while (_again) { var object = _x3, property = _x4, receiver = _x5; desc = parent = getter = undefined; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x3 = parent; _x4 = property; _x5 = receiver; _again = true; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; + + function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } + + function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } + + function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; } + + var _utilCubicBezierEdgeBase = __webpack_require__(87); + + var _utilCubicBezierEdgeBase2 = _interopRequireDefault(_utilCubicBezierEdgeBase); + + var CubicBezierEdge = (function (_CubicBezierEdgeBase) { + _inherits(CubicBezierEdge, _CubicBezierEdgeBase); + + function CubicBezierEdge(options, body, labelModule) { + _classCallCheck(this, CubicBezierEdge); + + _get(Object.getPrototypeOf(CubicBezierEdge.prototype), 'constructor', this).call(this, options, body, labelModule); + } + + /** + * Draw a line between two nodes + * @param {CanvasRenderingContext2D} ctx + * @private + */ + + _createClass(CubicBezierEdge, [{ + key: '_line', + value: function _line(ctx) { + var _getViaCoordinates2 = this._getViaCoordinates(); + + var _getViaCoordinates22 = _slicedToArray(_getViaCoordinates2, 2); + + var via1 = _getViaCoordinates22[0]; + var via2 = _getViaCoordinates22[1]; + + var returnValue = [via1, via2]; + + // start drawing the line. + ctx.beginPath(); + ctx.moveTo(this.from.x, this.from.y); + + // fallback to normal straight edges + if (via1.x === undefined) { + ctx.lineTo(this.to.x, this.to.y); + returnValue = undefined; + } else { + ctx.bezierCurveTo(via1.x, via1.y, via2.x, via2.y, this.to.x, this.to.y); + } + // draw shadow if enabled + this.enableShadow(ctx); + ctx.stroke(); + this.disableShadow(ctx); + return returnValue; + } + }, { + key: '_getViaCoordinates', + value: function _getViaCoordinates() { + var dx = this.from.x - this.to.x; + var dy = this.from.y - this.to.y; + + var x1 = undefined, + y1 = undefined, + x2 = undefined, + y2 = undefined; + var roundness = this.options.smooth.roundness;; + + // horizontal if x > y or if direction is forced or if direction is horizontal + if ((Math.abs(dx) > Math.abs(dy) || this.options.smooth.forceDirection === true || this.options.smooth.forceDirection === 'horizontal') && this.options.smooth.forceDirection !== 'vertical') { + y1 = this.from.y; + y2 = this.to.y; + x1 = this.from.x - roundness * dx; + x2 = this.to.x + roundness * dx; + } else { + y1 = this.from.y - roundness * dy; + y2 = this.to.y + roundness * dy; + x1 = this.from.x; + x2 = this.to.x; + } + + return [{ x: x1, y: y1 }, { x: x2, y: y2 }]; + } + }, { + key: '_findBorderPosition', + value: function _findBorderPosition(nearNode, ctx) { + return this._findBorderPositionBezier(nearNode, ctx); + } + }, { + key: '_getDistanceToEdge', + value: function _getDistanceToEdge(x1, y1, x2, y2, x3, y3) { + var _ref = arguments.length <= 6 || arguments[6] === undefined ? this._getViaCoordinates() : arguments[6]; + + var _ref2 = _slicedToArray(_ref, 2); + + var via1 = _ref2[0]; + var via2 = _ref2[1]; + // x3,y3 is the point + return this._getDistanceToBezierEdge(x1, y1, x2, y2, x3, y3, via1, via2); + } + + /** + * Combined function of pointOnLine and pointOnBezier. This gives the coordinates of a point on the line at a certain percentage of the way + * @param percentage + * @param via + * @returns {{x: number, y: number}} + * @private + */ + }, { + key: 'getPoint', + value: function getPoint(percentage) { + var _ref3 = arguments.length <= 1 || arguments[1] === undefined ? this._getViaCoordinates() : arguments[1]; + + var _ref32 = _slicedToArray(_ref3, 2); + + var via1 = _ref32[0]; + var via2 = _ref32[1]; + + var t = percentage; + var vec = []; + vec[0] = Math.pow(1 - t, 3); + vec[1] = 3 * t * Math.pow(1 - t, 2); + vec[2] = 3 * Math.pow(t, 2) * (1 - t); + vec[3] = Math.pow(t, 3); + var x = vec[0] * this.from.x + vec[1] * via1.x + vec[2] * via2.x + vec[3] * this.to.x; + var y = vec[0] * this.from.y + vec[1] * via1.y + vec[2] * via2.y + vec[3] * this.to.y; + + return { x: x, y: y }; + } + }]); + + return CubicBezierEdge; + })(_utilCubicBezierEdgeBase2['default']); + + exports['default'] = CubicBezierEdge; + module.exports = exports['default']; + + // get the coordinates of the support points. + /***/ }, /* 87 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + Object.defineProperty(exports, '__esModule', { + 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 _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; desc = parent = getter = undefined; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; + + function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } + + function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } + + function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; } + + var _BezierEdgeBase2 = __webpack_require__(84); + + var _BezierEdgeBase3 = _interopRequireDefault(_BezierEdgeBase2); + + var CubicBezierEdgeBase = (function (_BezierEdgeBase) { + _inherits(CubicBezierEdgeBase, _BezierEdgeBase); + + function CubicBezierEdgeBase(options, body, labelModule) { + _classCallCheck(this, CubicBezierEdgeBase); + + _get(Object.getPrototypeOf(CubicBezierEdgeBase.prototype), 'constructor', this).call(this, options, body, labelModule); + } + + /** + * Calculate the distance between a point (x3,y3) and a line segment from + * (x1,y1) to (x2,y2). + * http://stackoverflow.com/questions/849211/shortest-distancae-between-a-point-and-a-line-segment + * https://en.wikipedia.org/wiki/B%C3%A9zier_curve + * @param {number} x1 from x + * @param {number} y1 from y + * @param {number} x2 to x + * @param {number} y2 to y + * @param {number} x3 point to check x + * @param {number} y3 point to check y + * @private + */ + + _createClass(CubicBezierEdgeBase, [{ + key: '_getDistanceToBezierEdge', + value: function _getDistanceToBezierEdge(x1, y1, x2, y2, x3, y3, via1, via2) { + // x3,y3 is the point + var minDistance = 1e9; + var distance = undefined; + var i = undefined, + t = undefined, + x = undefined, + y = undefined; + var lastX = x1; + var lastY = y1; + var vec = [0, 0, 0, 0]; + for (i = 1; i < 10; i++) { + t = 0.1 * i; + vec[0] = Math.pow(1 - t, 3); + vec[1] = 3 * t * Math.pow(1 - t, 2); + vec[2] = 3 * Math.pow(t, 2) * (1 - t); + vec[3] = Math.pow(t, 3); + x = vec[0] * x1 + vec[1] * via1.x + vec[2] * via2.x + vec[3] * x2; + y = vec[0] * y1 + vec[1] * via1.y + vec[2] * via2.y + vec[3] * y2; + if (i > 0) { + distance = this._getDistanceToLine(lastX, lastY, x, y, x3, y3); + minDistance = distance < minDistance ? distance : minDistance; + } + lastX = x; + lastY = y; + } + + return minDistance; + } + }]); + + return CubicBezierEdgeBase; + })(_BezierEdgeBase3['default']); + + exports['default'] = CubicBezierEdgeBase; + module.exports = exports['default']; + +/***/ }, +/* 88 */ /***/ function(module, exports, __webpack_require__) { "use strict"; @@ -32512,7 +32689,7 @@ return /******/ (function(modules) { // webpackBootstrap function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; } - var _utilBezierEdgeBase = __webpack_require__(85); + var _utilBezierEdgeBase = __webpack_require__(84); var _utilBezierEdgeBase2 = _interopRequireDefault(_utilBezierEdgeBase); @@ -32562,13 +32739,13 @@ return /******/ (function(modules) { // webpackBootstrap } } } - }, { - key: "cleanup", /** * remove the support nodes * @returns {boolean} */ + }, { + key: "cleanup", value: function cleanup() { this.body.emitter.off("_repositionBezierNodes", this._boundFunction); if (this.via !== undefined) { @@ -32578,8 +32755,6 @@ return /******/ (function(modules) { // webpackBootstrap } return false; } - }, { - key: "setupSupportNode", /** * Bezier curves require an anchor point to calculate the smooth flow. These points are nodes. These nodes are invisible but @@ -32588,12 +32763,14 @@ return /******/ (function(modules) { // webpackBootstrap * The changed data is not called, if needed, it is returned by the main edge constructor. * @private */ + }, { + key: "setupSupportNode", value: function setupSupportNode() { if (this.via === undefined) { var nodeId = "edgeId:" + this.id; var node = this.body.functions.createNode({ id: nodeId, - shape: "circle", + shape: 'circle', physics: true, hidden: true }); @@ -32614,14 +32791,14 @@ return /******/ (function(modules) { // webpackBootstrap this.via.y = 0; } } - }, { - key: "_line", /** * Draw a line between two nodes * @param {CanvasRenderingContext2D} ctx * @private */ + }, { + key: "_line", value: function _line(ctx) { // draw a straight line ctx.beginPath(); @@ -32633,8 +32810,6 @@ return /******/ (function(modules) { // webpackBootstrap this.disableShadow(ctx); return this.via; } - }, { - key: "getPoint", /** * Combined function of pointOnLine and pointOnBezier. This gives the coordinates of a point on the line at a certain percentage of the way @@ -32643,6 +32818,8 @@ return /******/ (function(modules) { // webpackBootstrap * @returns {{x: number, y: number}} * @private */ + }, { + key: "getPoint", value: function getPoint(percentage) { var t = percentage; var x = Math.pow(1 - t, 2) * this.from.x + 2 * t * (1 - t) * this.via.x + Math.pow(t, 2) * this.to.x; @@ -32669,265 +32846,6 @@ return /******/ (function(modules) { // webpackBootstrap exports["default"] = BezierEdgeDynamic; module.exports = exports["default"]; -/***/ }, -/* 88 */ -/***/ function(module, exports, __webpack_require__) { - - 'use strict'; - - Object.defineProperty(exports, '__esModule', { - 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 _get = function get(_x4, _x5, _x6) { var _again = true; _function: while (_again) { var object = _x4, property = _x5, receiver = _x6; desc = parent = getter = undefined; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x4 = parent; _x5 = property; _x6 = receiver; _again = true; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; - - function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } - - function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } - - function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; } - - var _utilBezierEdgeBase = __webpack_require__(85); - - var _utilBezierEdgeBase2 = _interopRequireDefault(_utilBezierEdgeBase); - - var BezierEdgeStatic = (function (_BezierEdgeBase) { - _inherits(BezierEdgeStatic, _BezierEdgeBase); - - function BezierEdgeStatic(options, body, labelModule) { - _classCallCheck(this, BezierEdgeStatic); - - _get(Object.getPrototypeOf(BezierEdgeStatic.prototype), 'constructor', this).call(this, options, body, labelModule); - } - - _createClass(BezierEdgeStatic, [{ - key: '_line', - - /** - * Draw a line between two nodes - * @param {CanvasRenderingContext2D} ctx - * @private - */ - value: function _line(ctx) { - // draw a straight line - ctx.beginPath(); - ctx.moveTo(this.from.x, this.from.y); - var via = this._getViaCoordinates(); - var returnValue = via; - - // fallback to normal straight edges - if (via.x === undefined) { - ctx.lineTo(this.to.x, this.to.y); - returnValue = undefined; - } else { - ctx.quadraticCurveTo(via.x, via.y, this.to.x, this.to.y); - } - // draw shadow if enabled - this.enableShadow(ctx); - ctx.stroke(); - this.disableShadow(ctx); - return returnValue; - } - }, { - key: '_getViaCoordinates', - value: function _getViaCoordinates() { - var xVia = undefined; - var yVia = undefined; - var factor = this.options.smooth.roundness; - var type = this.options.smooth.type; - var dx = Math.abs(this.from.x - this.to.x); - var dy = Math.abs(this.from.y - this.to.y); - if (type === 'discrete' || type === 'diagonalCross') { - if (Math.abs(this.from.x - this.to.x) <= Math.abs(this.from.y - this.to.y)) { - if (this.from.y >= this.to.y) { - if (this.from.x <= this.to.x) { - xVia = this.from.x + factor * dy; - yVia = this.from.y - factor * dy; - } else if (this.from.x > this.to.x) { - xVia = this.from.x - factor * dy; - yVia = this.from.y - factor * dy; - } - } else if (this.from.y < this.to.y) { - if (this.from.x <= this.to.x) { - xVia = this.from.x + factor * dy; - yVia = this.from.y + factor * dy; - } else if (this.from.x > this.to.x) { - xVia = this.from.x - factor * dy; - yVia = this.from.y + factor * dy; - } - } - if (type === 'discrete') { - xVia = dx < factor * dy ? this.from.x : xVia; - } - } else if (Math.abs(this.from.x - this.to.x) > Math.abs(this.from.y - this.to.y)) { - if (this.from.y >= this.to.y) { - if (this.from.x <= this.to.x) { - xVia = this.from.x + factor * dx; - yVia = this.from.y - factor * dx; - } else if (this.from.x > this.to.x) { - xVia = this.from.x - factor * dx; - yVia = this.from.y - factor * dx; - } - } else if (this.from.y < this.to.y) { - if (this.from.x <= this.to.x) { - xVia = this.from.x + factor * dx; - yVia = this.from.y + factor * dx; - } else if (this.from.x > this.to.x) { - xVia = this.from.x - factor * dx; - yVia = this.from.y + factor * dx; - } - } - if (type === 'discrete') { - yVia = dy < factor * dx ? this.from.y : yVia; - } - } - } else if (type === 'straightCross') { - if (Math.abs(this.from.x - this.to.x) <= Math.abs(this.from.y - this.to.y)) { - // up - down - xVia = this.from.x; - if (this.from.y < this.to.y) { - yVia = this.to.y - (1 - factor) * dy; - } else { - yVia = this.to.y + (1 - factor) * dy; - } - } else if (Math.abs(this.from.x - this.to.x) > Math.abs(this.from.y - this.to.y)) { - // left - right - if (this.from.x < this.to.x) { - xVia = this.to.x - (1 - factor) * dx; - } else { - xVia = this.to.x + (1 - factor) * dx; - } - yVia = this.from.y; - } - } else if (type === 'horizontal') { - if (this.from.x < this.to.x) { - xVia = this.to.x - (1 - factor) * dx; - } else { - xVia = this.to.x + (1 - factor) * dx; - } - yVia = this.from.y; - } else if (type === 'vertical') { - xVia = this.from.x; - if (this.from.y < this.to.y) { - yVia = this.to.y - (1 - factor) * dy; - } else { - yVia = this.to.y + (1 - factor) * dy; - } - } else if (type === 'curvedCW') { - dx = this.to.x - this.from.x; - dy = this.from.y - this.to.y; - var radius = Math.sqrt(dx * dx + dy * dy); - var pi = Math.PI; - - var originalAngle = Math.atan2(dy, dx); - var myAngle = (originalAngle + (factor * 0.5 + 0.5) * pi) % (2 * pi); - - xVia = this.from.x + (factor * 0.5 + 0.5) * radius * Math.sin(myAngle); - yVia = this.from.y + (factor * 0.5 + 0.5) * radius * Math.cos(myAngle); - } else if (type === 'curvedCCW') { - dx = this.to.x - this.from.x; - dy = this.from.y - this.to.y; - var radius = Math.sqrt(dx * dx + dy * dy); - var pi = Math.PI; - - var originalAngle = Math.atan2(dy, dx); - var myAngle = (originalAngle + (-factor * 0.5 + 0.5) * pi) % (2 * pi); - - xVia = this.from.x + (factor * 0.5 + 0.5) * radius * Math.sin(myAngle); - yVia = this.from.y + (factor * 0.5 + 0.5) * radius * Math.cos(myAngle); - } else { - // continuous - if (Math.abs(this.from.x - this.to.x) <= Math.abs(this.from.y - this.to.y)) { - if (this.from.y >= this.to.y) { - if (this.from.x <= this.to.x) { - xVia = this.from.x + factor * dy; - yVia = this.from.y - factor * dy; - xVia = this.to.x < xVia ? this.to.x : xVia; - } else if (this.from.x > this.to.x) { - xVia = this.from.x - factor * dy; - yVia = this.from.y - factor * dy; - xVia = this.to.x > xVia ? this.to.x : xVia; - } - } else if (this.from.y < this.to.y) { - if (this.from.x <= this.to.x) { - xVia = this.from.x + factor * dy; - yVia = this.from.y + factor * dy; - xVia = this.to.x < xVia ? this.to.x : xVia; - } else if (this.from.x > this.to.x) { - xVia = this.from.x - factor * dy; - yVia = this.from.y + factor * dy; - xVia = this.to.x > xVia ? this.to.x : xVia; - } - } - } else if (Math.abs(this.from.x - this.to.x) > Math.abs(this.from.y - this.to.y)) { - if (this.from.y >= this.to.y) { - if (this.from.x <= this.to.x) { - xVia = this.from.x + factor * dx; - yVia = this.from.y - factor * dx; - yVia = this.to.y > yVia ? this.to.y : yVia; - } else if (this.from.x > this.to.x) { - xVia = this.from.x - factor * dx; - yVia = this.from.y - factor * dx; - yVia = this.to.y > yVia ? this.to.y : yVia; - } - } else if (this.from.y < this.to.y) { - if (this.from.x <= this.to.x) { - xVia = this.from.x + factor * dx; - yVia = this.from.y + factor * dx; - yVia = this.to.y < yVia ? this.to.y : yVia; - } else if (this.from.x > this.to.x) { - xVia = this.from.x - factor * dx; - yVia = this.from.y + factor * dx; - yVia = this.to.y < yVia ? this.to.y : yVia; - } - } - } - } - return { x: xVia, y: yVia }; - } - }, { - key: '_findBorderPosition', - value: function _findBorderPosition(nearNode, ctx) { - var options = arguments.length <= 2 || arguments[2] === undefined ? {} : arguments[2]; - - return this._findBorderPositionBezier(nearNode, ctx, options.via); - } - }, { - key: '_getDistanceToEdge', - value: function _getDistanceToEdge(x1, y1, x2, y2, x3, y3) { - var via = arguments.length <= 6 || arguments[6] === undefined ? this._getViaCoordinates() : arguments[6]; - // x3,y3 is the point - return this._getDistanceToBezierEdge(x1, y1, x2, y2, x3, y3, via); - } - }, { - key: 'getPoint', - - /** - * Combined function of pointOnLine and pointOnBezier. This gives the coordinates of a point on the line at a certain percentage of the way - * @param percentage - * @param via - * @returns {{x: number, y: number}} - * @private - */ - value: function getPoint(percentage) { - var via = arguments.length <= 1 || arguments[1] === undefined ? this._getViaCoordinates() : arguments[1]; - - var t = percentage; - var x = Math.pow(1 - t, 2) * this.from.x + 2 * t * (1 - t) * via.x + Math.pow(t, 2) * this.to.x; - var y = Math.pow(1 - t, 2) * this.from.y + 2 * t * (1 - t) * via.y + Math.pow(t, 2) * this.to.y; - - return { x: x, y: y }; - } - }]); - - return BezierEdgeStatic; - })(_utilBezierEdgeBase2['default']); - - exports['default'] = BezierEdgeStatic; - module.exports = exports['default']; - /***/ }, /* 89 */ /***/ function(module, exports, __webpack_require__) { @@ -32948,7 +32866,7 @@ return /******/ (function(modules) { // webpackBootstrap function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; } - var _utilEdgeBase = __webpack_require__(86); + var _utilEdgeBase = __webpack_require__(85); var _utilEdgeBase2 = _interopRequireDefault(_utilEdgeBase); @@ -32961,14 +32879,14 @@ return /******/ (function(modules) { // webpackBootstrap _get(Object.getPrototypeOf(StraightEdge.prototype), 'constructor', this).call(this, options, body, labelModule); } + /** + * Draw a line between two nodes + * @param {CanvasRenderingContext2D} ctx + * @private + */ + _createClass(StraightEdge, [{ key: '_line', - - /** - * Draw a line between two nodes - * @param {CanvasRenderingContext2D} ctx - * @private - */ value: function _line(ctx) { // draw a straight line ctx.beginPath(); @@ -32980,8 +32898,6 @@ return /******/ (function(modules) { // webpackBootstrap this.disableShadow(ctx); return undefined; } - }, { - key: 'getPoint', /** * Combined function of pointOnLine and pointOnBezier. This gives the coordinates of a point on the line at a certain percentage of the way @@ -32990,6 +32906,8 @@ return /******/ (function(modules) { // webpackBootstrap * @returns {{x: number, y: number}} * @private */ + }, { + key: 'getPoint', value: function getPoint(percentage) { return { x: (1 - percentage) * this.from.x + percentage * this.to.x, @@ -33161,6 +33079,7 @@ return /******/ (function(modules) { // webpackBootstrap }; util.extend(this.options, this.defaultOptions); this.timestep = 0.5; + this.layoutFailed = false; this.bindEventListeners(); } @@ -33173,6 +33092,9 @@ return /******/ (function(modules) { // webpackBootstrap this.body.emitter.on('initPhysics', function () { _this.initPhysics(); }); + this.body.emitter.on('_layoutFailed', function () { + _this.layoutFailed = true; + }); this.body.emitter.on('resetPhysics', function () { _this.stopSimulation();_this.ready = false; }); @@ -33198,13 +33120,13 @@ return /******/ (function(modules) { // webpackBootstrap _this.body.emitter.off(); }); } - }, { - key: 'setOptions', /** * set the physics options * @param options */ + }, { + key: 'setOptions', value: function setOptions(options) { if (options !== undefined) { if (options === false) { @@ -33231,12 +33153,12 @@ return /******/ (function(modules) { // webpackBootstrap } this.init(); } - }, { - key: 'init', /** * configure the engine. */ + }, { + key: 'init', value: function init() { var options; if (this.options.solver === 'forceAtlas2Based') { @@ -33264,12 +33186,12 @@ return /******/ (function(modules) { // webpackBootstrap this.modelOptions = options; } - }, { - key: 'initPhysics', /** * initialize the engine */ + }, { + key: 'initPhysics', value: function initPhysics() { if (this.physicsEnabled === true && this.options.enabled === true) { if (this.options.stabilization.enabled === true) { @@ -33277,7 +33199,7 @@ return /******/ (function(modules) { // webpackBootstrap } else { this.stabilized = false; this.ready = true; - this.body.emitter.emit('fit', {}, false); + this.body.emitter.emit('fit', {}, this.layoutFailed); // if the layout failed, we use the approximation for the zoom this.startSimulation(); } } else { @@ -33285,12 +33207,12 @@ return /******/ (function(modules) { // webpackBootstrap this.body.emitter.emit('fit'); } } - }, { - key: 'startSimulation', /** * Start the simulation */ + }, { + key: 'startSimulation', value: function startSimulation() { if (this.physicsEnabled === true && this.options.enabled === true) { this.stabilized = false; @@ -33299,7 +33221,7 @@ return /******/ (function(modules) { // webpackBootstrap this.adaptiveTimestep = false; // this sets the width of all nodes initially which could be required for the avoidOverlap - this.body.emitter.emit('_resizeNodes'); + this.body.emitter.emit("_resizeNodes"); if (this.viewFunction === undefined) { this.viewFunction = this.simulationStep.bind(this); this.body.emitter.on('initRedraw', this.viewFunction); @@ -33309,12 +33231,12 @@ return /******/ (function(modules) { // webpackBootstrap this.body.emitter.emit('_redraw'); } } - }, { - key: 'stopSimulation', /** * Stop the simulation, force stabilization. */ + }, { + key: 'stopSimulation', value: function stopSimulation() { var emit = arguments.length <= 0 || arguments[0] === undefined ? true : arguments[0]; @@ -33330,13 +33252,13 @@ return /******/ (function(modules) { // webpackBootstrap } } } - }, { - key: 'simulationStep', /** * The viewFunction inserts this step into each renderloop. It calls the physics tick and handles the cleanup at stabilized. * */ + }, { + key: 'simulationStep', value: function simulationStep() { // check if the physics have settled var startTime = Date.now(); @@ -33355,13 +33277,13 @@ return /******/ (function(modules) { // webpackBootstrap this.stopSimulation(); } } - }, { - key: '_emitStabilized', /** * trigger the stabilized event. * @private */ + }, { + key: '_emitStabilized', value: function _emitStabilized() { var _this2 = this; @@ -33372,14 +33294,14 @@ return /******/ (function(modules) { // webpackBootstrap }, 0); } } - }, { - key: 'physicsTick', /** * A single simulation step (or 'tick') in the physics simulation * * @private */ + }, { + key: 'physicsTick', value: function physicsTick() { if (this.stabilized === false) { // adaptivity means the timestep adapts to the situation, only applicable for stabilization @@ -33450,14 +33372,14 @@ return /******/ (function(modules) { // webpackBootstrap this.stabilizationIterations++; } } - }, { - key: 'updatePhysicsData', /** * Nodes and edges can have the physics toggles on or off. A collection of indices is created here so we can skip the check all the time. * * @private */ + }, { + key: 'updatePhysicsData', value: function updatePhysicsData() { this.physicsBody.forces = {}; this.physicsBody.physicsNodeIndices = []; @@ -33501,12 +33423,12 @@ return /******/ (function(modules) { // webpackBootstrap } } } - }, { - key: 'revert', /** * Revert the simulation one step. This is done so after stabilization, every new start of the simulation will also say stabilized. */ + }, { + key: 'revert', value: function revert() { var nodeIds = Object.keys(this.previousStates); var nodes = this.body.nodes; @@ -33530,12 +33452,12 @@ return /******/ (function(modules) { // webpackBootstrap } } } - }, { - key: '_evaluateStepQuality', /** * This compares the reference state to the current state */ + }, { + key: '_evaluateStepQuality', value: function _evaluateStepQuality() { var dx = undefined, dy = undefined, @@ -33558,13 +33480,13 @@ return /******/ (function(modules) { // webpackBootstrap } return true; } - }, { - key: 'moveNodes', /** * move the nodes one timestap and check if they are stabilized * @returns {boolean} */ + }, { + key: 'moveNodes', value: function moveNodes() { var nodeIndices = this.physicsBody.physicsNodeIndices; var maxVelocity = this.options.maxVelocity ? this.options.maxVelocity : 1e9; @@ -33586,8 +33508,6 @@ return /******/ (function(modules) { // webpackBootstrap this.adaptiveTimestepEnabled = averageNodeVelocity / nodeIndices.length < velocityAdaptiveThreshold; this.stabilized = maxNodeVelocity < this.options.minVelocity; } - }, { - key: '_performStep', /** * Perform the actual step @@ -33597,6 +33517,8 @@ return /******/ (function(modules) { // webpackBootstrap * @returns {number} * @private */ + }, { + key: '_performStep', value: function _performStep(nodeId, maxVelocity) { var node = this.body.nodes[nodeId]; var timestep = this.timestep; @@ -33613,9 +33535,9 @@ return /******/ (function(modules) { // webpackBootstrap velocities[nodeId].x = Math.abs(velocities[nodeId].x) > maxVelocity ? velocities[nodeId].x > 0 ? maxVelocity : -maxVelocity : velocities[nodeId].x; node.x += velocities[nodeId].x * timestep; // position } else { - forces[nodeId].x = 0; - velocities[nodeId].x = 0; - } + forces[nodeId].x = 0; + velocities[nodeId].x = 0; + } if (node.options.fixed.y === false) { var dy = this.modelOptions.damping * velocities[nodeId].y; // damping force @@ -33624,26 +33546,24 @@ return /******/ (function(modules) { // webpackBootstrap velocities[nodeId].y = Math.abs(velocities[nodeId].y) > maxVelocity ? velocities[nodeId].y > 0 ? maxVelocity : -maxVelocity : velocities[nodeId].y; node.y += velocities[nodeId].y * timestep; // position } else { - forces[nodeId].y = 0; - velocities[nodeId].y = 0; - } + forces[nodeId].y = 0; + velocities[nodeId].y = 0; + } var totalVelocity = Math.sqrt(Math.pow(velocities[nodeId].x, 2) + Math.pow(velocities[nodeId].y, 2)); return totalVelocity; } - }, { - key: 'calculateForces', /** * calculate the forces for one physics iteration. */ + }, { + key: 'calculateForces', value: function calculateForces() { this.gravitySolver.solve(); this.nodesSolver.solve(); this.edgesSolver.solve(); } - }, { - key: '_freezeNodes', /** * When initializing and stabilizing, we can freeze nodes with a predefined position. This greatly speeds up stabilization @@ -33651,6 +33571,8 @@ return /******/ (function(modules) { // webpackBootstrap * * @private */ + }, { + key: '_freezeNodes', value: function _freezeNodes() { var nodes = this.body.nodes; for (var id in nodes) { @@ -33663,14 +33585,14 @@ return /******/ (function(modules) { // webpackBootstrap } } } - }, { - key: '_restoreFrozenNodes', /** * Unfreezes the nodes that have been frozen by _freezeDefinedNodes. * * @private */ + }, { + key: '_restoreFrozenNodes', value: function _restoreFrozenNodes() { var nodes = this.body.nodes; for (var id in nodes) { @@ -33683,13 +33605,13 @@ return /******/ (function(modules) { // webpackBootstrap } this.freezeCache = {}; } - }, { - key: 'stabilize', /** * Find a stable position for all nodes * @private */ + }, { + key: 'stabilize', value: function stabilize() { var _this3 = this; @@ -33709,7 +33631,7 @@ return /******/ (function(modules) { // webpackBootstrap this.adaptiveTimestep = true && this.options.adaptiveTimestep; // this sets the width of all nodes initially which could be required for the avoidOverlap - this.body.emitter.emit('_resizeNodes'); + this.body.emitter.emit("_resizeNodes"); // stop the render loop this.stopSimulation(); @@ -33731,13 +33653,13 @@ return /******/ (function(modules) { // webpackBootstrap return _this3._stabilizationBatch(); }, 0); } - }, { - key: '_stabilizationBatch', /** * One batch of stabilization * @private */ + }, { + key: '_stabilizationBatch', value: function _stabilizationBatch() { var count = 0; while (this.stabilized === false && count < this.options.stabilization.updateInterval && this.stabilizationIterations < this.targetIterations) { @@ -33752,13 +33674,13 @@ return /******/ (function(modules) { // webpackBootstrap this._finalizeStabilization(); } } - }, { - key: '_finalizeStabilization', /** * Wrap up the stabilization, fit and emit the events. * @private */ + }, { + key: '_finalizeStabilization', value: function _finalizeStabilization() { this.body.emitter.emit('_allowRedraw'); if (this.options.stabilization.fit === true) { @@ -33826,8 +33748,6 @@ return /******/ (function(modules) { // webpackBootstrap var x = Math.sin(this.randomSeed++) * 10000; return x - Math.floor(x); } - }, { - key: "solve", /** * This function calculates the forces the nodes apply on eachother based on a gravitational model. @@ -33835,6 +33755,8 @@ return /******/ (function(modules) { // webpackBootstrap * * @private */ + }, { + key: "solve", value: function solve() { if (this.options.gravitationalConstant !== 0 && this.physicsBody.physicsNodeIndices.length > 0) { var node = undefined; @@ -33861,8 +33783,6 @@ return /******/ (function(modules) { // webpackBootstrap } } } - }, { - key: "_getForceContribution", /** * This function traverses the barnesHutTree. It checks when it can approximate distant nodes with their center of mass. @@ -33872,6 +33792,8 @@ return /******/ (function(modules) { // webpackBootstrap * @param node * @private */ + }, { + key: "_getForceContribution", value: function _getForceContribution(parentBranch, node) { // we get no force contribution from an empty region if (parentBranch.childrenCount > 0) { @@ -33906,8 +33828,6 @@ return /******/ (function(modules) { // webpackBootstrap } } } - }, { - key: "_calculateForces", /** * Calculate the forces based on the distance. @@ -33919,6 +33839,8 @@ return /******/ (function(modules) { // webpackBootstrap * @param parentBranch * @private */ + }, { + key: "_calculateForces", value: function _calculateForces(distance, dx, dy, node, parentBranch) { if (distance === 0) { distance = 0.1; @@ -33938,8 +33860,6 @@ return /******/ (function(modules) { // webpackBootstrap this.physicsBody.forces[node.id].x += fx; this.physicsBody.forces[node.id].y += fy; } - }, { - key: "_formBarnesHutTree", /** * This function constructs the barnesHut tree recursively. It creates the root, splits it and starts placing the nodes. @@ -33948,6 +33868,8 @@ return /******/ (function(modules) { // webpackBootstrap * @param nodeIndices * @private */ + }, { + key: "_formBarnesHutTree", value: function _formBarnesHutTree(nodes, nodeIndices) { var node = undefined; var nodeCount = nodeIndices.length; @@ -33983,9 +33905,9 @@ return /******/ (function(modules) { // webpackBootstrap maxY += 0.5 * sizeDiff; } // xSize > ySize else { - minX += 0.5 * sizeDiff; - maxX -= 0.5 * sizeDiff; - } // xSize < ySize + minX += 0.5 * sizeDiff; + maxX -= 0.5 * sizeDiff; + } // xSize < ySize var minimumTreeSize = 1e-5; var rootSize = Math.max(minimumTreeSize, Math.abs(maxX - minX)); @@ -34023,8 +33945,6 @@ return /******/ (function(modules) { // webpackBootstrap // make global return barnesHutTree; } - }, { - key: "_updateBranchMass", /** * this updates the mass of a branch. this is increased by adding a node. @@ -34033,6 +33953,8 @@ return /******/ (function(modules) { // webpackBootstrap * @param node * @private */ + }, { + key: "_updateBranchMass", value: function _updateBranchMass(parentBranch, node) { var totalMass = parentBranch.mass + node.options.mass; var totalMassInv = 1 / totalMass; @@ -34047,8 +33969,6 @@ return /******/ (function(modules) { // webpackBootstrap var biggestSize = Math.max(Math.max(node.height, node.radius), node.width); parentBranch.maxWidth = parentBranch.maxWidth < biggestSize ? biggestSize : parentBranch.maxWidth; } - }, { - key: "_placeInTree", /** * determine in which branch the node will be placed. @@ -34058,6 +33978,8 @@ return /******/ (function(modules) { // webpackBootstrap * @param skipMassUpdate * @private */ + }, { + key: "_placeInTree", value: function _placeInTree(parentBranch, node, skipMassUpdate) { if (skipMassUpdate != true || skipMassUpdate === undefined) { // update the mass of the branch. @@ -34084,8 +34006,6 @@ return /******/ (function(modules) { // webpackBootstrap } } } - }, { - key: "_placeInRegion", /** * actually place the node in a region (or branch) @@ -34095,6 +34015,8 @@ return /******/ (function(modules) { // webpackBootstrap * @param region * @private */ + }, { + key: "_placeInRegion", value: function _placeInRegion(parentBranch, node, region) { switch (parentBranch.children[region].childrenCount) { case 0: @@ -34121,8 +34043,6 @@ return /******/ (function(modules) { // webpackBootstrap break; } } - }, { - key: "_splitBranch", /** * this function splits a branch into 4 sub branches. If the branch contained a node, we place it in the subbranch @@ -34131,6 +34051,8 @@ return /******/ (function(modules) { // webpackBootstrap * @param parentBranch * @private */ + }, { + key: "_splitBranch", value: function _splitBranch(parentBranch) { // if the branch is shaded with a node, replace the node in the new subset. var containedNode = null; @@ -34151,8 +34073,6 @@ return /******/ (function(modules) { // webpackBootstrap this._placeInTree(parentBranch, containedNode); } } - }, { - key: "_insertRegion", /** * This function subdivides the region into four new segments. @@ -34164,6 +34084,8 @@ return /******/ (function(modules) { // webpackBootstrap * @param parentRange * @private */ + }, { + key: "_insertRegion", value: function _insertRegion(parentBranch, region) { var minX = undefined, maxX = undefined, @@ -34209,8 +34131,6 @@ return /******/ (function(modules) { // webpackBootstrap childrenCount: 0 }; } - }, { - key: "_debug", //--------------------------- DEBUGGING BELOW ---------------------------// @@ -34221,6 +34141,8 @@ return /******/ (function(modules) { // webpackBootstrap * @param color * @private */ + }, { + key: "_debug", value: function _debug(ctx, color) { if (this.barnesHutTree !== undefined) { @@ -34229,8 +34151,6 @@ return /******/ (function(modules) { // webpackBootstrap this._drawBranch(this.barnesHutTree.root, ctx, color); } } - }, { - key: "_drawBranch", /** * This function is for debugging purposes. It draws the branches recursively. @@ -34240,6 +34160,8 @@ return /******/ (function(modules) { // webpackBootstrap * @param color * @private */ + }, { + key: "_drawBranch", value: function _drawBranch(branch, ctx, color) { if (color === undefined) { color = "#FF0000"; @@ -34315,8 +34237,6 @@ return /******/ (function(modules) { // webpackBootstrap value: function setOptions(options) { this.options = options; } - }, { - key: "solve", /** * Calculate the forces the nodes apply on each other based on a repulsion field. @@ -34324,6 +34244,8 @@ return /******/ (function(modules) { // webpackBootstrap * * @private */ + }, { + key: "solve", value: function solve() { var dx, dy, distance, fx, fy, repulsingForce, node1, node2; @@ -34410,8 +34332,6 @@ return /******/ (function(modules) { // webpackBootstrap value: function setOptions(options) { this.options = options; } - }, { - key: "solve", /** * Calculate the forces the nodes apply on each other based on a repulsion field. @@ -34419,6 +34339,8 @@ return /******/ (function(modules) { // webpackBootstrap * * @private */ + }, { + key: "solve", value: function solve() { var dx, dy, distance, fx, fy, repulsingForce, node1, node2, i, j; @@ -34501,14 +34423,14 @@ return /******/ (function(modules) { // webpackBootstrap value: function setOptions(options) { this.options = options; } - }, { - key: "solve", /** * This function calculates the springforces on the nodes, accounting for the support nodes. * * @private */ + }, { + key: "solve", value: function solve() { var edgeLength = undefined, edge = undefined; @@ -34542,8 +34464,6 @@ return /******/ (function(modules) { // webpackBootstrap } } } - }, { - key: "_calculateSpringForce", /** * This is the code actually performing the calculation for the function above. @@ -34553,6 +34473,8 @@ return /******/ (function(modules) { // webpackBootstrap * @param edgeLength * @private */ + }, { + key: "_calculateSpringForce", value: function _calculateSpringForce(node1, node2, edgeLength) { var dx = node1.x - node2.x; var dy = node1.y - node2.y; @@ -34611,14 +34533,14 @@ return /******/ (function(modules) { // webpackBootstrap value: function setOptions(options) { this.options = options; } - }, { - key: "solve", /** * This function calculates the springforces on the nodes, accounting for the support nodes. * * @private */ + }, { + key: "solve", value: function solve() { var edgeLength, edge; var dx, dy, fx, fy, springForce, distance; @@ -34761,13 +34683,13 @@ return /******/ (function(modules) { // webpackBootstrap this._calculateForces(distance, dx, dy, forces, node); } } - }, { - key: "_calculateForces", /** * Calculate the forces based on the distance. * @private */ + }, { + key: "_calculateForces", value: function _calculateForces(distance, dx, dy, forces, node) { var gravityForce = distance === 0 ? 0 : this.options.centralGravity / distance; forces[node.id].x = dx * gravityForce; @@ -34814,19 +34736,19 @@ return /******/ (function(modules) { // webpackBootstrap _get(Object.getPrototypeOf(ForceAtlas2BasedRepulsionSolver.prototype), "constructor", this).call(this, body, physicsBody, options); } + /** + * Calculate the forces based on the distance. + * + * @param distance + * @param dx + * @param dy + * @param node + * @param parentBranch + * @private + */ + _createClass(ForceAtlas2BasedRepulsionSolver, [{ key: "_calculateForces", - - /** - * Calculate the forces based on the distance. - * - * @param distance - * @param dx - * @param dy - * @param node - * @param parentBranch - * @private - */ value: function _calculateForces(distance, dx, dy, node, parentBranch) { if (distance === 0) { distance = 0.1 * Math.random(); @@ -34888,13 +34810,13 @@ return /******/ (function(modules) { // webpackBootstrap _get(Object.getPrototypeOf(ForceAtlas2BasedCentralGravitySolver.prototype), "constructor", this).call(this, body, physicsBody, options); } + /** + * Calculate the forces based on the distance. + * @private + */ + _createClass(ForceAtlas2BasedCentralGravitySolver, [{ key: "_calculateForces", - - /** - * Calculate the forces based on the distance. - * @private - */ value: function _calculateForces(distance, dx, dy, forces, node) { if (distance > 0) { var degree = node.edges.length + 1; @@ -34956,18 +34878,18 @@ return /******/ (function(modules) { // webpackBootstrap value: function setOptions(options) { if (options !== undefined) {} } - }, { - key: 'clusterByHubsize', /** * * @param hubsize * @param options */ + }, { + key: 'clusterByHubsize', value: function clusterByHubsize(hubsize, options) { if (hubsize === undefined) { hubsize = this._getHubSize(); - } else if (typeof hubsize === 'object') { + } else if (typeof hubsize === "object") { options = this._checkOptions(hubsize); hubsize = this._getHubSize(); } @@ -34986,20 +34908,20 @@ return /******/ (function(modules) { // webpackBootstrap this.body.emitter.emit('_dataChanged'); } - }, { - key: 'cluster', /** * loop over all nodes, check if they adhere to the condition and cluster if needed. * @param options * @param refreshData */ + }, { + key: 'cluster', value: function cluster() { var options = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0]; var refreshData = arguments.length <= 1 || arguments[1] === undefined ? true : arguments[1]; if (options.joinCondition === undefined) { - throw new Error('Cannot call clusterByNodeData without a joinCondition function in the options.'); + throw new Error("Cannot call clusterByNodeData without a joinCondition function in the options."); } // check if the options object is fine, append if needed @@ -35028,8 +34950,6 @@ return /******/ (function(modules) { // webpackBootstrap this._cluster(childNodesObj, childEdgesObj, options, refreshData); } - }, { - key: 'clusterByEdgeCount', /** * Cluster all nodes in the network that have only X edges @@ -35037,6 +34957,8 @@ return /******/ (function(modules) { // webpackBootstrap * @param options * @param refreshData */ + }, { + key: 'clusterByEdgeCount', value: function clusterByEdgeCount(edgeCount, options) { var refreshData = arguments.length <= 2 || arguments[2] === undefined ? true : arguments[2]; @@ -35115,34 +35037,32 @@ return /******/ (function(modules) { // webpackBootstrap this.body.emitter.emit('_dataChanged'); } } - }, { - key: 'clusterOutliers', /** * Cluster all nodes in the network that have only 1 edge * @param options * @param refreshData */ + }, { + key: 'clusterOutliers', value: function clusterOutliers(options) { var refreshData = arguments.length <= 1 || arguments[1] === undefined ? true : arguments[1]; this.clusterByEdgeCount(1, options, refreshData); } - }, { - key: 'clusterBridges', /** * Cluster all nodes in the network that have only 2 edge * @param options * @param refreshData */ + }, { + key: 'clusterBridges', value: function clusterBridges(options) { var refreshData = arguments.length <= 1 || arguments[1] === undefined ? true : arguments[1]; this.clusterByEdgeCount(2, options, refreshData); } - }, { - key: 'clusterByConnection', /** * suck all connected nodes of a node into the node. @@ -35150,15 +35070,17 @@ return /******/ (function(modules) { // webpackBootstrap * @param options * @param refreshData */ + }, { + key: 'clusterByConnection', value: function clusterByConnection(nodeId, options) { var refreshData = arguments.length <= 2 || arguments[2] === undefined ? true : arguments[2]; // kill conditions if (nodeId === undefined) { - throw new Error('No nodeId supplied to clusterByConnection!'); + throw new Error("No nodeId supplied to clusterByConnection!"); } if (this.body.nodes[nodeId] === undefined) { - throw new Error('The nodeId given to clusterByConnection does not exist!'); + throw new Error("The nodeId given to clusterByConnection does not exist!"); } var node = this.body.nodes[nodeId]; @@ -35211,8 +35133,6 @@ return /******/ (function(modules) { // webpackBootstrap this._cluster(childNodesObj, childEdgesObj, options, refreshData); } - }, { - key: '_cloneOptions', /** * This returns a clone of the options or options of the edge or node to be used for construction of new edges or check functions for new nodes. @@ -35221,6 +35141,8 @@ return /******/ (function(modules) { // webpackBootstrap * @returns {{}} * @private */ + }, { + key: '_cloneOptions', value: function _cloneOptions(item, type) { var clonedOptions = {}; if (type === undefined || type === 'node') { @@ -35233,8 +35155,6 @@ return /******/ (function(modules) { // webpackBootstrap } return clonedOptions; } - }, { - key: '_createClusterEdges', /** * This function creates the edges that will be attached to the cluster @@ -35245,6 +35165,8 @@ return /******/ (function(modules) { // webpackBootstrap * @param options * @private */ + }, { + key: '_createClusterEdges', value: function _createClusterEdges(childNodesObj, clusterNodeProperties, clusterEdgeProperties) { var edge = undefined, childNodeId = undefined, @@ -35314,8 +35236,6 @@ return /******/ (function(modules) { // webpackBootstrap _edge.hiddenByCluster = true; } } - }, { - key: '_checkOptions', /** * This function checks the options that can be supplied to the different cluster functions @@ -35324,6 +35244,8 @@ return /******/ (function(modules) { // webpackBootstrap * @returns {*} * @private */ + }, { + key: '_checkOptions', value: function _checkOptions() { var options = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0]; @@ -35336,8 +35258,6 @@ return /******/ (function(modules) { // webpackBootstrap return options; } - }, { - key: '_cluster', /** * @@ -35347,6 +35267,8 @@ return /******/ (function(modules) { // webpackBootstrap * @param {Boolean} refreshData | when true, do not wrap up * @private */ + }, { + key: '_cluster', value: function _cluster(childNodesObj, childEdgesObj, options) { var refreshData = arguments.length <= 3 || arguments[3] === undefined ? true : arguments[3]; @@ -35382,7 +35304,7 @@ return /******/ (function(modules) { // webpackBootstrap for (var edgeId in childEdgesObj) { if (childEdgesObj.hasOwnProperty(edgeId)) { // these cluster edges will be removed on creation of the cluster. - if (edgeId.substr(0, 12) !== 'clusterEdge:') { + if (edgeId.substr(0, 12) !== "clusterEdge:") { var clonedOptions = this._cloneOptions(childEdgesObj[edgeId], 'edge'); childEdgesOptions.push(clonedOptions); } @@ -35391,7 +35313,7 @@ return /******/ (function(modules) { // webpackBootstrap clusterNodeProperties = options.processProperties(clusterNodeProperties, childNodesOptions, childEdgesOptions); if (!clusterNodeProperties) { - throw new Error('The processProperties function does not return properties!'); + throw new Error("The processProperties function does not return properties!"); } } @@ -35462,24 +35384,22 @@ return /******/ (function(modules) { // webpackBootstrap this.body.emitter.emit('_dataChanged'); } } - }, { - key: 'isCluster', /** * Check if a node is a cluster. * @param nodeId * @returns {*} */ + }, { + key: 'isCluster', value: function isCluster(nodeId) { if (this.body.nodes[nodeId] !== undefined) { return this.body.nodes[nodeId].isCluster === true; } else { - console.log('Node does not exist.'); + console.log("Node does not exist."); return false; } } - }, { - key: '_getClusterPosition', /** * get the position of the cluster node based on what's inside @@ -35487,6 +35407,8 @@ return /******/ (function(modules) { // webpackBootstrap * @returns {{x: number, y: number}} * @private */ + }, { + key: '_getClusterPosition', value: function _getClusterPosition(childNodesObj) { var childKeys = Object.keys(childNodesObj); var minX = childNodesObj[childKeys[0]].x; @@ -35504,26 +35426,26 @@ return /******/ (function(modules) { // webpackBootstrap return { x: 0.5 * (minX + maxX), y: 0.5 * (minY + maxY) }; } - }, { - key: 'openCluster', /** * Open a cluster by calling this function. * @param {String} clusterNodeId | the ID of the cluster node * @param {Boolean} refreshData | wrap up afterwards if not true */ + }, { + key: 'openCluster', value: function openCluster(clusterNodeId, options) { var refreshData = arguments.length <= 2 || arguments[2] === undefined ? true : arguments[2]; // kill conditions if (clusterNodeId === undefined) { - throw new Error('No clusterNodeId supplied to openCluster.'); + 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.'); + 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.'); + console.log("The node:" + clusterNodeId + " is not a cluster."); return; } var clusterNode = this.body.nodes[clusterNodeId]; @@ -35669,8 +35591,6 @@ return /******/ (function(modules) { // webpackBootstrap return nodesArray; } - }, { - key: 'findNode', /** * Get the stack clusterId's that a certain node resides in. cluster A -> cluster B -> cluster C -> node @@ -35678,6 +35598,8 @@ return /******/ (function(modules) { // webpackBootstrap * @returns {Array} * @private */ + }, { + key: 'findNode', value: function findNode(nodeId) { var stack = []; var max = 100; @@ -35691,8 +35613,6 @@ return /******/ (function(modules) { // webpackBootstrap stack.push(this.body.nodes[nodeId]); return stack; } - }, { - key: '_getConnectedId', /** * Get the Id the node is connected to @@ -35701,6 +35621,8 @@ return /******/ (function(modules) { // webpackBootstrap * @returns {*} * @private */ + }, { + key: '_getConnectedId', value: function _getConnectedId(edge, nodeId) { if (edge.toId != nodeId) { return edge.toId; @@ -35710,8 +35632,6 @@ return /******/ (function(modules) { // webpackBootstrap return edge.fromId; } } - }, { - key: '_getHubSize', /** * We determine how many connections denote an important hub. @@ -35719,6 +35639,8 @@ return /******/ (function(modules) { // webpackBootstrap * * @private */ + }, { + key: '_getHubSize', value: function _getHubSize() { var average = 0; var averageSquared = 0; @@ -35777,12 +35699,12 @@ return /******/ (function(modules) { // webpackBootstrap var _Node2 = __webpack_require__(62); - var _Node3 = _interopRequireDefault(_Node2); - /** * */ + var _Node3 = _interopRequireDefault(_Node2); + var Cluster = (function (_Node) { _inherits(Cluster, _Node); @@ -35854,33 +35776,33 @@ return /******/ (function(modules) { // webpackBootstrap value: function bindEventListeners() { var _this = this; - this.body.emitter.on('dragStart', function () { + this.body.emitter.on("dragStart", function () { _this.dragging = true; }); - this.body.emitter.on('dragEnd', function () { + this.body.emitter.on("dragEnd", function () { return _this.dragging = false; }); - this.body.emitter.on('_resizeNodes', function () { + this.body.emitter.on("_resizeNodes", function () { return _this._resizeNodes(); }); - this.body.emitter.on('_redraw', function () { + this.body.emitter.on("_redraw", function () { if (_this.renderingActive === false) { _this._redraw(); } }); - this.body.emitter.on('_blockRedraw', function () { + this.body.emitter.on("_blockRedraw", function () { _this.allowRedraw = false; }); - this.body.emitter.on('_allowRedraw', function () { + this.body.emitter.on("_allowRedraw", function () { _this.allowRedraw = true;_this.redrawRequested = false; }); - this.body.emitter.on('_requestRedraw', this._requestRedraw.bind(this)); - this.body.emitter.on('_startRendering', function () { + this.body.emitter.on("_requestRedraw", this._requestRedraw.bind(this)); + this.body.emitter.on("_startRendering", function () { _this.renderRequests += 1; _this.renderingActive = true; _this._startRendering(); }); - this.body.emitter.on('_stopRendering', function () { + this.body.emitter.on("_stopRendering", function () { _this.renderRequests -= 1; _this.renderingActive = _this.renderRequests > 0; _this.renderTimer = undefined; @@ -35913,8 +35835,8 @@ return /******/ (function(modules) { // webpackBootstrap if (this.requiresTimeout === true) { this.renderTimer = window.setTimeout(this._renderStep.bind(this), this.simulationInterval); // wait this.renderTimeStep milliseconds and perform the animation step function } else { - this.renderTimer = window.requestAnimationFrame(this._renderStep.bind(this)); // wait this.renderTimeStep milliseconds and perform the animation step function - } + this.renderTimer = window.requestAnimationFrame(this._renderStep.bind(this)); // wait this.renderTimeStep milliseconds and perform the animation step function + } } } } @@ -35938,25 +35860,25 @@ return /******/ (function(modules) { // webpackBootstrap } } } - }, { - key: 'redraw', /** * Redraw the network with the current data * chart will be resized too. */ + }, { + key: 'redraw', value: function redraw() { this.body.emitter.emit('setSize'); this._redraw(); } - }, { - key: '_requestRedraw', /** * Redraw the network with the current data * @param hidden | used to get the first estimate of the node sizes. only the nodes are drawn after which they are quickly drawn over. * @private */ + }, { + key: '_requestRedraw', value: function _requestRedraw() { var _this2 = this; @@ -35979,7 +35901,7 @@ return /******/ (function(modules) { // webpackBootstrap var hidden = arguments.length <= 0 || arguments[0] === undefined ? false : arguments[0]; if (this.allowRedraw === true) { - this.body.emitter.emit('initRedraw'); + this.body.emitter.emit("initRedraw"); this.redrawRequested = false; var ctx = this.canvas.frame.canvas.getContext('2d'); @@ -35989,9 +35911,7 @@ return /******/ (function(modules) { // webpackBootstrap this.canvas.setSize(); } - if (this.pixelRatio === undefined) { - this.pixelRatio = (window.devicePixelRatio || 1) / (ctx.webkitBackingStorePixelRatio || ctx.mozBackingStorePixelRatio || ctx.msBackingStorePixelRatio || ctx.oBackingStorePixelRatio || ctx.backingStorePixelRatio || 1); - } + this.pixelRatio = (window.devicePixelRatio || 1) / (ctx.webkitBackingStorePixelRatio || ctx.mozBackingStorePixelRatio || ctx.msBackingStorePixelRatio || ctx.oBackingStorePixelRatio || ctx.backingStorePixelRatio || 1); ctx.setTransform(this.pixelRatio, 0, 0, this.pixelRatio, 0, 0); @@ -36006,7 +35926,7 @@ return /******/ (function(modules) { // webpackBootstrap ctx.scale(this.body.view.scale, this.body.view.scale); ctx.beginPath(); - this.body.emitter.emit('beforeDrawing', ctx); + this.body.emitter.emit("beforeDrawing", ctx); ctx.closePath(); if (hidden === false) { @@ -36025,7 +35945,7 @@ return /******/ (function(modules) { // webpackBootstrap ctx.beginPath(); //this.physics.nodesSolver._debug(ctx,"#F00F0F"); - this.body.emitter.emit('afterDrawing', ctx); + this.body.emitter.emit("afterDrawing", ctx); ctx.closePath(); // restore original scaling and translation ctx.restore(); @@ -36035,8 +35955,6 @@ return /******/ (function(modules) { // webpackBootstrap } } } - }, { - key: '_resizeNodes', /** * Redraw all nodes @@ -36045,6 +35963,8 @@ return /******/ (function(modules) { // webpackBootstrap * @param {Boolean} [alwaysShow] * @private */ + }, { + key: '_resizeNodes', value: function _resizeNodes() { var ctx = this.canvas.frame.canvas.getContext('2d'); if (this.pixelRatio === undefined) { @@ -36070,8 +35990,6 @@ return /******/ (function(modules) { // webpackBootstrap // restore original scaling and translation ctx.restore(); } - }, { - key: '_drawNodes', /** * Redraw all nodes @@ -36080,6 +35998,8 @@ return /******/ (function(modules) { // webpackBootstrap * @param {Boolean} [alwaysShow] * @private */ + }, { + key: '_drawNodes', value: function _drawNodes(ctx) { var alwaysShow = arguments.length <= 1 || arguments[1] === undefined ? false : arguments[1]; @@ -36118,8 +36038,6 @@ return /******/ (function(modules) { // webpackBootstrap node.draw(ctx); } } - }, { - key: '_drawEdges', /** * Redraw all edges @@ -36127,6 +36045,8 @@ return /******/ (function(modules) { // webpackBootstrap * @param {CanvasRenderingContext2D} ctx * @private */ + }, { + key: '_drawEdges', value: function _drawEdges(ctx) { var edges = this.body.edges; var edgeIndices = this.body.edgeIndices; @@ -36139,8 +36059,6 @@ return /******/ (function(modules) { // webpackBootstrap } } } - }, { - key: '_drawControlNodes', /** * Redraw all edges @@ -36148,6 +36066,8 @@ return /******/ (function(modules) { // webpackBootstrap * @param {CanvasRenderingContext2D} ctx * @private */ + }, { + key: '_drawControlNodes', value: function _drawControlNodes(ctx) { var edges = this.body.edges; var edgeIndices = this.body.edgeIndices; @@ -36158,14 +36078,14 @@ return /******/ (function(modules) { // webpackBootstrap edge._drawControlNodes(ctx); } } - }, { - key: '_determineBrowserMethod', /** * Determine if the browser requires a setTimeout or a requestAnimationFrame. This was required because * some implementations (safari and IE9) did not support requestAnimationFrame * @private */ + }, { + key: '_determineBrowserMethod', value: function _determineBrowserMethod() { if (typeof window !== 'undefined') { var browserType = navigator.userAgent.toLowerCase(); @@ -36245,7 +36165,7 @@ return /******/ (function(modules) { // webpackBootstrap var _this = this; // bind the events - this.body.emitter.once('resize', function (obj) { + this.body.emitter.once("resize", function (obj) { if (obj.width !== 0) { _this.body.view.translation.x = obj.width * 0.5; } @@ -36253,8 +36173,8 @@ return /******/ (function(modules) { // webpackBootstrap _this.body.view.translation.y = obj.height * 0.5; } }); - this.body.emitter.on('setSize', this.setSize.bind(this)); - this.body.emitter.on('destroy', function () { + this.body.emitter.on("setSize", this.setSize.bind(this)); + this.body.emitter.on("destroy", function () { _this.hammerFrame.destroy(); _this.hammer.destroy(); _this._cleanUp(); @@ -36276,7 +36196,7 @@ return /******/ (function(modules) { // webpackBootstrap this.resizeTimer = setInterval(function () { var changed = _this2.setSize(); if (changed === true) { - _this2.body.emitter.emit('_requestRedraw'); + _this2.body.emitter.emit("_requestRedraw"); } }, 1000); this.resizeFunction = this._onResize.bind(this); @@ -36297,39 +36217,42 @@ return /******/ (function(modules) { // webpackBootstrap key: '_onResize', value: function _onResize() { this.setSize(); - this.body.emitter.emit('_redraw'); + this.body.emitter.emit("_redraw"); } - }, { - key: '_getCameraState', /** * Get and store the cameraState * @private */ + }, { + key: '_getCameraState', value: function _getCameraState() { - this.cameraState.previousWidth = this.frame.canvas.width; + var pixelRatio = arguments.length <= 0 || arguments[0] === undefined ? this.pixelRatio : arguments[0]; + + this.cameraState.previousWidth = this.frame.canvas.width / pixelRatio; this.cameraState.scale = this.body.view.scale; - this.cameraState.position = this.DOMtoCanvas({ x: 0.5 * this.frame.canvas.width, y: 0.5 * this.frame.canvas.height }); + this.cameraState.position = this.DOMtoCanvas({ x: 0.5 * this.frame.canvas.width / pixelRatio, y: 0.5 * this.frame.canvas.height / pixelRatio }); } - }, { - key: '_setCameraState', /** * Set the cameraState * @private */ + }, { + key: '_setCameraState', value: function _setCameraState() { if (this.cameraState.scale !== undefined) { - this.body.view.scale = this.body.view.scale * (this.frame.canvas.clientWidth / this.cameraState.previousWidth); + this.body.view.scale = this.cameraState.scale * (this.frame.canvas.width / this.pixelRatio / this.cameraState.previousWidth); // this comes from the view module. - var viewCenter = this.DOMtoCanvas({ + var currentViewCenter = this.DOMtoCanvas({ x: 0.5 * this.frame.canvas.clientWidth, y: 0.5 * this.frame.canvas.clientHeight }); + var distanceFromCenter = { // offset from view, distance view has to change by these x and y to center the node - x: viewCenter.x - this.cameraState.position.x, - y: viewCenter.y - this.cameraState.position.y + x: currentViewCenter.x - this.cameraState.position.x, + y: currentViewCenter.y - this.cameraState.position.y }; this.body.view.translation.x += distanceFromCenter.x * this.body.view.scale; this.body.view.translation.y += distanceFromCenter.y * this.body.view.scale; @@ -36347,14 +36270,14 @@ return /******/ (function(modules) { // webpackBootstrap return value + 'px'; } } - throw new Error('Could not use the value supplie for width or height:' + value); + throw new Error('Could not use the value supplied for width or height:' + value); } - }, { - key: '_create', /** * Create the HTML */ + }, { + key: '_create', value: function _create() { // remove all elements from the container element. while (this.body.container.hasChildNodes()) { @@ -36369,7 +36292,7 @@ return /******/ (function(modules) { // webpackBootstrap ////////////////////////////////////////////////////////////////// - this.frame.canvas = document.createElement('canvas'); + this.frame.canvas = document.createElement("canvas"); this.frame.canvas.style.position = 'relative'; this.frame.appendChild(this.frame.canvas); @@ -36381,10 +36304,10 @@ return /******/ (function(modules) { // webpackBootstrap noCanvas.innerHTML = 'Error: your browser does not support HTML canvas'; this.frame.canvas.appendChild(noCanvas); } else { - var ctx = this.frame.canvas.getContext('2d'); + var ctx = this.frame.canvas.getContext("2d"); this.pixelRatio = (window.devicePixelRatio || 1) / (ctx.webkitBackingStorePixelRatio || ctx.mozBackingStorePixelRatio || ctx.msBackingStorePixelRatio || ctx.oBackingStorePixelRatio || ctx.backingStorePixelRatio || 1); - this.frame.canvas.getContext('2d').setTransform(this.pixelRatio, 0, 0, this.pixelRatio, 0, 0); + this.frame.canvas.getContext("2d").setTransform(this.pixelRatio, 0, 0, this.pixelRatio, 0, 0); } // add the frame to the container element @@ -36395,13 +36318,13 @@ return /******/ (function(modules) { // webpackBootstrap this._bindHammer(); } - }, { - key: '_bindHammer', /** * This function binds hammer, it can be repeated over and over due to the uniqueness check. * @private */ + }, { + key: '_bindHammer', value: function _bindHammer() { var _this3 = this; @@ -36462,8 +36385,6 @@ return /******/ (function(modules) { // webpackBootstrap _this3.body.eventListeners.onRelease(event); }); } - }, { - key: 'setSize', /** * Set a new size for the network @@ -36472,11 +36393,12 @@ return /******/ (function(modules) { // webpackBootstrap * @param {string} height Height in pixels or percentage (for example '400px' * or '30%') */ + }, { + key: 'setSize', value: function setSize() { var width = arguments.length <= 0 || arguments[0] === undefined ? this.options.width : arguments[0]; var height = arguments.length <= 1 || arguments[1] === undefined ? this.options.height : arguments[1]; - this._getCameraState(); width = this._prepareValue(width); height = this._prepareValue(height); @@ -36484,7 +36406,14 @@ return /******/ (function(modules) { // webpackBootstrap var oldWidth = this.frame.canvas.width; var oldHeight = this.frame.canvas.height; + // update the pixelratio + var ctx = this.frame.canvas.getContext("2d"); + var previousRation = this.pixelRatio; // we cache this because the camera state storage needs the old value + this.pixelRatio = (window.devicePixelRatio || 1) / (ctx.webkitBackingStorePixelRatio || ctx.mozBackingStorePixelRatio || ctx.msBackingStorePixelRatio || ctx.oBackingStorePixelRatio || ctx.backingStorePixelRatio || 1); + if (width != this.options.width || height != this.options.height || this.frame.style.width != width || this.frame.style.height != height) { + this._getCameraState(previousRation); + this.frame.style.width = width; this.frame.style.height = height; @@ -36502,6 +36431,11 @@ return /******/ (function(modules) { // webpackBootstrap // this would adapt the width of the canvas to the width from 100% if and only if // there is a change. + // store the camera if there is a change in size. + if (this.frame.canvas.width != Math.round(this.frame.canvas.clientWidth * this.pixelRatio) || this.frame.canvas.height != Math.round(this.frame.canvas.clientHeight * this.pixelRatio)) { + this._getCameraState(previousRation); + } + if (this.frame.canvas.width != Math.round(this.frame.canvas.clientWidth * this.pixelRatio)) { this.frame.canvas.width = Math.round(this.frame.canvas.clientWidth * this.pixelRatio); emitEvent = true; @@ -36519,8 +36453,11 @@ return /******/ (function(modules) { // webpackBootstrap oldWidth: Math.round(oldWidth / this.pixelRatio), oldHeight: Math.round(oldHeight / this.pixelRatio) }); + + // restore the camera on change. + this._setCameraState(); } - this._setCameraState(); + return emitEvent; } }, { @@ -36536,8 +36473,6 @@ return /******/ (function(modules) { // webpackBootstrap value: function _XconvertDOMtoCanvas(x) { return (x - this.body.view.translation.x) / this.body.view.scale; } - }, { - key: '_XconvertCanvasToDOM', /** * Convert the X coordinate in canvas-space (the simulation sandbox, which the camera looks upon) to @@ -36546,11 +36481,11 @@ return /******/ (function(modules) { // webpackBootstrap * @returns {number} * @private */ + }, { + key: '_XconvertCanvasToDOM', value: function _XconvertCanvasToDOM(x) { return x * this.body.view.scale + this.body.view.translation.x; } - }, { - key: '_YconvertDOMtoCanvas', /** * Convert the Y coordinate in DOM-space (coordinate point in browser relative to the container div) to @@ -36559,11 +36494,11 @@ return /******/ (function(modules) { // webpackBootstrap * @returns {number} * @private */ + }, { + key: '_YconvertDOMtoCanvas', value: function _YconvertDOMtoCanvas(y) { return (y - this.body.view.translation.y) / this.body.view.scale; } - }, { - key: '_YconvertCanvasToDOM', /** * Convert the Y coordinate in canvas-space (the simulation sandbox, which the camera looks upon) to @@ -36572,11 +36507,11 @@ return /******/ (function(modules) { // webpackBootstrap * @returns {number} * @private */ + }, { + key: '_YconvertCanvasToDOM', value: function _YconvertCanvasToDOM(y) { return y * this.body.view.scale + this.body.view.translation.y; } - }, { - key: 'canvasToDOM', /** * @@ -36584,11 +36519,11 @@ return /******/ (function(modules) { // webpackBootstrap * @returns {{x: number, y: number}} * @constructor */ + }, { + key: 'canvasToDOM', value: function canvasToDOM(pos) { return { x: this._XconvertCanvasToDOM(pos.x), y: this._YconvertCanvasToDOM(pos.y) }; } - }, { - key: 'DOMtoCanvas', /** * @@ -36596,6 +36531,8 @@ return /******/ (function(modules) { // webpackBootstrap * @returns {{x: number, y: number}} * @constructor */ + }, { + key: 'DOMtoCanvas', value: function DOMtoCanvas(pos) { return { x: this._XconvertDOMtoCanvas(pos.x), y: this._YconvertDOMtoCanvas(pos.y) }; } @@ -36611,15 +36548,21 @@ return /******/ (function(modules) { // webpackBootstrap /* 103 */ /***/ function(module, exports, __webpack_require__) { - "use strict"; + 'use strict'; - Object.defineProperty(exports, "__esModule", { + Object.defineProperty(exports, '__esModule', { 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 _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } + + function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } + + var _NetworkUtil = __webpack_require__(104); + + var _NetworkUtil2 = _interopRequireDefault(_NetworkUtil); var util = __webpack_require__(1); @@ -36653,92 +36596,29 @@ return /******/ (function(modules) { // webpackBootstrap } _createClass(View, [{ - key: "setOptions", + key: 'setOptions', value: function setOptions() { var options = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0]; this.options = options; } - }, { - key: "_getRange", - - /** - * Find the center position of the network - * @private - */ - value: function _getRange() { - var specificNodes = arguments.length <= 0 || arguments[0] === undefined ? [] : arguments[0]; - - var minY = 1e9, - maxY = -1e9, - minX = 1e9, - maxX = -1e9, - node; - if (specificNodes.length > 0) { - for (var i = 0; i < specificNodes.length; i++) { - node = this.body.nodes[specificNodes[i]]; - if (minX > node.shape.boundingBox.left) { - minX = node.shape.boundingBox.left; - } - if (maxX < node.shape.boundingBox.right) { - maxX = node.shape.boundingBox.right; - } - if (minY > node.shape.boundingBox.top) { - minY = node.shape.boundingBox.top; - } // top is negative, bottom is positive - if (maxY < node.shape.boundingBox.bottom) { - maxY = node.shape.boundingBox.bottom; - } // top is negative, bottom is positive - } - } else { - for (var i = 0; i < this.body.nodeIndices.length; i++) { - node = this.body.nodes[this.body.nodeIndices[i]]; - if (minX > node.shape.boundingBox.left) { - minX = node.shape.boundingBox.left; - } - if (maxX < node.shape.boundingBox.right) { - maxX = node.shape.boundingBox.right; - } - if (minY > node.shape.boundingBox.top) { - minY = node.shape.boundingBox.top; - } // top is negative, bottom is positive - if (maxY < node.shape.boundingBox.bottom) { - maxY = node.shape.boundingBox.bottom; - } // top is negative, bottom is positive - } - } - - if (minX === 1e9 && maxX === -1e9 && minY === 1e9 && maxY === -1e9) { - minY = 0, maxY = 0, minX = 0, maxX = 0; - } - return { minX: minX, maxX: maxX, minY: minY, maxY: maxY }; - } - }, { - key: "_findCenter", - - /** - * @param {object} range = {minX: minX, maxX: maxX, minY: minY, maxY: maxY}; - * @returns {{x: number, y: number}} - * @private - */ - value: function _findCenter(range) { - return { x: 0.5 * (range.maxX + range.minX), - y: 0.5 * (range.maxY + range.minY) }; - } - }, { - key: "fit", /** * This function zooms out to fit all data on screen based on amount of nodes * @param {Object} Options * @param {Boolean} [initialZoom] | zoom based on fitted formula or range, true = fitted, default = false; */ + }, { + key: 'fit', value: function fit() { var options = arguments.length <= 0 || arguments[0] === undefined ? { nodes: [] } : arguments[0]; var initialZoom = arguments.length <= 1 || arguments[1] === undefined ? false : arguments[1]; - var range; - var zoomLevel; + var range = undefined; + var zoomLevel = undefined; + if (options.nodes === undefined || options.nodes.length === 0) { + options.nodes = this.body.nodeIndices; + } if (initialZoom === true) { // check if more than half of the nodes have a predefined position. If so, we use the range, not the approximation. @@ -36756,7 +36636,7 @@ return /******/ (function(modules) { // webpackBootstrap return; } - range = this._getRange(options.nodes); + range = _NetworkUtil2['default']._getRange(this.body.nodes, options.nodes); var numberOfNodes = this.body.nodeIndices.length; zoomLevel = 12.662 / (numberOfNodes + 7.4147) + 0.0964822; // this is obtained from fitting a dataset from 5 points with scale levels that looked good. @@ -36766,7 +36646,7 @@ return /******/ (function(modules) { // webpackBootstrap zoomLevel *= factor; } else { this.body.emitter.emit("_resizeNodes"); - range = this._getRange(options.nodes); + range = _NetworkUtil2['default']._getRange(this.body.nodes, options.nodes); var xDistance = Math.abs(range.maxX - range.minX) * 1.1; var yDistance = Math.abs(range.maxY - range.minY) * 1.1; @@ -36783,12 +36663,10 @@ return /******/ (function(modules) { // webpackBootstrap zoomLevel = 1.0; } - var center = this._findCenter(range); + var center = _NetworkUtil2['default']._findCenter(range); var animationOptions = { position: center, scale: zoomLevel, animation: options.animation }; this.moveTo(animationOptions); } - }, { - key: "focus", // animation @@ -36798,6 +36676,8 @@ return /******/ (function(modules) { // webpackBootstrap * @param {Number} nodeId * @param {Number} [options] */ + }, { + key: 'focus', value: function focus(nodeId) { var options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1]; @@ -36811,8 +36691,6 @@ return /******/ (function(modules) { // webpackBootstrap console.log("Node: " + nodeId + " cannot be found."); } } - }, { - key: "moveTo", /** * @@ -36821,6 +36699,8 @@ return /******/ (function(modules) { // webpackBootstrap * | options.position = {x:Number, y:Number} // position to move to * | options.animation = {duration:Number, easingFunction:String} || Boolean // position to move to */ + }, { + key: 'moveTo', value: function moveTo(options) { if (options === undefined) { options = {}; @@ -36859,8 +36739,6 @@ return /******/ (function(modules) { // webpackBootstrap this.animateView(options); } - }, { - key: "animateView", /** * @@ -36873,6 +36751,8 @@ return /******/ (function(modules) { // webpackBootstrap * // easeInQuart, easeOutQuart, easeInOutQuart, * // easeInQuint, easeOutQuint, easeInOutQuint */ + }, { + key: 'animateView', value: function animateView(options) { if (options === undefined) { return; @@ -36927,13 +36807,13 @@ return /******/ (function(modules) { // webpackBootstrap this.body.emitter.emit("_startRendering"); } } - }, { - key: "_lockedRedraw", /** * used to animate smoothly by hijacking the redraw function. * @private */ + }, { + key: '_lockedRedraw', value: function _lockedRedraw() { var nodePosition = { x: this.body.nodes[this.lockedOnNodeId].x, y: this.body.nodes[this.lockedOnNodeId].y }; var viewCenter = this.canvas.DOMtoCanvas({ x: 0.5 * this.canvas.frame.canvas.clientWidth, y: 0.5 * this.canvas.frame.canvas.clientHeight }); @@ -36950,7 +36830,7 @@ return /******/ (function(modules) { // webpackBootstrap this.body.view.translation = targetTranslation; } }, { - key: "releaseNode", + key: 'releaseNode', value: function releaseNode() { if (this.lockedOnNodeId !== undefined && this.viewFunction !== undefined) { this.body.emitter.off("initRedraw", this.viewFunction); @@ -36958,14 +36838,14 @@ return /******/ (function(modules) { // webpackBootstrap this.lockedOnNodeOffset = undefined; } } - }, { - key: "_transitionRedraw", /** * * @param easingTime * @private */ + }, { + key: '_transitionRedraw', value: function _transitionRedraw() { var finished = arguments.length <= 0 || arguments[0] === undefined ? false : arguments[0]; @@ -36992,12 +36872,12 @@ return /******/ (function(modules) { // webpackBootstrap } } }, { - key: "getScale", + key: 'getScale', value: function getScale() { return this.body.view.scale; } }, { - key: "getViewPosition", + key: 'getViewPosition', value: function getViewPosition() { return this.canvas.DOMtoCanvas({ x: 0.5 * this.canvas.frame.canvas.clientWidth, y: 0.5 * this.canvas.frame.canvas.clientHeight }); } @@ -37006,11 +36886,126 @@ return /******/ (function(modules) { // webpackBootstrap return View; })(); - exports["default"] = View; - module.exports = exports["default"]; + exports['default'] = View; + module.exports = exports['default']; /***/ }, /* 104 */ +/***/ function(module, exports) { + + "use strict"; + + Object.defineProperty(exports, "__esModule", { + 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; }; })(); + + function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + + var NetworkUtil = (function () { + function NetworkUtil() { + _classCallCheck(this, NetworkUtil); + } + + /** + * Find the center position of the network considering the bounding boxes + * @private + */ + + _createClass(NetworkUtil, null, [{ + key: "_getRange", + value: function _getRange(allNodes) { + var specificNodes = arguments.length <= 1 || arguments[1] === undefined ? [] : arguments[1]; + + var minY = 1e9, + maxY = -1e9, + minX = 1e9, + maxX = -1e9, + node; + if (specificNodes.length > 0) { + for (var i = 0; i < specificNodes.length; i++) { + node = allNodes[specificNodes[i]]; + if (minX > node.shape.boundingBox.left) { + minX = node.shape.boundingBox.left; + } + if (maxX < node.shape.boundingBox.right) { + maxX = node.shape.boundingBox.right; + } + if (minY > node.shape.boundingBox.top) { + minY = node.shape.boundingBox.top; + } // top is negative, bottom is positive + if (maxY < node.shape.boundingBox.bottom) { + maxY = node.shape.boundingBox.bottom; + } // top is negative, bottom is positive + } + } + + if (minX === 1e9 && maxX === -1e9 && minY === 1e9 && maxY === -1e9) { + minY = 0, maxY = 0, minX = 0, maxX = 0; + } + return { minX: minX, maxX: maxX, minY: minY, maxY: maxY }; + } + + /** + * Find the center position of the network + * @private + */ + }, { + key: "_getRangeCore", + value: function _getRangeCore(allNodes) { + var specificNodes = arguments.length <= 1 || arguments[1] === undefined ? [] : arguments[1]; + + var minY = 1e9, + maxY = -1e9, + minX = 1e9, + maxX = -1e9, + node; + if (specificNodes.length > 0) { + for (var i = 0; i < specificNodes.length; i++) { + node = allNodes[specificNodes[i]]; + if (minX > node.x) { + minX = node.x; + } + if (maxX < node.x) { + maxX = node.x; + } + if (minY > node.y) { + minY = node.y; + } // top is negative, bottom is positive + if (maxY < node.y) { + maxY = node.y; + } // top is negative, bottom is positive + } + } + + if (minX === 1e9 && maxX === -1e9 && minY === 1e9 && maxY === -1e9) { + minY = 0, maxY = 0, minX = 0, maxX = 0; + } + return { minX: minX, maxX: maxX, minY: minY, maxY: maxY }; + } + + /** + * @param {object} range = {minX: minX, maxX: maxX, minY: minY, maxY: maxY}; + * @returns {{x: number, y: number}} + * @private + */ + }, { + key: "_findCenter", + value: function _findCenter(range) { + return { x: 0.5 * (range.maxX + range.minX), + y: 0.5 * (range.maxY + range.minY) }; + } + }]); + + return NetworkUtil; + })(); + + exports["default"] = NetworkUtil; + module.exports = exports["default"]; + +/***/ }, +/* 105 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; @@ -37025,11 +37020,11 @@ return /******/ (function(modules) { // webpackBootstrap function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } - var _componentsNavigationHandler = __webpack_require__(105); + var _componentsNavigationHandler = __webpack_require__(106); var _componentsNavigationHandler2 = _interopRequireDefault(_componentsNavigationHandler); - var _componentsPopup = __webpack_require__(106); + var _componentsPopup = __webpack_require__(107); var _componentsPopup2 = _interopRequireDefault(_componentsPopup); @@ -37117,8 +37112,6 @@ return /******/ (function(modules) { // webpackBootstrap this.navigationHandler.setOptions(this.options); } - }, { - key: 'getPointer', /** * Get the pointer location from a touch location @@ -37126,20 +37119,22 @@ return /******/ (function(modules) { // webpackBootstrap * @return {{x: Number, y: Number}} pointer * @private */ + }, { + key: 'getPointer', value: function getPointer(touch) { return { x: touch.x - util.getAbsoluteLeft(this.canvas.frame.canvas), y: touch.y - util.getAbsoluteTop(this.canvas.frame.canvas) }; } - }, { - key: 'onTouch', /** * On start of a touch gesture, store the pointer * @param event * @private */ + }, { + key: 'onTouch', value: function onTouch(event) { if (new Date().valueOf() - this.touchTime > 50) { this.drag.pointer = this.getPointer(event.center); @@ -37149,13 +37144,13 @@ return /******/ (function(modules) { // webpackBootstrap this.touchTime = new Date().valueOf(); } } - }, { - key: 'onTap', /** * handle tap/click event: select/unselect a node * @private */ + }, { + key: 'onTap', value: function onTap(event) { var pointer = this.getPointer(event.center); var multiselect = this.selectionHandler.options.multiselect && (event.changedPointers[0].ctrlKey || event.changedPointers[0].metaKey); @@ -37163,24 +37158,24 @@ return /******/ (function(modules) { // webpackBootstrap this.checkSelectionChanges(pointer, event, multiselect); this.selectionHandler._generateClickEvent('click', event, pointer); } - }, { - key: 'onDoubleTap', /** * handle doubletap event * @private */ + }, { + key: 'onDoubleTap', value: function onDoubleTap(event) { var pointer = this.getPointer(event.center); this.selectionHandler._generateClickEvent('doubleClick', event, pointer); } - }, { - key: 'onHold', /** * handle long tap event: multi select nodes * @private */ + }, { + key: 'onHold', value: function onHold(event) { var pointer = this.getPointer(event.center); var multiselect = this.selectionHandler.options.multiselect; @@ -37190,14 +37185,14 @@ return /******/ (function(modules) { // webpackBootstrap this.selectionHandler._generateClickEvent('click', event, pointer); this.selectionHandler._generateClickEvent('hold', event, pointer); } - }, { - key: 'onRelease', /** * handle the release of the screen * * @private */ + }, { + key: 'onRelease', value: function onRelease(event) { if (new Date().valueOf() - this.touchTime > 10) { var pointer = this.getPointer(event.center); @@ -37212,14 +37207,14 @@ return /******/ (function(modules) { // webpackBootstrap var pointer = this.getPointer({ x: event.clientX, y: event.clientY }); this.selectionHandler._generateClickEvent('oncontext', event, pointer); } - }, { - key: 'checkSelectionChanges', /** * * @param pointer * @param add */ + }, { + key: 'checkSelectionChanges', value: function checkSelectionChanges(pointer, event) { var add = arguments.length <= 2 || arguments[2] === undefined ? false : arguments[2]; @@ -37280,8 +37275,6 @@ return /******/ (function(modules) { // webpackBootstrap this.selectionHandler._generateClickEvent('select', event, pointer); } } - }, { - key: '_determineIfDifferent', /** * This function checks if the nodes and edges previously selected have changed. @@ -37290,6 +37283,8 @@ return /******/ (function(modules) { // webpackBootstrap * @returns {{nodesChanges: boolean, edgesChanges: boolean}} * @private */ + }, { + key: '_determineIfDifferent', value: function _determineIfDifferent(previousSelection, currentSelection) { var nodesChanges = false; var edgesChanges = false; @@ -37317,8 +37312,6 @@ return /******/ (function(modules) { // webpackBootstrap return { nodesChanges: nodesChanges, edgesChanges: edgesChanges }; } - }, { - key: 'onDragStart', /** * This function is called by onDragStart. @@ -37326,6 +37319,8 @@ return /******/ (function(modules) { // webpackBootstrap * * @private */ + }, { + key: 'onDragStart', value: function onDragStart(event) { //in case the touch event was triggered on an external div, do the initial touch now. if (this.drag.pointer === undefined) { @@ -37378,13 +37373,13 @@ return /******/ (function(modules) { // webpackBootstrap this.selectionHandler._generateClickEvent('dragStart', event, this.drag.pointer, undefined, true); } } - }, { - key: 'onDrag', /** * handle drag event * @private */ + }, { + key: 'onDrag', value: function onDrag(event) { var _this2 = this; @@ -37440,13 +37435,13 @@ return /******/ (function(modules) { // webpackBootstrap } } } - }, { - key: 'onDragEnd', /** * handle drag start event * @private */ + }, { + key: 'onDragEnd', value: function onDragEnd(event) { this.drag.dragging = false; var selection = this.drag.selection; @@ -37463,14 +37458,14 @@ return /******/ (function(modules) { // webpackBootstrap this.body.emitter.emit('_requestRedraw'); } } - }, { - key: 'onPinch', /** * Handle pinch event * @param event * @private */ + }, { + key: 'onPinch', value: function onPinch(event) { var pointer = this.getPointer(event.center); @@ -37483,8 +37478,6 @@ return /******/ (function(modules) { // webpackBootstrap var scale = this.pinch.scale * event.scale; this.zoom(scale, pointer); } - }, { - key: 'zoom', /** * Zoom the network in or out @@ -37493,6 +37486,8 @@ return /******/ (function(modules) { // webpackBootstrap * @return {Number} appliedScale scale is limited within the boundaries * @private */ + }, { + key: 'zoom', value: function zoom(scale, pointer) { if (this.options.zoomView === true) { var scaleOld = this.body.view.scale; @@ -37534,8 +37529,6 @@ return /******/ (function(modules) { // webpackBootstrap } } } - }, { - key: 'onMouseWheel', /** * Event handler for mouse wheel event, used to zoom the timeline @@ -37544,6 +37537,8 @@ return /******/ (function(modules) { // webpackBootstrap * @param {MouseEvent} event * @private */ + }, { + key: 'onMouseWheel', value: function onMouseWheel(event) { // retrieve delta var delta = 0; @@ -37580,14 +37575,14 @@ return /******/ (function(modules) { // webpackBootstrap // Prevent default actions caused by mouse wheel. event.preventDefault(); } - }, { - key: 'onMouseMove', /** * Mouse move handler for checking whether the title moves over a node with a title. * @param {Event} event * @private */ + }, { + key: 'onMouseMove', value: function onMouseMove(event) { var _this3 = this; @@ -37638,8 +37633,6 @@ return /******/ (function(modules) { // webpackBootstrap this.selectionHandler.hoverObject(obj); } } - }, { - key: '_checkShowPopup', /** * Check if there is an element on the given position in the network @@ -37649,6 +37642,8 @@ return /******/ (function(modules) { // webpackBootstrap * @param {{x:Number, y:Number}} pointer * @private */ + }, { + key: '_checkShowPopup', value: function _checkShowPopup(pointer) { var x = this.canvas._XconvertDOMtoCanvas(pointer.x); var y = this.canvas._YconvertDOMtoCanvas(pointer.y); @@ -37733,8 +37728,6 @@ return /******/ (function(modules) { // webpackBootstrap } } } - }, { - key: '_checkHidePopup', /** * Check if the popup must be hidden, which is the case when the mouse is no @@ -37742,6 +37735,8 @@ return /******/ (function(modules) { // webpackBootstrap * @param {{x:Number, y:Number}} pointer * @private */ + }, { + key: '_checkHidePopup', value: function _checkHidePopup(pointer) { var pointerObj = this.selectionHandler._pointerToPositionObject(pointer); @@ -37780,7 +37775,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = exports['default']; /***/ }, -/* 105 */ +/* 106 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; @@ -37813,13 +37808,13 @@ return /******/ (function(modules) { // webpackBootstrap this.touchTime = 0; this.activated = false; - this.body.emitter.on('activate', function () { + this.body.emitter.on("activate", function () { _this.activated = true;_this.configureKeyboardBindings(); }); - this.body.emitter.on('deactivate', function () { + this.body.emitter.on("deactivate", function () { _this.activated = false;_this.configureKeyboardBindings(); }); - this.body.emitter.on('destroy', function () { + this.body.emitter.on("destroy", function () { if (_this.keycharm !== undefined) { _this.keycharm.destroy(); } @@ -37867,8 +37862,6 @@ return /******/ (function(modules) { // webpackBootstrap this.iconsCreated = false; } - }, { - key: 'loadNavigationElements', /** * Creation of the navigation controls nodes. They are drawn over the rest of the nodes and are not affected by scale and translation @@ -37878,6 +37871,8 @@ return /******/ (function(modules) { // webpackBootstrap * * @private */ + }, { + key: 'loadNavigationElements', value: function loadNavigationElements() { var _this2 = this; @@ -37897,7 +37892,7 @@ return /******/ (function(modules) { // webpackBootstrap this.navigationDOM['wrapper'].appendChild(this.navigationDOM[navigationDivs[i]]); var hammer = new Hammer(this.navigationDOM[navigationDivs[i]]); - if (navigationDivActions[i] === '_fit') { + if (navigationDivActions[i] === "_fit") { hammerUtil.onTouch(hammer, this._fit.bind(this)); } else { hammerUtil.onTouch(hammer, this.bindToRedraw.bind(this, navigationDivActions[i])); @@ -37921,47 +37916,47 @@ return /******/ (function(modules) { // webpackBootstrap value: function bindToRedraw(action) { if (this.boundFunctions[action] === undefined) { this.boundFunctions[action] = this[action].bind(this); - this.body.emitter.on('initRedraw', this.boundFunctions[action]); - this.body.emitter.emit('_startRendering'); + this.body.emitter.on("initRedraw", this.boundFunctions[action]); + this.body.emitter.emit("_startRendering"); } } }, { key: 'unbindFromRedraw', value: function unbindFromRedraw(action) { if (this.boundFunctions[action] !== undefined) { - this.body.emitter.off('initRedraw', this.boundFunctions[action]); - this.body.emitter.emit('_stopRendering'); + this.body.emitter.off("initRedraw", this.boundFunctions[action]); + this.body.emitter.emit("_stopRendering"); delete this.boundFunctions[action]; } } - }, { - key: '_fit', /** * this stops all movement induced by the navigation buttons * * @private */ + }, { + key: '_fit', value: function _fit() { if (new Date().valueOf() - this.touchTime > 700) { // TODO: fix ugly hack to avoid hammer's double fireing of event (because we use release?) - this.body.emitter.emit('fit', { duration: 700 }); + this.body.emitter.emit("fit", { duration: 700 }); this.touchTime = new Date().valueOf(); } } - }, { - key: '_stopMovement', /** * this stops all movement induced by the navigation buttons * * @private */ + }, { + key: '_stopMovement', value: function _stopMovement() { for (var boundAction in this.boundFunctions) { if (this.boundFunctions.hasOwnProperty(boundAction)) { - this.body.emitter.off('initRedraw', this.boundFunctions[boundAction]); - this.body.emitter.emit('_stopRendering'); + this.body.emitter.off("initRedraw", this.boundFunctions[boundAction]); + this.body.emitter.emit("_stopRendering"); } } this.boundFunctions = {}; @@ -37998,12 +37993,12 @@ return /******/ (function(modules) { // webpackBootstrap this.body.view.scale /= 1 + this.options.keyboard.speed.zoom; this.body.emitter.emit('zoom', { direction: '-', scale: this.body.view.scale }); } - }, { - key: 'configureKeyboardBindings', /** * bind all keys using keycharm. */ + }, { + key: 'configureKeyboardBindings', value: function configureKeyboardBindings() { var _this3 = this; @@ -38021,79 +38016,79 @@ return /******/ (function(modules) { // webpackBootstrap this.keycharm.reset(); if (this.activated === true) { - this.keycharm.bind('up', function () { - _this3.bindToRedraw('_moveUp'); - }, 'keydown'); - this.keycharm.bind('down', function () { - _this3.bindToRedraw('_moveDown'); - }, 'keydown'); - this.keycharm.bind('left', function () { - _this3.bindToRedraw('_moveLeft'); - }, 'keydown'); - this.keycharm.bind('right', function () { - _this3.bindToRedraw('_moveRight'); - }, 'keydown'); - this.keycharm.bind('=', function () { - _this3.bindToRedraw('_zoomIn'); - }, 'keydown'); - this.keycharm.bind('num+', function () { - _this3.bindToRedraw('_zoomIn'); - }, 'keydown'); - this.keycharm.bind('num-', function () { - _this3.bindToRedraw('_zoomOut'); - }, 'keydown'); - this.keycharm.bind('-', function () { - _this3.bindToRedraw('_zoomOut'); - }, 'keydown'); - this.keycharm.bind('[', function () { - _this3.bindToRedraw('_zoomOut'); - }, 'keydown'); - this.keycharm.bind(']', function () { - _this3.bindToRedraw('_zoomIn'); - }, 'keydown'); - this.keycharm.bind('pageup', function () { - _this3.bindToRedraw('_zoomIn'); - }, 'keydown'); - this.keycharm.bind('pagedown', function () { - _this3.bindToRedraw('_zoomOut'); - }, 'keydown'); - - this.keycharm.bind('up', function () { - _this3.unbindFromRedraw('_moveUp'); - }, 'keyup'); - this.keycharm.bind('down', function () { - _this3.unbindFromRedraw('_moveDown'); - }, 'keyup'); - this.keycharm.bind('left', function () { - _this3.unbindFromRedraw('_moveLeft'); - }, 'keyup'); - this.keycharm.bind('right', function () { - _this3.unbindFromRedraw('_moveRight'); - }, 'keyup'); - this.keycharm.bind('=', function () { - _this3.unbindFromRedraw('_zoomIn'); - }, 'keyup'); - this.keycharm.bind('num+', function () { - _this3.unbindFromRedraw('_zoomIn'); - }, 'keyup'); - this.keycharm.bind('num-', function () { - _this3.unbindFromRedraw('_zoomOut'); - }, 'keyup'); - this.keycharm.bind('-', function () { - _this3.unbindFromRedraw('_zoomOut'); - }, 'keyup'); - this.keycharm.bind('[', function () { - _this3.unbindFromRedraw('_zoomOut'); - }, 'keyup'); - this.keycharm.bind(']', function () { - _this3.unbindFromRedraw('_zoomIn'); - }, 'keyup'); - this.keycharm.bind('pageup', function () { - _this3.unbindFromRedraw('_zoomIn'); - }, 'keyup'); - this.keycharm.bind('pagedown', function () { - _this3.unbindFromRedraw('_zoomOut'); - }, 'keyup'); + this.keycharm.bind("up", function () { + _this3.bindToRedraw("_moveUp"); + }, "keydown"); + this.keycharm.bind("down", function () { + _this3.bindToRedraw("_moveDown"); + }, "keydown"); + this.keycharm.bind("left", function () { + _this3.bindToRedraw("_moveLeft"); + }, "keydown"); + this.keycharm.bind("right", function () { + _this3.bindToRedraw("_moveRight"); + }, "keydown"); + this.keycharm.bind("=", function () { + _this3.bindToRedraw("_zoomIn"); + }, "keydown"); + this.keycharm.bind("num+", function () { + _this3.bindToRedraw("_zoomIn"); + }, "keydown"); + this.keycharm.bind("num-", function () { + _this3.bindToRedraw("_zoomOut"); + }, "keydown"); + this.keycharm.bind("-", function () { + _this3.bindToRedraw("_zoomOut"); + }, "keydown"); + this.keycharm.bind("[", function () { + _this3.bindToRedraw("_zoomOut"); + }, "keydown"); + this.keycharm.bind("]", function () { + _this3.bindToRedraw("_zoomIn"); + }, "keydown"); + this.keycharm.bind("pageup", function () { + _this3.bindToRedraw("_zoomIn"); + }, "keydown"); + this.keycharm.bind("pagedown", function () { + _this3.bindToRedraw("_zoomOut"); + }, "keydown"); + + this.keycharm.bind("up", function () { + _this3.unbindFromRedraw("_moveUp"); + }, "keyup"); + this.keycharm.bind("down", function () { + _this3.unbindFromRedraw("_moveDown"); + }, "keyup"); + this.keycharm.bind("left", function () { + _this3.unbindFromRedraw("_moveLeft"); + }, "keyup"); + this.keycharm.bind("right", function () { + _this3.unbindFromRedraw("_moveRight"); + }, "keyup"); + this.keycharm.bind("=", function () { + _this3.unbindFromRedraw("_zoomIn"); + }, "keyup"); + this.keycharm.bind("num+", function () { + _this3.unbindFromRedraw("_zoomIn"); + }, "keyup"); + this.keycharm.bind("num-", function () { + _this3.unbindFromRedraw("_zoomOut"); + }, "keyup"); + this.keycharm.bind("-", function () { + _this3.unbindFromRedraw("_zoomOut"); + }, "keyup"); + this.keycharm.bind("[", function () { + _this3.unbindFromRedraw("_zoomOut"); + }, "keyup"); + this.keycharm.bind("]", function () { + _this3.unbindFromRedraw("_zoomIn"); + }, "keyup"); + this.keycharm.bind("pageup", function () { + _this3.unbindFromRedraw("_zoomIn"); + }, "keyup"); + this.keycharm.bind("pagedown", function () { + _this3.unbindFromRedraw("_zoomOut"); + }, "keyup"); } } } @@ -38106,7 +38101,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = exports['default']; /***/ }, -/* 106 */ +/* 107 */ /***/ function(module, exports) { /** @@ -38145,24 +38140,24 @@ return /******/ (function(modules) { // webpackBootstrap this.container.appendChild(this.frame); } + /** + * @param {number} x Horizontal position of the popup window + * @param {number} y Vertical position of the popup window + */ + _createClass(Popup, [{ key: 'setPosition', - - /** - * @param {number} x Horizontal position of the popup window - * @param {number} y Vertical position of the popup window - */ value: function setPosition(x, y) { this.x = parseInt(x); this.y = parseInt(y); } - }, { - key: 'setText', /** * Set the content for the popup window. This can be HTML code or text. * @param {string | Element} content */ + }, { + key: 'setText', value: function setText(content) { if (content instanceof Element) { this.frame.innerHTML = ''; @@ -38171,13 +38166,13 @@ return /******/ (function(modules) { // webpackBootstrap this.frame.innerHTML = content; // string containing text or HTML } } - }, { - key: 'show', /** * Show the popup window * @param {boolean} [doShow] Show or hide the window */ + }, { + key: 'show', value: function show(doShow) { if (doShow === undefined) { doShow = true; @@ -38205,23 +38200,23 @@ return /******/ (function(modules) { // webpackBootstrap left = this.padding; } - this.frame.style.left = left + 'px'; - this.frame.style.top = top + 'px'; - this.frame.style.visibility = 'visible'; + this.frame.style.left = left + "px"; + this.frame.style.top = top + "px"; + this.frame.style.visibility = "visible"; this.hidden = false; } else { this.hide(); } } - }, { - key: 'hide', /** * Hide the popup window */ + }, { + key: 'hide', value: function hide() { this.hidden = true; - this.frame.style.visibility = 'hidden'; + this.frame.style.visibility = "hidden"; } }]); @@ -38232,7 +38227,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = exports['default']; /***/ }, -/* 107 */ +/* 108 */ /***/ function(module, exports, __webpack_require__) { "use strict"; @@ -38278,12 +38273,10 @@ return /******/ (function(modules) { // webpackBootstrap key: "setOptions", value: function setOptions(options) { if (options !== undefined) { - var fields = ["multiselect", "hoverConnectedEdges", "selectable", "selectConnectedEdges"]; + var fields = ['multiselect', 'hoverConnectedEdges', 'selectable', 'selectConnectedEdges']; util.selectiveDeepExtend(fields, this.options, options); } } - }, { - key: "selectOnPoint", /** * handles the selection part of the tap; @@ -38291,6 +38284,8 @@ return /******/ (function(modules) { // webpackBootstrap * @param {Object} pointer * @private */ + }, { + key: "selectOnPoint", value: function selectOnPoint(pointer) { var selected = false; if (this.options.selectable === true) { @@ -38337,14 +38332,14 @@ return /******/ (function(modules) { // webpackBootstrap } else { properties = this.getSelection(); } - properties["pointer"] = { + properties['pointer'] = { DOM: { x: pointer.x, y: pointer.y }, canvas: this.canvas.DOMtoCanvas(pointer) }; - properties["event"] = event; + properties['event'] = event; if (oldSelection !== undefined) { - properties["previousSelection"] = oldSelection; + properties['previousSelection'] = oldSelection; } this.body.emitter.emit(eventType, properties); } @@ -38373,8 +38368,6 @@ return /******/ (function(modules) { // webpackBootstrap this._removeFromSelection(obj); } } - }, { - key: "_getAllNodesOverlappingWith", /** * retrieve all nodes overlapping with given object @@ -38382,6 +38375,8 @@ return /******/ (function(modules) { // webpackBootstrap * @return {Number[]} An array with id's of the overlapping nodes * @private */ + }, { + key: "_getAllNodesOverlappingWith", value: function _getAllNodesOverlappingWith(object) { var overlappingNodes = []; var nodes = this.body.nodes; @@ -38393,8 +38388,6 @@ return /******/ (function(modules) { // webpackBootstrap } return overlappingNodes; } - }, { - key: "_pointerToPositionObject", /** * Return a position object in canvasspace from a single point in screenspace @@ -38403,6 +38396,8 @@ return /******/ (function(modules) { // webpackBootstrap * @returns {{left: number, top: number, right: number, bottom: number}} * @private */ + }, { + key: "_pointerToPositionObject", value: function _pointerToPositionObject(pointer) { var canvasPos = this.canvas.DOMtoCanvas(pointer); return { @@ -38412,8 +38407,6 @@ return /******/ (function(modules) { // webpackBootstrap bottom: canvasPos.y - 1 }; } - }, { - key: "getNodeAt", /** * Get the top node at the a specific point (like a click) @@ -38422,6 +38415,8 @@ return /******/ (function(modules) { // webpackBootstrap * @return {Node | undefined} node * @private */ + }, { + key: "getNodeAt", value: function getNodeAt(pointer) { var returnNode = arguments.length <= 1 || arguments[1] === undefined ? true : arguments[1]; @@ -38440,8 +38435,6 @@ return /******/ (function(modules) { // webpackBootstrap return undefined; } } - }, { - key: "_getEdgesOverlappingWith", /** * retrieve all edges overlapping with given object, selector is around center @@ -38449,6 +38442,8 @@ return /******/ (function(modules) { // webpackBootstrap * @return {Number[]} An array with id's of the overlapping nodes * @private */ + }, { + key: "_getEdgesOverlappingWith", value: function _getEdgesOverlappingWith(object, overlappingEdges) { var edges = this.body.edges; for (var i = 0; i < this.body.edgeIndices.length; i++) { @@ -38458,8 +38453,6 @@ return /******/ (function(modules) { // webpackBootstrap } } } - }, { - key: "_getAllEdgesOverlappingWith", /** * retrieve all nodes overlapping with given object @@ -38467,13 +38460,13 @@ return /******/ (function(modules) { // webpackBootstrap * @return {Number[]} An array with id's of the overlapping nodes * @private */ + }, { + key: "_getAllEdgesOverlappingWith", value: function _getAllEdgesOverlappingWith(object) { var overlappingEdges = []; this._getEdgesOverlappingWith(object, overlappingEdges); return overlappingEdges; } - }, { - key: "getEdgeAt", /** * Place holder. To implement change the getNodeAt to a _getObjectAt. Have the _getObjectAt call @@ -38483,6 +38476,8 @@ return /******/ (function(modules) { // webpackBootstrap * @returns {undefined} * @private */ + }, { + key: "getEdgeAt", value: function getEdgeAt(pointer) { var returnEdge = arguments.length <= 1 || arguments[1] === undefined ? true : arguments[1]; @@ -38499,8 +38494,6 @@ return /******/ (function(modules) { // webpackBootstrap return undefined; } } - }, { - key: "_addToSelection", /** * Add object to the selection array. @@ -38508,6 +38501,8 @@ return /******/ (function(modules) { // webpackBootstrap * @param obj * @private */ + }, { + key: "_addToSelection", value: function _addToSelection(obj) { if (obj instanceof Node) { this.selectionObj.nodes[obj.id] = obj; @@ -38515,8 +38510,6 @@ return /******/ (function(modules) { // webpackBootstrap this.selectionObj.edges[obj.id] = obj; } } - }, { - key: "_addToHover", /** * Add object to the selection array. @@ -38524,6 +38517,8 @@ return /******/ (function(modules) { // webpackBootstrap * @param obj * @private */ + }, { + key: "_addToHover", value: function _addToHover(obj) { if (obj instanceof Node) { this.hoverObj.nodes[obj.id] = obj; @@ -38531,8 +38526,6 @@ return /******/ (function(modules) { // webpackBootstrap this.hoverObj.edges[obj.id] = obj; } } - }, { - key: "_removeFromSelection", /** * Remove a single option from selection. @@ -38540,6 +38533,8 @@ return /******/ (function(modules) { // webpackBootstrap * @param {Object} obj * @private */ + }, { + key: "_removeFromSelection", value: function _removeFromSelection(obj) { if (obj instanceof Node) { delete this.selectionObj.nodes[obj.id]; @@ -38547,14 +38542,14 @@ return /******/ (function(modules) { // webpackBootstrap delete this.selectionObj.edges[obj.id]; } } - }, { - key: "unselectAll", /** * Unselect all. The selectionObj is useful for this. * * @private */ + }, { + key: "unselectAll", value: function unselectAll() { for (var nodeId in this.selectionObj.nodes) { if (this.selectionObj.nodes.hasOwnProperty(nodeId)) { @@ -38569,8 +38564,6 @@ return /******/ (function(modules) { // webpackBootstrap this.selectionObj = { nodes: {}, edges: {} }; } - }, { - key: "_getSelectedNodeCount", /** * return the number of selected nodes @@ -38578,6 +38571,8 @@ return /******/ (function(modules) { // webpackBootstrap * @returns {number} * @private */ + }, { + key: "_getSelectedNodeCount", value: function _getSelectedNodeCount() { var count = 0; for (var nodeId in this.selectionObj.nodes) { @@ -38587,8 +38582,6 @@ return /******/ (function(modules) { // webpackBootstrap } return count; } - }, { - key: "_getSelectedNode", /** * return the selected node @@ -38596,6 +38589,8 @@ return /******/ (function(modules) { // webpackBootstrap * @returns {number} * @private */ + }, { + key: "_getSelectedNode", value: function _getSelectedNode() { for (var nodeId in this.selectionObj.nodes) { if (this.selectionObj.nodes.hasOwnProperty(nodeId)) { @@ -38604,8 +38599,6 @@ return /******/ (function(modules) { // webpackBootstrap } return undefined; } - }, { - key: "_getSelectedEdge", /** * return the selected edge @@ -38613,6 +38606,8 @@ return /******/ (function(modules) { // webpackBootstrap * @returns {number} * @private */ + }, { + key: "_getSelectedEdge", value: function _getSelectedEdge() { for (var edgeId in this.selectionObj.edges) { if (this.selectionObj.edges.hasOwnProperty(edgeId)) { @@ -38621,8 +38616,6 @@ return /******/ (function(modules) { // webpackBootstrap } return undefined; } - }, { - key: "_getSelectedEdgeCount", /** * return the number of selected edges @@ -38630,6 +38623,8 @@ return /******/ (function(modules) { // webpackBootstrap * @returns {number} * @private */ + }, { + key: "_getSelectedEdgeCount", value: function _getSelectedEdgeCount() { var count = 0; for (var edgeId in this.selectionObj.edges) { @@ -38639,8 +38634,6 @@ return /******/ (function(modules) { // webpackBootstrap } return count; } - }, { - key: "_getSelectedObjectCount", /** * return the number of selected objects. @@ -38648,6 +38641,8 @@ return /******/ (function(modules) { // webpackBootstrap * @returns {number} * @private */ + }, { + key: "_getSelectedObjectCount", value: function _getSelectedObjectCount() { var count = 0; for (var nodeId in this.selectionObj.nodes) { @@ -38662,8 +38657,6 @@ return /******/ (function(modules) { // webpackBootstrap } return count; } - }, { - key: "_selectionIsEmpty", /** * Check if anything is selected @@ -38671,6 +38664,8 @@ return /******/ (function(modules) { // webpackBootstrap * @returns {boolean} * @private */ + }, { + key: "_selectionIsEmpty", value: function _selectionIsEmpty() { for (var nodeId in this.selectionObj.nodes) { if (this.selectionObj.nodes.hasOwnProperty(nodeId)) { @@ -38684,8 +38679,6 @@ return /******/ (function(modules) { // webpackBootstrap } return true; } - }, { - key: "_clusterInSelection", /** * check if one of the selected nodes is a cluster. @@ -38693,6 +38686,8 @@ return /******/ (function(modules) { // webpackBootstrap * @returns {boolean} * @private */ + }, { + key: "_clusterInSelection", value: function _clusterInSelection() { for (var nodeId in this.selectionObj.nodes) { if (this.selectionObj.nodes.hasOwnProperty(nodeId)) { @@ -38703,8 +38698,6 @@ return /******/ (function(modules) { // webpackBootstrap } return false; } - }, { - key: "_selectConnectedEdges", /** * select the edges connected to the node that is being selected @@ -38712,6 +38705,8 @@ return /******/ (function(modules) { // webpackBootstrap * @param {Node} node * @private */ + }, { + key: "_selectConnectedEdges", value: function _selectConnectedEdges(node) { for (var i = 0; i < node.edges.length; i++) { var edge = node.edges[i]; @@ -38719,8 +38714,6 @@ return /******/ (function(modules) { // webpackBootstrap this._addToSelection(edge); } } - }, { - key: "_hoverConnectedEdges", /** * select the edges connected to the node that is being selected @@ -38728,6 +38721,8 @@ return /******/ (function(modules) { // webpackBootstrap * @param {Node} node * @private */ + }, { + key: "_hoverConnectedEdges", value: function _hoverConnectedEdges(node) { for (var i = 0; i < node.edges.length; i++) { var edge = node.edges[i]; @@ -38735,8 +38730,6 @@ return /******/ (function(modules) { // webpackBootstrap this._addToHover(edge); } } - }, { - key: "_unselectConnectedEdges", /** * unselect the edges connected to the node that is being selected @@ -38744,6 +38737,8 @@ return /******/ (function(modules) { // webpackBootstrap * @param {Node} node * @private */ + }, { + key: "_unselectConnectedEdges", value: function _unselectConnectedEdges(node) { for (var i = 0; i < node.edges.length; i++) { var edge = node.edges[i]; @@ -38751,8 +38746,6 @@ return /******/ (function(modules) { // webpackBootstrap this._removeFromSelection(edge); } } - }, { - key: "blurObject", /** * This is called when someone clicks on a node. either select or deselect it. @@ -38761,6 +38754,8 @@ return /******/ (function(modules) { // webpackBootstrap * @param {Node || Edge} object * @private */ + }, { + key: "blurObject", value: function blurObject(object) { if (object.hover === true) { object.hover = false; @@ -38771,8 +38766,6 @@ return /******/ (function(modules) { // webpackBootstrap } } } - }, { - key: "hoverObject", /** * This is called when someone clicks on a node. either select or deselect it. @@ -38781,6 +38774,8 @@ return /******/ (function(modules) { // webpackBootstrap * @param {Node || Edge} object * @private */ + }, { + key: "hoverObject", value: function hoverObject(object) { var hoverChanged = false; // remove all node hover highlights @@ -38805,10 +38800,10 @@ return /******/ (function(modules) { // webpackBootstrap } // if the blur remains the same and the object is undefined (mouse off), we blur the edge else if (object === undefined) { - this.blurObject(this.hoverObj.edges[edgeId]); - delete this.hoverObj.edges[edgeId]; - hoverChanged = true; - } + this.blurObject(this.hoverObj.edges[edgeId]); + delete this.hoverObj.edges[edgeId]; + hoverChanged = true; + } } } @@ -38829,24 +38824,22 @@ return /******/ (function(modules) { // webpackBootstrap } if (hoverChanged === true) { - this.body.emitter.emit("_requestRedraw"); + this.body.emitter.emit('_requestRedraw'); } } - }, { - key: "getSelection", /** * * retrieve the currently selected objects * @return {{nodes: Array., edges: Array.}} selection */ + }, { + key: "getSelection", value: function getSelection() { var nodeIds = this.getSelectedNodes(); var edgeIds = this.getSelectedEdges(); return { nodes: nodeIds, edges: edgeIds }; } - }, { - key: "getSelectedNodes", /** * @@ -38854,6 +38847,8 @@ return /******/ (function(modules) { // webpackBootstrap * @return {String[]} selection An array with the ids of the * selected nodes. */ + }, { + key: "getSelectedNodes", value: function getSelectedNodes() { var idArray = []; if (this.options.selectable === true) { @@ -38865,8 +38860,6 @@ return /******/ (function(modules) { // webpackBootstrap } return idArray; } - }, { - key: "getSelectedEdges", /** * @@ -38874,6 +38867,8 @@ return /******/ (function(modules) { // webpackBootstrap * @return {Array} selection An array with the ids of the * selected nodes. */ + }, { + key: "getSelectedEdges", value: function getSelectedEdges() { var idArray = []; if (this.options.selectable === true) { @@ -38885,8 +38880,6 @@ return /******/ (function(modules) { // webpackBootstrap } return idArray; } - }, { - key: "selectNodes", /** * select zero or more nodes with the option to highlight edges @@ -38894,13 +38887,15 @@ return /******/ (function(modules) { // webpackBootstrap * selected nodes. * @param {boolean} [highlightEdges] */ + }, { + key: "selectNodes", value: function selectNodes(selection) { var highlightEdges = arguments.length <= 1 || arguments[1] === undefined ? true : arguments[1]; var i = undefined, id = undefined; - if (!selection || selection.length === undefined) throw "Selection must be an array with ids"; + if (!selection || selection.length === undefined) throw 'Selection must be an array with ids'; // first unselect any selected node this.unselectAll(); @@ -38910,25 +38905,25 @@ return /******/ (function(modules) { // webpackBootstrap var node = this.body.nodes[id]; if (!node) { - throw new RangeError("Node with id \"" + id + "\" not found"); + throw new RangeError('Node with id "' + id + '" not found'); } this.selectObject(node, highlightEdges); } - this.body.emitter.emit("_requestRedraw"); + this.body.emitter.emit('_requestRedraw'); } - }, { - key: "selectEdges", /** * select zero or more edges * @param {Number[] | String[]} selection An array with the ids of the * selected nodes. */ + }, { + key: "selectEdges", value: function selectEdges(selection) { var i = undefined, id = undefined; - if (!selection || selection.length === undefined) throw "Selection must be an array with ids"; + if (!selection || selection.length === undefined) throw 'Selection must be an array with ids'; // first unselect any selected objects this.unselectAll(); @@ -38938,19 +38933,19 @@ return /******/ (function(modules) { // webpackBootstrap var edge = this.body.edges[id]; if (!edge) { - throw new RangeError("Edge with id \"" + id + "\" not found"); + throw new RangeError('Edge with id "' + id + '" not found'); } this.selectObject(edge); } - this.body.emitter.emit("_requestRedraw"); + this.body.emitter.emit('_requestRedraw'); } - }, { - key: "updateSelection", /** * Validate the selection: remove ids of nodes which no longer exist * @private */ + }, { + key: "updateSelection", value: function updateSelection() { for (var nodeId in this.selectionObj.nodes) { if (this.selectionObj.nodes.hasOwnProperty(nodeId)) { @@ -38976,7 +38971,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = exports["default"]; /***/ }, -/* 108 */ +/* 109 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; @@ -38987,8 +38982,14 @@ return /******/ (function(modules) { // webpackBootstrap 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 _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } + function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } + var _NetworkUtil = __webpack_require__(104); + + var _NetworkUtil2 = _interopRequireDefault(_NetworkUtil); + var util = __webpack_require__(1); var LayoutEngine = (function () { @@ -39039,7 +39040,7 @@ return /******/ (function(modules) { // webpackBootstrap value: function setOptions(options, allOptions) { if (options !== undefined) { var prevHierarchicalState = this.options.hierarchical.enabled; - util.selectiveDeepExtend(['randomSeed', 'improvedLayout'], this.options, options); + util.selectiveDeepExtend(["randomSeed", "improvedLayout"], this.options, options); util.mergeOptions(this.options, options, 'hierarchical'); if (options.randomSeed !== undefined) { this.initialRandomSeed = options.randomSeed; @@ -39161,13 +39162,13 @@ return /******/ (function(modules) { // webpackBootstrap } } } - }, { - key: 'layoutNetwork', /** * Use KamadaKawai to position nodes. This is quite a heavy algorithm so if there are a lot of nodes we * cluster them first to reduce the amount. */ + }, { + key: 'layoutNetwork', value: function layoutNetwork() { if (this.options.hierarchical.enabled !== true && this.options.improvedLayout === true) { // first check if we should KamadaKawai to layout. The threshold is if less than half of the visible @@ -39200,7 +39201,8 @@ return /******/ (function(modules) { // webpackBootstrap var after = this.body.nodeIndices.length; if (before == after && levels % 3 !== 0 || levels > MAX_LEVELS) { this._declusterAll(); - console.info('This network could not be positioned by this version of the improved layout algorithm.'); + this.body.emitter.emit("_layoutFailed"); + console.info("This network could not be positioned by this version of the improved layout algorithm."); return; } } @@ -39211,14 +39213,38 @@ return /******/ (function(modules) { // webpackBootstrap // position the system for these nodes and edges this.body.modules.kamadaKawai.solve(this.body.nodeIndices, this.body.edgeIndices, true); + // shift to center point + this._shiftToCenter(); + + // perturb the nodes a little bit to force the physics to kick in + for (var i = 0; i < this.body.nodeIndices.length; i++) { + this.body.nodes[this.body.nodeIndices[i]].x += (0.5 - this.seededRandom()) * 50; + this.body.nodes[this.body.nodeIndices[i]].y += (0.5 - this.seededRandom()) * 50; + } + // uncluster all clusters this._declusterAll(); // reposition all bezier nodes. - this.body.emitter.emit('_repositionBezierNodes'); + this.body.emitter.emit("_repositionBezierNodes"); } } } + + /** + * Move all the nodes towards to the center so gravitational pull wil not move the nodes away from view + * @private + */ + }, { + key: '_shiftToCenter', + value: function _shiftToCenter() { + var range = _NetworkUtil2['default']._getRangeCore(this.body.nodes, this.body.nodeIndices); + var center = _NetworkUtil2['default']._findCenter(range); + for (var i = 0; i < this.body.nodeIndices.length; i++) { + this.body.nodes[this.body.nodeIndices[i]].x -= center.x; + this.body.nodes[this.body.nodeIndices[i]].y -= center.y; + } + } }, { key: '_declusterAll', value: function _declusterAll() { @@ -39241,8 +39267,6 @@ return /******/ (function(modules) { // webpackBootstrap value: function getSeed() { return this.initialRandomSeed; } - }, { - key: 'setupHierarchicalLayout', /** * This is the main function to layout the nodes in a hierarchical way. @@ -39250,6 +39274,8 @@ return /******/ (function(modules) { // webpackBootstrap * * @private */ + }, { + key: 'setupHierarchicalLayout', value: function setupHierarchicalLayout() { if (this.options.hierarchical.enabled === true && this.body.nodeIndices.length > 0) { // get the size of the largest hubs and check if the user has defined a level for a node. @@ -39297,8 +39323,6 @@ return /******/ (function(modules) { // webpackBootstrap } } } - }, { - key: '_placeNodesByHierarchy', /** * This function places the nodes on the canvas based on the hierarchial distribution. @@ -39306,6 +39330,8 @@ return /******/ (function(modules) { // webpackBootstrap * @param {Object} distribution | obtained by the function this._getDistribution() * @private */ + }, { + key: '_placeNodesByHierarchy', value: function _placeNodesByHierarchy(distribution) { var nodeId = undefined, node = undefined; @@ -39337,8 +39363,6 @@ return /******/ (function(modules) { // webpackBootstrap } } } - }, { - key: '_getDistribution', /** * This function get the distribution of levels based on hubsize @@ -39346,6 +39370,8 @@ return /******/ (function(modules) { // webpackBootstrap * @returns {Object} * @private */ + }, { + key: '_getDistribution', value: function _getDistribution() { var distribution = {}; var nodeId = undefined, @@ -39373,8 +39399,6 @@ return /******/ (function(modules) { // webpackBootstrap } return distribution; } - }, { - key: '_getHubSize', /** * Get the hubsize from all remaining unlevelled nodes. @@ -39382,6 +39406,8 @@ return /******/ (function(modules) { // webpackBootstrap * @returns {number} * @private */ + }, { + key: '_getHubSize', value: function _getHubSize() { var hubSize = 0; for (var nodeId in this.body.nodes) { @@ -39394,8 +39420,6 @@ return /******/ (function(modules) { // webpackBootstrap } return hubSize; } - }, { - key: '_determineLevelsByHubsize', /** * this function allocates nodes in levels based on the recursive branching from the largest hubs. @@ -39403,6 +39427,8 @@ return /******/ (function(modules) { // webpackBootstrap * @param hubsize * @private */ + }, { + key: '_determineLevelsByHubsize', value: function _determineLevelsByHubsize() { var nodeId = undefined, node = undefined; @@ -39423,8 +39449,6 @@ return /******/ (function(modules) { // webpackBootstrap } } } - }, { - key: '_setLevelByHubsize', /** * this function is called recursively to enumerate the barnches of the largest hubs and give each node a level. @@ -39434,6 +39458,8 @@ return /******/ (function(modules) { // webpackBootstrap * @param parentId * @private */ + }, { + key: '_setLevelByHubsize', value: function _setLevelByHubsize(level, node) { if (this.hierarchicalLevels[node.id] !== undefined) return; @@ -39448,8 +39474,6 @@ return /******/ (function(modules) { // webpackBootstrap this._setLevelByHubsize(level + 1, childNode); } } - }, { - key: '_determineLevelsDirected', /** * this function allocates nodes in levels based on the direction of the edges @@ -39457,6 +39481,8 @@ return /******/ (function(modules) { // webpackBootstrap * @param hubsize * @private */ + }, { + key: '_determineLevelsDirected', value: function _determineLevelsDirected() { var nodeId = undefined, node = undefined; @@ -39484,8 +39510,6 @@ return /******/ (function(modules) { // webpackBootstrap } } } - }, { - key: '_setLevelDirected', /** * this function is called recursively to enumerate the branched of the first node and give each node a level based on edge direction @@ -39495,6 +39519,8 @@ return /******/ (function(modules) { // webpackBootstrap * @param parentId * @private */ + }, { + key: '_setLevelDirected', value: function _setLevelDirected(level, node) { if (this.hierarchicalLevels[node.id] !== undefined) return; @@ -39511,8 +39537,6 @@ return /******/ (function(modules) { // webpackBootstrap } } } - }, { - key: '_placeBranchNodes', /** * This is a recursively called function to enumerate the branches from the largest hubs and place the nodes @@ -39524,6 +39548,8 @@ return /******/ (function(modules) { // webpackBootstrap * @param parentLevel * @private */ + }, { + key: '_placeBranchNodes', value: function _placeBranchNodes(edges, parentId, distribution, parentLevel) { for (var i = 0; i < edges.length; i++) { var childNode = undefined; @@ -39570,7 +39596,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = exports['default']; /***/ }, -/* 109 */ +/* 110 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; @@ -39645,13 +39671,13 @@ return /******/ (function(modules) { // webpackBootstrap this.body.emitter.on('_resetData', this._restore.bind(this)); } + /** + * If something changes in the data during editing, switch back to the initial datamanipulation state and close all edit modes. + * @private + */ + _createClass(ManipulationSystem, [{ key: '_restore', - - /** - * If something changes in the data during editing, switch back to the initial datamanipulation state and close all edit modes. - * @private - */ value: function _restore() { if (this.inMode !== false) { if (this.options.initiallyActive === true) { @@ -39661,13 +39687,13 @@ return /******/ (function(modules) { // webpackBootstrap } } } - }, { - key: 'setOptions', /** * Set the Options * @param options */ + }, { + key: 'setOptions', value: function setOptions(options, allOptions, globalOptions) { if (allOptions !== undefined) { if (allOptions.locale !== undefined) { @@ -39695,14 +39721,14 @@ return /******/ (function(modules) { // webpackBootstrap this._setup(); } } - }, { - key: 'toggleEditMode', /** * Enable or disable edit-mode. Draws the DOM required and cleans up after itself. * * @private */ + }, { + key: 'toggleEditMode', value: function toggleEditMode() { if (this.editMode === true) { this.disableEditMode(); @@ -39736,14 +39762,14 @@ return /******/ (function(modules) { // webpackBootstrap this._createEditButton(); } } - }, { - key: 'showManipulatorToolbar', /** * Creates the main toolbar. Removes functions bound to the select event. Binds all the buttons of the toolbar. * * @private */ + }, { + key: 'showManipulatorToolbar', value: function showManipulatorToolbar() { // restore the state of any bound functions or events, remove control nodes, restore physics this._clean(); @@ -39818,14 +39844,14 @@ return /******/ (function(modules) { // webpackBootstrap // redraw to show any possible changes this.body.emitter.emit('_redraw'); } - }, { - key: 'addNodeMode', /** * Create the toolbar for adding Nodes * * @private */ + }, { + key: 'addNodeMode', value: function addNodeMode() { // when using the gui, enable edit mode if it wasnt already. if (this.editMode !== true) { @@ -39849,14 +39875,14 @@ return /******/ (function(modules) { // webpackBootstrap this._temporaryBindEvent('click', this._performAddNode.bind(this)); } - }, { - key: 'editNode', /** * call the bound function to handle the editing of the node. The node has to be selected. * * @private */ + }, { + key: 'editNode', value: function editNode() { var _this2 = this; @@ -39897,14 +39923,14 @@ return /******/ (function(modules) { // webpackBootstrap this.showManipulatorToolbar(); } } - }, { - key: 'addEdgeMode', /** * create the toolbar to connect nodes * * @private */ + }, { + key: 'addEdgeMode', value: function addEdgeMode() { // when using the gui, enable edit mode if it wasnt already. if (this.editMode !== true) { @@ -39935,14 +39961,14 @@ return /******/ (function(modules) { // webpackBootstrap this._temporaryBindUI('onDragStart', function () {}); this._temporaryBindUI('onHold', function () {}); } - }, { - key: 'editEdgeMode', /** * create the toolbar to edit edges * * @private */ + }, { + key: 'editEdgeMode', value: function editEdgeMode() { var _this3 = this; @@ -40012,14 +40038,14 @@ return /******/ (function(modules) { // webpackBootstrap this.showManipulatorToolbar(); } } - }, { - key: 'deleteSelected', /** * delete everything in the selection * * @private */ + }, { + key: 'deleteSelected', value: function deleteSelected() { var _this4 = this; @@ -40077,8 +40103,6 @@ return /******/ (function(modules) { // webpackBootstrap this.showManipulatorToolbar(); } } - }, { - key: '_setup', //********************************************** PRIVATE ***************************************// @@ -40086,6 +40110,8 @@ return /******/ (function(modules) { // webpackBootstrap * draw or remove the DOM * @private */ + }, { + key: '_setup', value: function _setup() { if (this.options.enabled === true) { // Enable the GUI @@ -40104,13 +40130,13 @@ return /******/ (function(modules) { // webpackBootstrap this.guiEnabled = false; } } - }, { - key: '_createWrappers', /** * create the div overlays that contain the DOM * @private */ + }, { + key: '_createWrappers', value: function _createWrappers() { // load the manipulator HTML elements. All styling done in css. if (this.manipulationDiv === undefined) { @@ -40144,8 +40170,6 @@ return /******/ (function(modules) { // webpackBootstrap this.canvas.frame.appendChild(this.closeDiv); } } - }, { - key: '_getNewTargetNode', /** * generate a new target node. Used for creating new edges and editing edges @@ -40154,6 +40178,8 @@ return /******/ (function(modules) { // webpackBootstrap * @returns {*} * @private */ + }, { + key: '_getNewTargetNode', value: function _getNewTargetNode(x, y) { var controlNodeStyle = util.deepExtend({}, this.options.controlNodeStyle); @@ -40165,12 +40191,12 @@ return /******/ (function(modules) { // webpackBootstrap return this.body.functions.createNode(controlNodeStyle); } - }, { - key: '_createEditButton', /** * Create the edit button */ + }, { + key: '_createEditButton', value: function _createEditButton() { // restore everything to it's original state (if applicable) this._clean(); @@ -40189,13 +40215,13 @@ return /******/ (function(modules) { // webpackBootstrap // bind a hammer listener to the button, calling the function toggleEditMode. this._bindHammerToDiv(button, this.toggleEditMode.bind(this)); } - }, { - key: '_clean', /** * this function cleans up after everything this module does. Temporary elements, functions and events are removed, physics restored, hammers removed. * @private */ + }, { + key: '_clean', value: function _clean() { // not in mode this.inMode = false; @@ -40221,13 +40247,13 @@ return /******/ (function(modules) { // webpackBootstrap // restore the physics if required this.body.emitter.emit('restorePhysics'); } - }, { - key: '_cleanManipulatorHammers', /** * Each dom element has it's own hammer. They are stored in this.manipulationHammers. This cleans them up. * @private */ + }, { + key: '_cleanManipulatorHammers', value: function _cleanManipulatorHammers() { // _clean hammer bindings if (this.manipulationHammers.length != 0) { @@ -40237,13 +40263,13 @@ return /******/ (function(modules) { // webpackBootstrap this.manipulationHammers = []; } } - }, { - key: '_removeManipulationDOM', /** * Remove all DOM elements created by this module. * @private */ + }, { + key: '_removeManipulationDOM', value: function _removeManipulationDOM() { // removes all the bindings and overloads this._clean(); @@ -40269,14 +40295,14 @@ return /******/ (function(modules) { // webpackBootstrap this.editModeDiv = undefined; this.closeDiv = undefined; } - }, { - key: '_createSeperator', /** * create a seperator line. the index is to differentiate in the manipulation dom * @param index * @private */ + }, { + key: '_createSeperator', value: function _createSeperator() { var index = arguments.length <= 0 || arguments[0] === undefined ? 1 : arguments[0]; @@ -40284,11 +40310,11 @@ return /******/ (function(modules) { // webpackBootstrap this.manipulationDOM['seperatorLineDiv' + index].className = 'vis-separator-line'; this.manipulationDiv.appendChild(this.manipulationDOM['seperatorLineDiv' + index]); } - }, { - key: '_createAddNodeButton', // ---------------------- DOM functions for buttons --------------------------// + }, { + key: '_createAddNodeButton', value: function _createAddNodeButton(locale) { var button = this._createButton('addNode', 'vis-button vis-add', locale['addNode'] || this.options.locales['en']['addNode']); this.manipulationDiv.appendChild(button); @@ -40347,8 +40373,6 @@ return /******/ (function(modules) { // webpackBootstrap value: function _createDescription(label) { this.manipulationDiv.appendChild(this._createButton('description', 'vis-button vis-none', label)); } - }, { - key: '_temporaryBindEvent', // -------------------------- End of DOM functions for buttons ------------------------------// @@ -40358,12 +40382,12 @@ return /******/ (function(modules) { // webpackBootstrap * @param newFunction * @private */ + }, { + key: '_temporaryBindEvent', value: function _temporaryBindEvent(event, newFunction) { this.temporaryEventFunctions.push({ event: event, boundFunction: newFunction }); this.body.emitter.on(event, newFunction); } - }, { - key: '_temporaryBindUI', /** * this overrides an UI function until cleanup by the clean function @@ -40371,6 +40395,8 @@ return /******/ (function(modules) { // webpackBootstrap * @param newFunction * @private */ + }, { + key: '_temporaryBindUI', value: function _temporaryBindUI(UIfunctionName, newFunction) { if (this.body.eventListeners[UIfunctionName] !== undefined) { this.temporaryUIFunctions[UIfunctionName] = this.body.eventListeners[UIfunctionName]; @@ -40379,14 +40405,14 @@ return /******/ (function(modules) { // webpackBootstrap throw new Error('This UI function does not exist. Typo? You tried: ' + UIfunctionName + ' possible are: ' + JSON.stringify(Object.keys(this.body.eventListeners))); } } - }, { - key: '_unbindTemporaryUIs', /** * Restore the overridden UI functions to their original state. * * @private */ + }, { + key: '_unbindTemporaryUIs', value: function _unbindTemporaryUIs() { for (var functionName in this.temporaryUIFunctions) { if (this.temporaryUIFunctions.hasOwnProperty(functionName)) { @@ -40396,13 +40422,13 @@ return /******/ (function(modules) { // webpackBootstrap } this.temporaryUIFunctions = {}; } - }, { - key: '_unbindTemporaryEvents', /** * Unbind the events created by _temporaryBindEvent * @private */ + }, { + key: '_unbindTemporaryEvents', value: function _unbindTemporaryEvents() { for (var i = 0; i < this.temporaryEventFunctions.length; i++) { var eventName = this.temporaryEventFunctions[i].event; @@ -40411,26 +40437,26 @@ return /******/ (function(modules) { // webpackBootstrap } this.temporaryEventFunctions = []; } - }, { - key: '_bindHammerToDiv', /** * Bind an hammer instance to a DOM element. * @param domElement * @param funct */ + }, { + key: '_bindHammerToDiv', value: function _bindHammerToDiv(domElement, boundFunction) { var hammer = new Hammer(domElement, {}); hammerUtil.onTouch(hammer, boundFunction); this.manipulationHammers.push(hammer); } - }, { - key: '_cleanupTemporaryNodesAndEdges', /** * Neatly clean up temporary edges and nodes * @private */ + }, { + key: '_cleanupTemporaryNodesAndEdges', value: function _cleanupTemporaryNodesAndEdges() { // _clean temporary edges for (var i = 0; i < this.temporaryIds.edges.length; i++) { @@ -40453,8 +40479,6 @@ return /******/ (function(modules) { // webpackBootstrap this.temporaryIds = { nodes: [], edges: [] }; } - }, { - key: '_controlNodeTouch', // ------------------------------------------ EDIT EDGE FUNCTIONS -----------------------------------------// @@ -40463,19 +40487,21 @@ return /******/ (function(modules) { // webpackBootstrap * @param event * @private */ + }, { + key: '_controlNodeTouch', value: function _controlNodeTouch(event) { this.selectionHandler.unselectAll(); this.lastTouch = this.body.functions.getPointer(event.center); this.lastTouch.translation = util.extend({}, this.body.view.translation); // copy the object } - }, { - key: '_controlNodeDragStart', /** * the drag start is used to mark one of the control nodes as selected. * @param event * @private */ + }, { + key: '_controlNodeDragStart', value: function _controlNodeDragStart(event) { var pointer = this.lastTouch; var pointerObj = this.selectionHandler._pointerToPositionObject(pointer); @@ -40497,14 +40523,14 @@ return /******/ (function(modules) { // webpackBootstrap this.body.emitter.emit('_redraw'); } - }, { - key: '_controlNodeDrag', /** * dragging the control nodes or the canvas * @param event * @private */ + }, { + key: '_controlNodeDrag', value: function _controlNodeDrag(event) { this.body.emitter.emit('disablePhysics'); var pointer = this.body.functions.getPointer(event.center); @@ -40521,14 +40547,14 @@ return /******/ (function(modules) { // webpackBootstrap } this.body.emitter.emit('_redraw'); } - }, { - key: '_controlNodeDragEnd', /** * connecting or restoring the control nodes. * @param event * @private */ + }, { + key: '_controlNodeDragEnd', value: function _controlNodeDragEnd(event) { var pointer = this.body.functions.getPointer(event.center); var pointerObj = this.selectionHandler._pointerToPositionObject(pointer); @@ -40561,8 +40587,6 @@ return /******/ (function(modules) { // webpackBootstrap } this.body.emitter.emit('_redraw'); } - }, { - key: '_handleConnect', // ------------------------------------ END OF EDIT EDGE FUNCTIONS -----------------------------------------// @@ -40573,6 +40597,8 @@ return /******/ (function(modules) { // webpackBootstrap * * @private */ + }, { + key: '_handleConnect', value: function _handleConnect(event) { // check to avoid double fireing of this function. if (new Date().valueOf() - this.touchTime > 100) { @@ -40628,14 +40654,14 @@ return /******/ (function(modules) { // webpackBootstrap this.body.view.translation = { x: this.lastTouch.translation.x + diffX, y: this.lastTouch.translation.y + diffY }; } } - }, { - key: '_finishConnect', /** * Connect the new edge to the target if one exists, otherwise remove temp line * @param event * @private */ + }, { + key: '_finishConnect', value: function _finishConnect(event) { var pointer = this.body.functions.getPointer(event.center); var pointerObj = this.selectionHandler._pointerToPositionObject(pointer); @@ -40672,8 +40698,6 @@ return /******/ (function(modules) { // webpackBootstrap } this.body.emitter.emit('_redraw'); } - }, { - key: '_performAddNode', // --------------------------------------- END OF ADD EDGE FUNCTIONS -------------------------------------// @@ -40682,6 +40706,8 @@ return /******/ (function(modules) { // webpackBootstrap /** * Adds a node on the specified location */ + }, { + key: '_performAddNode', value: function _performAddNode(clickData) { var _this5 = this; @@ -40710,14 +40736,14 @@ return /******/ (function(modules) { // webpackBootstrap this.showManipulatorToolbar(); } } - }, { - key: '_performAddEdge', /** * connect two nodes with a new edge. * * @private */ + }, { + key: '_performAddEdge', value: function _performAddEdge(sourceNodeId, targetNodeId) { var _this6 = this; @@ -40741,14 +40767,14 @@ return /******/ (function(modules) { // webpackBootstrap this.showManipulatorToolbar(); } } - }, { - key: '_performEditEdge', /** * connect two nodes with a new edge. * * @private */ + }, { + key: '_performEditEdge', value: function _performEditEdge(sourceNodeId, targetNodeId) { var _this7 = this; @@ -40784,7 +40810,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = exports['default']; /***/ }, -/* 110 */ +/* 111 */ /***/ function(module, exports) { /** @@ -41274,6 +41300,7 @@ return /******/ (function(modules) { // webpackBootstrap solver: ['barnesHut', 'forceAtlas2Based', 'repulsion', 'hierarchicalRepulsion'], timestep: [0.5, 0.01, 1, 0.01] }, + //adaptiveTimestep: true global: { locale: ['en', 'nl'] } @@ -41281,10 +41308,9 @@ return /******/ (function(modules) { // webpackBootstrap exports.allOptions = allOptions; exports.configureOptions = configureOptions; - //adaptiveTimestep: true /***/ }, -/* 111 */ +/* 112 */ /***/ function(module, exports, __webpack_require__) { /** @@ -41306,9 +41332,7 @@ return /******/ (function(modules) { // webpackBootstrap function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - var _componentsAlgorithmsFloydWarshallJs = __webpack_require__(112); - - var _componentsAlgorithmsFloydWarshallJs2 = _interopRequireDefault(_componentsAlgorithmsFloydWarshallJs); + var _componentsAlgorithmsFloydWarshallJs = __webpack_require__(113); /** * KamadaKawai positions the nodes initially based on @@ -41319,6 +41343,8 @@ return /******/ (function(modules) { // webpackBootstrap * Possible optimizations in the distance calculation can be implemented. */ + var _componentsAlgorithmsFloydWarshallJs2 = _interopRequireDefault(_componentsAlgorithmsFloydWarshallJs); + var KamadaKawai = (function () { function KamadaKawai(body, edgeLength, edgeStrength) { _classCallCheck(this, KamadaKawai); @@ -41329,13 +41355,13 @@ return /******/ (function(modules) { // webpackBootstrap this.distanceSolver = new _componentsAlgorithmsFloydWarshallJs2["default"](); } + /** + * Not sure if needed but can be used to update the spring length and spring constant + * @param options + */ + _createClass(KamadaKawai, [{ key: "setOptions", - - /** - * Not sure if needed but can be used to update the spring length and spring constant - * @param options - */ value: function setOptions(options) { if (options) { if (options.springLength) { @@ -41346,14 +41372,14 @@ return /******/ (function(modules) { // webpackBootstrap } } } - }, { - key: "solve", /** * Position the system * @param nodesArray * @param edgesArray */ + }, { + key: "solve", value: function solve(nodesArray, edgesArray) { var ignoreClusters = arguments.length <= 2 || arguments[2] === undefined ? false : arguments[2]; @@ -41408,14 +41434,14 @@ return /******/ (function(modules) { // webpackBootstrap } } } - }, { - key: "_getHighestEnergyNode", /** * get the node with the highest energy * @returns {*[]} * @private */ + }, { + key: "_getHighestEnergyNode", value: function _getHighestEnergyNode(ignoreClusters) { var nodesArray = this.body.nodeIndices; var nodes = this.body.nodes; @@ -41447,8 +41473,6 @@ return /******/ (function(modules) { // webpackBootstrap return [maxEnergyNodeId, maxEnergy, dE_dx_max, dE_dy_max]; } - }, { - key: "_getEnergy", /** * calculate the energy of a single node @@ -41456,6 +41480,8 @@ return /******/ (function(modules) { // webpackBootstrap * @returns {*[]} * @private */ + }, { + key: "_getEnergy", value: function _getEnergy(m) { var nodesArray = this.body.nodeIndices; var nodes = this.body.nodes; @@ -41478,8 +41504,6 @@ return /******/ (function(modules) { // webpackBootstrap var delta_m = Math.sqrt(Math.pow(dE_dx, 2) + Math.pow(dE_dy, 2)); return [delta_m, dE_dx, dE_dy]; } - }, { - key: "_moveNode", /** * move the node based on it's energy @@ -41489,6 +41513,8 @@ return /******/ (function(modules) { // webpackBootstrap * @param dE_dy * @private */ + }, { + key: "_moveNode", value: function _moveNode(m, dE_dx, dE_dy) { var nodesArray = this.body.nodeIndices; var nodes = this.body.nodes; @@ -41524,14 +41550,14 @@ return /******/ (function(modules) { // webpackBootstrap nodes[m].x += dx; nodes[m].y += dy; } - }, { - key: "_createL_matrix", /** * Create the L matrix: edge length times shortest path * @param D_matrix * @private */ + }, { + key: "_createL_matrix", value: function _createL_matrix(D_matrix) { var nodesArray = this.body.nodeIndices; var edgeLength = this.springLength; @@ -41544,14 +41570,14 @@ return /******/ (function(modules) { // webpackBootstrap } } } - }, { - key: "_createK_matrix", /** * Create the K matrix: spring constants times shortest path * @param D_matrix * @private */ + }, { + key: "_createK_matrix", value: function _createK_matrix(D_matrix) { var nodesArray = this.body.nodeIndices; var edgeStrength = this.springConstant; @@ -41573,7 +41599,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = exports["default"]; /***/ }, -/* 112 */ +/* 113 */ /***/ function(module, exports) { /** @@ -41641,7 +41667,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = exports["default"]; /***/ }, -/* 113 */ +/* 114 */ /***/ function(module, exports) { /** @@ -41928,7 +41954,7 @@ return /******/ (function(modules) { // webpackBootstrap } /***/ }, -/* 114 */ +/* 115 */ /***/ function(module, exports) { /** @@ -42278,10 +42304,10 @@ return /******/ (function(modules) { // webpackBootstrap if (token === 'false') { token = false; // convert to boolean } else if (token === 'true') { - token = true; // convert to boolean - } else if (!isNaN(Number(token))) { - token = Number(token); // convert to number - } + token = true; // convert to boolean + } else if (!isNaN(Number(token))) { + token = Number(token); // convert to number + } tokenType = TOKENTYPE.IDENTIFIER; return; } @@ -42423,8 +42449,8 @@ return /******/ (function(modules) { // webpackBootstrap getToken(); // TODO: implement comma separated list with "a_list: ID=ID [','] [a_list] " } else { - parseNodeStatement(graph, id); - } + parseNodeStatement(graph, id); + } } /** @@ -42826,7 +42852,7 @@ return /******/ (function(modules) { // webpackBootstrap exports.DOTToGraph = DOTToGraph; /***/ }, -/* 115 */ +/* 116 */ /***/ function(module, exports) { 'use strict'; @@ -42904,7 +42930,7 @@ return /******/ (function(modules) { // webpackBootstrap exports.parseGephi = parseGephi; /***/ }, -/* 116 */ +/* 117 */ /***/ function(module, exports) { /** @@ -42930,13 +42956,13 @@ return /******/ (function(modules) { // webpackBootstrap this.callback = callback; } + /** + * @param {string} url The Url to cache the image as + * @return {Image} imageToLoadBrokenUrlOn The image object + */ + _createClass(Images, [{ key: "_addImageToCache", - - /** - * @param {string} url The Url to cache the image as - * @return {Image} imageToLoadBrokenUrlOn The image object - */ value: function _addImageToCache(url, imageToCache) { // IE11 fix -- thanks dponch! if (imageToCache.width === 0) { @@ -42948,14 +42974,14 @@ return /******/ (function(modules) { // webpackBootstrap this.images[url] = imageToCache; } - }, { - key: "_tryloadBrokenUrl", /** * @param {string} url The original Url that failed to load, if the broken image is successfully loaded it will be added to the cache using this Url as the key so that subsequent requests for this Url will return the broken image * @param {string} brokenUrl Url the broken image to try and load * @return {Image} imageToLoadBrokenUrlOn The image object */ + }, { + key: "_tryloadBrokenUrl", value: function _tryloadBrokenUrl(url, brokenUrl, imageToLoadBrokenUrlOn) { var _this = this; @@ -42972,25 +42998,25 @@ return /******/ (function(modules) { // webpackBootstrap //Set the source of the image to the brokenUrl, this is actually what kicks off the loading of the broken image imageToLoadBrokenUrlOn.src = brokenUrl; } - }, { - key: "_redrawWithImage", /** * @return {Image} imageToRedrawWith The images that will be passed to the callback when it is invoked */ + }, { + key: "_redrawWithImage", value: function _redrawWithImage(imageToRedrawWith) { if (this.callback) { this.callback(imageToRedrawWith); } } - }, { - key: "load", /** * @param {string} url Url of the image * @param {string} brokenUrl Url of an image to use if the url image is not found * @return {Image} img The image object */ + }, { + key: "load", value: function load(url, brokenUrl, id) { var _this2 = this; @@ -43030,7 +43056,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = exports["default"]; /***/ }, -/* 117 */ +/* 118 */ /***/ function(module, exports) { // English @@ -43054,6 +43080,24 @@ return /******/ (function(modules) { // webpackBootstrap exports['en_EN'] = exports['en']; exports['en_US'] = exports['en']; + // German + exports['de'] = { + edit: 'Editieren', + del: 'Lösche Auswahl', + back: 'Zurück', + addNode: 'Knoten hinzufügen', + addEdge: 'Kante hinzufügen', + editNode: 'Knoten editieren', + editEdge: 'Kante editieren', + addDescription: 'Klicke auf eine freie Stelle, um einen neuen Knoten zu plazieren.', + edgeDescription: 'Klicke auf einen Knoten und ziehe die Kante zu einem anderen Knoten, um diese zu verbinden.', + editEdgeDescription: 'Klicke auf die Verbindungspunkte und ziehe diese auf einen Knoten, um sie zu verbinden.', + createEdgeError: 'Es ist nicht möglich, Kanten mit Clustern zu verbinden.', + deleteClusterError: 'Cluster können nicht gelöscht werden.', + editClusterError: 'Cluster können nicht editiert werden.' + }; + exports['de_DE'] = exports['de']; + // Spanish exports['es'] = { edit: 'Editar', diff --git a/dist/vis.min.css b/dist/vis.min.css index 529a6b06..b61d9a40 100644 --- a/dist/vis.min.css +++ b/dist/vis.min.css @@ -1 +1 @@ -.vis-background,.vis-labelset,.vis-timeline{overflow:hidden}.vis .overlay{position:absolute;top:0;left:0;width:100%;height:100%;z-index:10}.vis-active{box-shadow:0 0 10px #86d5f8}.vis [class*=span]{min-height:0;width:auto}div.vis-configuration{position:relative;display:block;float:left;font-size:9pt}div.vis-configuration-wrapper{display:block;width:700px}div.vis-configuration.vis-config-option-container{display:block;width:495px;background-color:#fff;border:2px solid #f7f8fa;border-radius:4px;margin-top:20px;left:10px;padding-left:5px}div.vis-configuration.vis-config-button{display:block;width:495px;height:25px;vertical-align:middle;line-height:25px;background-color:#f7f8fa;border:2px solid #ceced0;border-radius:4px;margin-top:20px;left:10px;padding-left:5px;cursor:pointer;margin-bottom:30px}div.vis-configuration.vis-config-button.hover{background-color:#4588e6;border:2px solid #214373;color:#fff}div.vis-configuration.vis-config-item{display:block;float:left;width:495px;height:25px;vertical-align:middle;line-height:25px}div.vis-configuration.vis-config-item.vis-config-s2{left:10px;background-color:#f7f8fa;padding-left:5px;border-radius:3px}div.vis-configuration.vis-config-item.vis-config-s3{left:20px;background-color:#e4e9f0;padding-left:5px;border-radius:3px}div.vis-configuration.vis-config-item.vis-config-s4{left:30px;background-color:#cfd8e6;padding-left:5px;border-radius:3px}div.vis-configuration.vis-config-header{font-size:18px;font-weight:700}div.vis-configuration.vis-config-label{width:90pt;height:25px;line-height:25px}div.vis-configuration.vis-config-label.vis-config-s3{width:110px}div.vis-configuration.vis-config-label.vis-config-s4{width:75pt}div.vis-configuration.vis-config-colorBlock{top:1px;width:30px;height:19px;border:1px solid #444;border-radius:2px;padding:0;margin:0;cursor:pointer}input.vis-configuration.vis-config-checkbox{left:-5px}input.vis-configuration.vis-config-rangeinput{position:relative;top:-5px;width:60px;height:13px;padding:1px;margin:0;pointer-events:none}.vis-panel,.vis-timeline{padding:0;box-sizing:border-box}input.vis-configuration.vis-config-range{-webkit-appearance:none;border:0 solid #fff;background-color:transparent;width:300px;height:20px}input.vis-configuration.vis-config-range::-webkit-slider-runnable-track{width:300px;height:5px;background:#dedede;background:-moz-linear-gradient(top,#dedede 0,#c8c8c8 99%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#dedede),color-stop(99%,#c8c8c8));background:-webkit-linear-gradient(top,#dedede 0,#c8c8c8 99%);background:-o-linear-gradient(top,#dedede 0,#c8c8c8 99%);background:-ms-linear-gradient(top,#dedede 0,#c8c8c8 99%);background:linear-gradient(to bottom,#dedede 0,#c8c8c8 99%);filter:progid:DXImageTransform.Microsoft.gradient( startColorstr='#dedede', endColorstr='#c8c8c8', GradientType=0 );border:1px solid #999;box-shadow:#aaa 0 0 3px 0;border-radius:3px}input.vis-configuration.vis-config-range::-webkit-slider-thumb{-webkit-appearance:none;border:1px solid #14334b;height:17px;width:17px;border-radius:50%;background:#3876c2;background:-moz-linear-gradient(top,#3876c2 0,#385380 100%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#3876c2),color-stop(100%,#385380));background:-webkit-linear-gradient(top,#3876c2 0,#385380 100%);background:-o-linear-gradient(top,#3876c2 0,#385380 100%);background:-ms-linear-gradient(top,#3876c2 0,#385380 100%);background:linear-gradient(to bottom,#3876c2 0,#385380 100%);filter:progid:DXImageTransform.Microsoft.gradient( startColorstr='#3876c2', endColorstr='#385380', GradientType=0 );box-shadow:#111927 0 0 1px 0;margin-top:-7px}input.vis-configuration.vis-config-range:focus{outline:0}input.vis-configuration.vis-config-range:focus::-webkit-slider-runnable-track{background:#9d9d9d;background:-moz-linear-gradient(top,#9d9d9d 0,#c8c8c8 99%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#9d9d9d),color-stop(99%,#c8c8c8));background:-webkit-linear-gradient(top,#9d9d9d 0,#c8c8c8 99%);background:-o-linear-gradient(top,#9d9d9d 0,#c8c8c8 99%);background:-ms-linear-gradient(top,#9d9d9d 0,#c8c8c8 99%);background:linear-gradient(to bottom,#9d9d9d 0,#c8c8c8 99%);filter:progid:DXImageTransform.Microsoft.gradient( startColorstr='#9d9d9d', endColorstr='#c8c8c8', GradientType=0 )}input.vis-configuration.vis-config-range::-moz-range-track{width:300px;height:10px;background:#dedede;background:-moz-linear-gradient(top,#dedede 0,#c8c8c8 99%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#dedede),color-stop(99%,#c8c8c8));background:-webkit-linear-gradient(top,#dedede 0,#c8c8c8 99%);background:-o-linear-gradient(top,#dedede 0,#c8c8c8 99%);background:-ms-linear-gradient(top,#dedede 0,#c8c8c8 99%);background:linear-gradient(to bottom,#dedede 0,#c8c8c8 99%);filter:progid:DXImageTransform.Microsoft.gradient( startColorstr='#dedede', endColorstr='#c8c8c8', GradientType=0 );border:1px solid #999;box-shadow:#aaa 0 0 3px 0;border-radius:3px}input.vis-configuration.vis-config-range::-moz-range-thumb{border:none;height:1pc;width:1pc;border-radius:50%;background:#385380}input.vis-configuration.vis-config-range:-moz-focusring{outline:#fff solid 1px;outline-offset:-1px}input.vis-configuration.vis-config-range::-ms-track{width:300px;height:5px;background:0 0;border-color:transparent;border-width:6px 0;color:transparent}input.vis-configuration.vis-config-range::-ms-fill-lower{background:#777;border-radius:10px}input.vis-configuration.vis-config-range::-ms-fill-upper{background:#ddd;border-radius:10px}input.vis-configuration.vis-config-range::-ms-thumb{border:none;height:1pc;width:1pc;border-radius:50%;background:#385380}input.vis-configuration.vis-config-range:focus::-ms-fill-lower{background:#888}input.vis-configuration.vis-config-range:focus::-ms-fill-upper{background:#ccc}.vis-configuration-popup{position:absolute;background:rgba(57,76,89,.85);border:2px solid #f2faff;line-height:30px;height:30px;width:150px;text-align:center;color:#fff;font-size:14px;border-radius:4px;-webkit-transition:opacity .3s ease-in-out;-moz-transition:opacity .3s ease-in-out;transition:opacity .3s ease-in-out}.vis-configuration-popup:after,.vis-configuration-popup:before{left:100%;top:50%;border:solid transparent;content:" ";height:0;width:0;position:absolute;pointer-events:none}.vis-configuration-popup:after{border-color:rgba(136,183,213,0);border-left-color:rgba(57,76,89,.85);border-width:8px;margin-top:-8px}.vis-configuration-popup:before{border-color:rgba(194,225,245,0);border-left-color:#f2faff;border-width:9pt;margin-top:-9pt}.vis-timeline{position:relative;border:1px solid #bfbfbf;margin:0}.vis-panel{position:absolute;margin:0}.vis-panel.vis-bottom,.vis-panel.vis-center,.vis-panel.vis-left,.vis-panel.vis-right,.vis-panel.vis-top{border:1px #bfbfbf}.vis-panel.vis-center,.vis-panel.vis-left,.vis-panel.vis-right{border-top-style:solid;border-bottom-style:solid;overflow:hidden}.vis-panel.vis-bottom,.vis-panel.vis-center,.vis-panel.vis-top{border-left-style:solid;border-right-style:solid}.vis-panel>.vis-content{position:relative}.vis-panel .vis-shadow{position:absolute;width:100%;height:1px;box-shadow:0 0 10px rgba(0,0,0,.8)}.vis-itemset,.vis-labelset,.vis-labelset .vis-label{position:relative;box-sizing:border-box}.vis-panel .vis-shadow.vis-top{top:-1px;left:0}.vis-panel .vis-shadow.vis-bottom{bottom:-1px;left:0}.vis-labelset .vis-label{left:0;top:0;width:100%;color:#4d4d4d;border-bottom:1px solid #bfbfbf}.vis-labelset .vis-label.draggable{cursor:pointer}.vis-labelset .vis-label:last-child{border-bottom:none}.vis-labelset .vis-label .vis-inner{display:inline-block;padding:5px}.vis-labelset .vis-label .vis-inner.vis-hidden{padding:0}.vis-itemset{padding:0;margin:0}.vis-itemset .vis-background,.vis-itemset .vis-foreground{position:absolute;width:100%;height:100%;overflow:visible}.vis-axis{position:absolute;width:100%;height:0;left:0;z-index:1}.vis-foreground .vis-group{position:relative;box-sizing:border-box;border-bottom:1px solid #bfbfbf}.vis-foreground .vis-group:last-child{border-bottom:none}.vis-overlay{position:absolute;top:0;left:0;width:100%;height:100%;z-index:10}.vis-item{position:absolute;color:#1A1A1A;border-color:#97B0F8;border-width:1px;background-color:#D5DDF6;display:inline-block}.vis-item.vis-point.vis-selected,.vis-item.vis-selected{background-color:#FFF785}.vis-item.vis-selected{border-color:#FFC200;z-index:2}.vis-editable.vis-selected{cursor:move}.vis-item.vis-box{text-align:center;border-style:solid;border-radius:2px}.vis-item.vis-point{background:0 0}.vis-item.vis-dot{position:absolute;padding:0;border-width:4px;border-style:solid;border-radius:4px}.vis-item.vis-range{border-style:solid;border-radius:2px;box-sizing:border-box}.vis-item.vis-background{border:none;background-color:rgba(213,221,246,.4);box-sizing:border-box;padding:0;margin:0}.vis-item .vis-item-overflow{position:relative;width:100%;height:100%;padding:0;margin:0;overflow:hidden}.vis-item.vis-range .vis-item-content{position:relative;display:inline-block}.vis-item.vis-background .vis-item-content{position:absolute;display:inline-block}.vis-item.vis-line{padding:0;position:absolute;width:0;border-left-width:1px;border-left-style:solid}.vis-item .vis-item-content{white-space:nowrap;box-sizing:border-box;padding:5px}.vis-item .vis-delete{background:url(img/timeline/delete.png) center no-repeat;position:absolute;width:24px;height:24px;top:-4px;right:-24px;cursor:pointer}.vis-item.vis-range .vis-drag-left{position:absolute;width:24px;max-width:20%;min-width:2px;height:100%;top:0;left:-4px;cursor:w-resize}.vis-item.vis-range .vis-drag-right{position:absolute;width:24px;max-width:20%;min-width:2px;height:100%;top:0;right:-4px;cursor:e-resize}.vis-time-axis{position:relative;overflow:hidden}.vis-time-axis.vis-foreground{top:0;left:0;width:100%}.vis-time-axis.vis-background{position:absolute;top:0;left:0;width:100%;height:100%}.vis-time-axis .vis-text{position:absolute;color:#4d4d4d;padding:3px;overflow:hidden;box-sizing:border-box;white-space:nowrap}.vis-time-axis .vis-text.vis-measure{position:absolute;padding-left:0;padding-right:0;margin-left:0;margin-right:0;visibility:hidden}.vis-time-axis .vis-grid.vis-vertical{position:absolute;border-left:1px solid}.vis-time-axis .vis-grid.vis-minor{border-color:#e5e5e5}.vis-time-axis .vis-grid.vis-major{border-color:#bfbfbf}.vis-current-time{background-color:#FF7F6E;width:2px;z-index:1}.vis-custom-time{background-color:#6E94FF;width:2px;cursor:move;z-index:1}.vis-panel.vis-background.vis-horizontal .vis-grid.vis-horizontal{position:absolute;width:100%;height:0;border-bottom:1px solid}.vis-panel.vis-background.vis-horizontal .vis-grid.vis-minor{border-color:#e5e5e5}.vis-panel.vis-background.vis-horizontal .vis-grid.vis-major{border-color:#bfbfbf}.vis-data-axis .vis-y-axis.vis-major{width:100%;position:absolute;color:#4d4d4d;white-space:nowrap}.vis-data-axis .vis-y-axis.vis-major.vis-measure{padding:0;margin:0;border:0;visibility:hidden;width:auto}.vis-data-axis .vis-y-axis.vis-minor{position:absolute;width:100%;color:#bebebe;white-space:nowrap}.vis-data-axis .vis-y-axis.vis-minor.vis-measure{padding:0;margin:0;border:0;visibility:hidden;width:auto}.vis-data-axis .vis-y-axis.vis-title{position:absolute;color:#4d4d4d;white-space:nowrap;bottom:20px;text-align:center}.vis-data-axis .vis-y-axis.vis-title.vis-measure{padding:0;margin:0;visibility:hidden;width:auto}.vis-data-axis .vis-y-axis.vis-title.vis-left{bottom:0;-webkit-transform-origin:left top;-moz-transform-origin:left top;-ms-transform-origin:left top;-o-transform-origin:left top;transform-origin:left bottom;-webkit-transform:rotate(-90deg);-moz-transform:rotate(-90deg);-ms-transform:rotate(-90deg);-o-transform:rotate(-90deg);transform:rotate(-90deg)}.vis-data-axis .vis-y-axis.vis-title.vis-right{bottom:0;-webkit-transform-origin:right bottom;-moz-transform-origin:right bottom;-ms-transform-origin:right bottom;-o-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:rotate(90deg);-moz-transform:rotate(90deg);-ms-transform:rotate(90deg);-o-transform:rotate(90deg);transform:rotate(90deg)}.vis-legend{background-color:rgba(247,252,255,.65);padding:5px;border:1px solid #b3b3b3;box-shadow:2px 2px 10px rgba(154,154,154,.55)}.vis-legend-text{white-space:nowrap;display:inline-block}.vis-graph-group0{fill:#4f81bd;fill-opacity:0;stroke-width:2px;stroke:#4f81bd}.vis-graph-group1{fill:#f79646;fill-opacity:0;stroke-width:2px;stroke:#f79646}.vis-graph-group2{fill:#8c51cf;fill-opacity:0;stroke-width:2px;stroke:#8c51cf}.vis-graph-group3{fill:#75c841;fill-opacity:0;stroke-width:2px;stroke:#75c841}.vis-graph-group4{fill:#ff0100;fill-opacity:0;stroke-width:2px;stroke:#ff0100}.vis-graph-group5{fill:#37d8e6;fill-opacity:0;stroke-width:2px;stroke:#37d8e6}.vis-graph-group6{fill:#042662;fill-opacity:0;stroke-width:2px;stroke:#042662}.vis-graph-group7{fill:#00ff26;fill-opacity:0;stroke-width:2px;stroke:#00ff26}.vis-graph-group8{fill:#f0f;fill-opacity:0;stroke-width:2px;stroke:#f0f}.vis-graph-group9{fill:#8f3938;fill-opacity:0;stroke-width:2px;stroke:#8f3938}.vis-timeline .vis-fill{fill-opacity:.1;stroke:none}.vis-timeline .vis-bar{fill-opacity:.5;stroke-width:1px}.vis-timeline .vis-point{stroke-width:2px;fill-opacity:1}.vis-timeline .vis-legend-background{stroke-width:1px;fill-opacity:.9;fill:#fff;stroke:#c2c2c2}.vis-timeline .vis-outline{stroke-width:1px;fill-opacity:1;fill:#fff;stroke:#e5e5e5}.vis-timeline .vis-icon-fill{fill-opacity:.3;stroke:none}div.vis-network div.vis-manipulation{border-width:0;border-bottom:1px;border-style:solid;border-color:#d6d9d8;background:#fff;background:-moz-linear-gradient(top,#fff 0,#fcfcfc 48%,#fafafa 50%,#fcfcfc 100%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#fff),color-stop(48%,#fcfcfc),color-stop(50%,#fafafa),color-stop(100%,#fcfcfc));background:-webkit-linear-gradient(top,#fff 0,#fcfcfc 48%,#fafafa 50%,#fcfcfc 100%);background:-o-linear-gradient(top,#fff 0,#fcfcfc 48%,#fafafa 50%,#fcfcfc 100%);background:-ms-linear-gradient(top,#fff 0,#fcfcfc 48%,#fafafa 50%,#fcfcfc 100%);background:linear-gradient(to bottom,#fff 0,#fcfcfc 48%,#fafafa 50%,#fcfcfc 100%);filter:progid:DXImageTransform.Microsoft.gradient( startColorstr='#ffffff', endColorstr='#fcfcfc', GradientType=0 );position:absolute;left:0;top:0;width:100%;height:30px}div.vis-network div.vis-edit-mode{position:absolute;left:0;top:15px;height:30px}div.vis-network div.vis-close{position:absolute;right:0;top:0;width:30px;height:30px;background-position:20px 3px;background-repeat:no-repeat;background-image:url(img/network/cross.png);cursor:pointer;-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}div.vis-network div.vis-close:hover{opacity:.6}div.vis-network div.vis-edit-mode div.vis-button,div.vis-network div.vis-manipulation div.vis-button{position:relative;top:-7px;font-family:verdana;font-size:9pt;-moz-border-radius:15px;border-radius:15px;display:inline-block;background-position:0 0;background-repeat:no-repeat;height:24px;margin:0 0 0 10px;vertical-align:middle;cursor:pointer;padding:0 8px;-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}div.vis-network div.vis-manipulation div.vis-button:hover{box-shadow:1px 1px 8px rgba(0,0,0,.2)}div.vis-network div.vis-manipulation div.vis-button:active{box-shadow:1px 1px 8px rgba(0,0,0,.5)}div.vis-network div.vis-manipulation div.vis-button.vis-back{background-image:url(img/network/backIcon.png)}div.vis-network div.vis-manipulation div.vis-button.vis-none:hover{box-shadow:1px 1px 8px transparent;cursor:default}div.vis-network div.vis-manipulation div.vis-button.vis-none:active{box-shadow:1px 1px 8px transparent}div.vis-network div.vis-manipulation div.vis-button.vis-none{padding:0}div.vis-network div.vis-manipulation div.notification{margin:2px;font-weight:700}div.vis-network div.vis-manipulation div.vis-button.vis-add{background-image:url(img/network/addNodeIcon.png)}div.vis-network div.vis-edit-mode div.vis-button.vis-edit,div.vis-network div.vis-manipulation div.vis-button.vis-edit{background-image:url(img/network/editIcon.png)}div.vis-network div.vis-edit-mode div.vis-button.vis-edit.vis-edit-mode{background-color:#fcfcfc;border:1px solid #ccc}div.vis-network div.vis-manipulation div.vis-button.vis-connect{background-image:url(img/network/connectIcon.png)}div.vis-network div.vis-manipulation div.vis-button.vis-delete{background-image:url(img/network/deleteIcon.png)}div.vis-network div.vis-edit-mode div.vis-label,div.vis-network div.vis-manipulation div.vis-label{margin:0 0 0 23px;line-height:25px}div.vis-network div.vis-manipulation div.vis-separator-line{display:inline-block;width:1px;height:20px;background-color:#bdbdbd;margin:5px 7px 0 15px}div.vis-network-tooltip{position:absolute;visibility:hidden;padding:5px;white-space:nowrap;font-family:verdana;font-size:14px;font-color:#000;background-color:#f5f4ed;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px;border:1px solid #808074;box-shadow:3px 3px 10px rgba(0,0,0,.2);pointer-events:none}div.vis-network div.vis-navigation div.vis-button{width:34px;height:34px;-moz-border-radius:17px;border-radius:17px;position:absolute;display:inline-block;background-position:2px 2px;background-repeat:no-repeat;cursor:pointer;-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}div.vis-network div.vis-navigation div.vis-button:hover{box-shadow:0 0 3px 3px rgba(56,207,21,.3)}div.vis-network div.vis-navigation div.vis-button:active{box-shadow:0 0 1px 3px rgba(56,207,21,.95)}div.vis-network div.vis-navigation div.vis-button.vis-up{background-image:url(img/network/upArrow.png);bottom:50px;left:55px}div.vis-network div.vis-navigation div.vis-button.vis-down{background-image:url(img/network/downArrow.png);bottom:10px;left:55px}div.vis-network div.vis-navigation div.vis-button.vis-left{background-image:url(img/network/leftArrow.png);bottom:10px;left:15px}div.vis-network div.vis-navigation div.vis-button.vis-right{background-image:url(img/network/rightArrow.png);bottom:10px;left:95px}div.vis-network div.vis-navigation div.vis-button.vis-zoomIn{background-image:url(img/network/plus.png);bottom:10px;right:15px}div.vis-network div.vis-navigation div.vis-button.vis-zoomOut{background-image:url(img/network/minus.png);bottom:10px;right:55px}div.vis-network div.vis-navigation div.vis-button.vis-zoomExtends{background-image:url(img/network/zoomExtends.png);bottom:50px;right:15px}div.vis-color-picker{position:absolute;margin-top:-140px;margin-left:30px;width:293px;height:425px;padding:10px;border-radius:15px;background-color:#fff;display:none;box-shadow:rgba(0,0,0,.5) 0 0 10px 0}div.vis-color-picker div.vis-arrow{position:absolute;top:147px;left:5px}div.vis-color-picker div.vis-arrow:after,div.vis-color-picker div.vis-arrow:before{right:100%;top:50%;border:solid transparent;content:" ";height:0;width:0;position:absolute;pointer-events:none}div.vis-color-picker div.vis-arrow:after{border-color:rgba(255,255,255,0);border-right-color:#fff;border-width:30px;margin-top:-30px}div.vis-color-picker div.vis-color{position:absolute;width:289px;height:289px;cursor:pointer}div.vis-color-picker div.vis-brightness{position:absolute;top:313px}div.vis-color-picker div.vis-opacity{position:absolute;top:350px}div.vis-color-picker div.vis-selector{position:absolute;top:137px;left:137px;width:15px;height:15px;border-radius:15px;border:1px solid #fff;background:#4c4c4c;background:-moz-linear-gradient(top,#4c4c4c 0,#595959 12%,#666 25%,#474747 39%,#2c2c2c 50%,#000 51%,#111 60%,#2b2b2b 76%,#1c1c1c 91%,#131313 100%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#4c4c4c),color-stop(12%,#595959),color-stop(25%,#666),color-stop(39%,#474747),color-stop(50%,#2c2c2c),color-stop(51%,#000),color-stop(60%,#111),color-stop(76%,#2b2b2b),color-stop(91%,#1c1c1c),color-stop(100%,#131313));background:-webkit-linear-gradient(top,#4c4c4c 0,#595959 12%,#666 25%,#474747 39%,#2c2c2c 50%,#000 51%,#111 60%,#2b2b2b 76%,#1c1c1c 91%,#131313 100%);background:-o-linear-gradient(top,#4c4c4c 0,#595959 12%,#666 25%,#474747 39%,#2c2c2c 50%,#000 51%,#111 60%,#2b2b2b 76%,#1c1c1c 91%,#131313 100%);background:-ms-linear-gradient(top,#4c4c4c 0,#595959 12%,#666 25%,#474747 39%,#2c2c2c 50%,#000 51%,#111 60%,#2b2b2b 76%,#1c1c1c 91%,#131313 100%);background:linear-gradient(to bottom,#4c4c4c 0,#595959 12%,#666 25%,#474747 39%,#2c2c2c 50%,#000 51%,#111 60%,#2b2b2b 76%,#1c1c1c 91%,#131313 100%);filter:progid:DXImageTransform.Microsoft.gradient( startColorstr='#4c4c4c', endColorstr='#131313', GradientType=0 )}div.vis-color-picker div.vis-initial-color,div.vis-color-picker div.vis-new-color{width:140px;height:20px;top:380px;font-size:10px;color:rgba(0,0,0,.4);line-height:20px;position:absolute;vertical-align:middle}div.vis-color-picker div.vis-new-color{border:1px solid rgba(0,0,0,.1);border-radius:5px;left:159px;text-align:right;padding-right:2px}div.vis-color-picker div.vis-initial-color{border:1px solid rgba(0,0,0,.1);border-radius:5px;left:10px;text-align:left;padding-left:2px}div.vis-color-picker div.vis-label{position:absolute;width:300px;left:10px}div.vis-color-picker div.vis-label.vis-brightness{top:300px}div.vis-color-picker div.vis-label.vis-opacity{top:338px}div.vis-color-picker div.vis-button{position:absolute;width:68px;height:25px;border-radius:10px;vertical-align:middle;text-align:center;line-height:25px;top:410px;border:2px solid #d9d9d9;background-color:#f7f7f7;cursor:pointer}div.vis-color-picker div.vis-button.vis-cancel{left:5px}div.vis-color-picker div.vis-button.vis-load{left:82px}div.vis-color-picker div.vis-button.vis-apply{left:159px}div.vis-color-picker div.vis-button.vis-save{left:236px}div.vis-color-picker input.vis-range{width:290px;height:20px} \ No newline at end of file +.vis-background,.vis-labelset,.vis-timeline{overflow:hidden}.vis .overlay{position:absolute;top:0;left:0;width:100%;height:100%;z-index:10}.vis-active{box-shadow:0 0 10px #86d5f8}.vis [class*=span]{min-height:0;width:auto}div.vis-configuration{position:relative;display:block;float:left;font-size:12px}div.vis-configuration-wrapper{display:block;width:700px}div.vis-configuration.vis-config-option-container{display:block;width:495px;background-color:#fff;border:2px solid #f7f8fa;border-radius:4px;margin-top:20px;left:10px;padding-left:5px}div.vis-configuration.vis-config-button{display:block;width:495px;height:25px;vertical-align:middle;line-height:25px;background-color:#f7f8fa;border:2px solid #ceced0;border-radius:4px;margin-top:20px;left:10px;padding-left:5px;cursor:pointer;margin-bottom:30px}div.vis-configuration.vis-config-button.hover{background-color:#4588e6;border:2px solid #214373;color:#fff}div.vis-configuration.vis-config-item{display:block;float:left;width:495px;height:25px;vertical-align:middle;line-height:25px}div.vis-configuration.vis-config-item.vis-config-s2{left:10px;background-color:#f7f8fa;padding-left:5px;border-radius:3px}div.vis-configuration.vis-config-item.vis-config-s3{left:20px;background-color:#e4e9f0;padding-left:5px;border-radius:3px}div.vis-configuration.vis-config-item.vis-config-s4{left:30px;background-color:#cfd8e6;padding-left:5px;border-radius:3px}div.vis-configuration.vis-config-header{font-size:18px;font-weight:700}div.vis-configuration.vis-config-label{width:120px;height:25px;line-height:25px}div.vis-configuration.vis-config-label.vis-config-s3{width:110px}div.vis-configuration.vis-config-label.vis-config-s4{width:100px}div.vis-configuration.vis-config-colorBlock{top:1px;width:30px;height:19px;border:1px solid #444;border-radius:2px;padding:0;margin:0;cursor:pointer}input.vis-configuration.vis-config-checkbox{left:-5px}input.vis-configuration.vis-config-rangeinput{position:relative;top:-5px;width:60px;height:13px;padding:1px;margin:0;pointer-events:none}.vis-panel,.vis-timeline{padding:0;box-sizing:border-box}input.vis-configuration.vis-config-range{-webkit-appearance:none;border:0 solid #fff;background-color:transparent;width:300px;height:20px}input.vis-configuration.vis-config-range::-webkit-slider-runnable-track{width:300px;height:5px;background:#dedede;background:-moz-linear-gradient(top,#dedede 0,#c8c8c8 99%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#dedede),color-stop(99%,#c8c8c8));background:-webkit-linear-gradient(top,#dedede 0,#c8c8c8 99%);background:-o-linear-gradient(top,#dedede 0,#c8c8c8 99%);background:-ms-linear-gradient(top,#dedede 0,#c8c8c8 99%);background:linear-gradient(to bottom,#dedede 0,#c8c8c8 99%);filter:progid:DXImageTransform.Microsoft.gradient( startColorstr='#dedede', endColorstr='#c8c8c8', GradientType=0 );border:1px solid #999;box-shadow:#aaa 0 0 3px 0;border-radius:3px}input.vis-configuration.vis-config-range::-webkit-slider-thumb{-webkit-appearance:none;border:1px solid #14334b;height:17px;width:17px;border-radius:50%;background:#3876c2;background:-moz-linear-gradient(top,#3876c2 0,#385380 100%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#3876c2),color-stop(100%,#385380));background:-webkit-linear-gradient(top,#3876c2 0,#385380 100%);background:-o-linear-gradient(top,#3876c2 0,#385380 100%);background:-ms-linear-gradient(top,#3876c2 0,#385380 100%);background:linear-gradient(to bottom,#3876c2 0,#385380 100%);filter:progid:DXImageTransform.Microsoft.gradient( startColorstr='#3876c2', endColorstr='#385380', GradientType=0 );box-shadow:#111927 0 0 1px 0;margin-top:-7px}input.vis-configuration.vis-config-range:focus{outline:0}input.vis-configuration.vis-config-range:focus::-webkit-slider-runnable-track{background:#9d9d9d;background:-moz-linear-gradient(top,#9d9d9d 0,#c8c8c8 99%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#9d9d9d),color-stop(99%,#c8c8c8));background:-webkit-linear-gradient(top,#9d9d9d 0,#c8c8c8 99%);background:-o-linear-gradient(top,#9d9d9d 0,#c8c8c8 99%);background:-ms-linear-gradient(top,#9d9d9d 0,#c8c8c8 99%);background:linear-gradient(to bottom,#9d9d9d 0,#c8c8c8 99%);filter:progid:DXImageTransform.Microsoft.gradient( startColorstr='#9d9d9d', endColorstr='#c8c8c8', GradientType=0 )}input.vis-configuration.vis-config-range::-moz-range-track{width:300px;height:10px;background:#dedede;background:-moz-linear-gradient(top,#dedede 0,#c8c8c8 99%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#dedede),color-stop(99%,#c8c8c8));background:-webkit-linear-gradient(top,#dedede 0,#c8c8c8 99%);background:-o-linear-gradient(top,#dedede 0,#c8c8c8 99%);background:-ms-linear-gradient(top,#dedede 0,#c8c8c8 99%);background:linear-gradient(to bottom,#dedede 0,#c8c8c8 99%);filter:progid:DXImageTransform.Microsoft.gradient( startColorstr='#dedede', endColorstr='#c8c8c8', GradientType=0 );border:1px solid #999;box-shadow:#aaa 0 0 3px 0;border-radius:3px}input.vis-configuration.vis-config-range::-moz-range-thumb{border:none;height:16px;width:16px;border-radius:50%;background:#385380}input.vis-configuration.vis-config-range:-moz-focusring{outline:#fff solid 1px;outline-offset:-1px}input.vis-configuration.vis-config-range::-ms-track{width:300px;height:5px;background:0 0;border-color:transparent;border-width:6px 0;color:transparent}input.vis-configuration.vis-config-range::-ms-fill-lower{background:#777;border-radius:10px}input.vis-configuration.vis-config-range::-ms-fill-upper{background:#ddd;border-radius:10px}input.vis-configuration.vis-config-range::-ms-thumb{border:none;height:16px;width:16px;border-radius:50%;background:#385380}input.vis-configuration.vis-config-range:focus::-ms-fill-lower{background:#888}input.vis-configuration.vis-config-range:focus::-ms-fill-upper{background:#ccc}.vis-configuration-popup{position:absolute;background:rgba(57,76,89,.85);border:2px solid #f2faff;line-height:30px;height:30px;width:150px;text-align:center;color:#fff;font-size:14px;border-radius:4px;-webkit-transition:opacity .3s ease-in-out;-moz-transition:opacity .3s ease-in-out;transition:opacity .3s ease-in-out}.vis-configuration-popup:after,.vis-configuration-popup:before{left:100%;top:50%;border:solid transparent;content:" ";height:0;width:0;position:absolute;pointer-events:none}.vis-configuration-popup:after{border-color:rgba(136,183,213,0);border-left-color:rgba(57,76,89,.85);border-width:8px;margin-top:-8px}.vis-configuration-popup:before{border-color:rgba(194,225,245,0);border-left-color:#f2faff;border-width:12px;margin-top:-12px}.vis-timeline{position:relative;border:1px solid #bfbfbf;margin:0}.vis-panel{position:absolute;margin:0}.vis-panel.vis-bottom,.vis-panel.vis-center,.vis-panel.vis-left,.vis-panel.vis-right,.vis-panel.vis-top{border:1px #bfbfbf}.vis-panel.vis-center,.vis-panel.vis-left,.vis-panel.vis-right{border-top-style:solid;border-bottom-style:solid;overflow:hidden}.vis-panel.vis-bottom,.vis-panel.vis-center,.vis-panel.vis-top{border-left-style:solid;border-right-style:solid}.vis-panel>.vis-content{position:relative}.vis-panel .vis-shadow{position:absolute;width:100%;height:1px;box-shadow:0 0 10px rgba(0,0,0,.8)}.vis-itemset,.vis-labelset,.vis-labelset .vis-label{box-sizing:border-box;position:relative}.vis-panel .vis-shadow.vis-top{top:-1px;left:0}.vis-panel .vis-shadow.vis-bottom{bottom:-1px;left:0}.vis-labelset .vis-label{left:0;top:0;width:100%;color:#4d4d4d;border-bottom:1px solid #bfbfbf}.vis-labelset .vis-label.draggable{cursor:pointer}.vis-labelset .vis-label:last-child{border-bottom:none}.vis-labelset .vis-label .vis-inner{display:inline-block;padding:5px}.vis-labelset .vis-label .vis-inner.vis-hidden{padding:0}.vis-itemset{padding:0;margin:0}.vis-itemset .vis-background,.vis-itemset .vis-foreground{position:absolute;width:100%;height:100%;overflow:visible}.vis-axis{position:absolute;width:100%;height:0;left:0;z-index:1}.vis-foreground .vis-group{position:relative;box-sizing:border-box;border-bottom:1px solid #bfbfbf}.vis-foreground .vis-group:last-child{border-bottom:none}.vis-overlay{position:absolute;top:0;left:0;width:100%;height:100%;z-index:10}.vis-item{position:absolute;color:#1A1A1A;border-color:#97B0F8;border-width:1px;background-color:#D5DDF6;display:inline-block}.vis-item.vis-point.vis-selected,.vis-item.vis-selected{background-color:#FFF785}.vis-item.vis-selected{border-color:#FFC200;z-index:2}.vis-editable.vis-selected{cursor:move}.vis-item.vis-box{text-align:center;border-style:solid;border-radius:2px}.vis-item.vis-point{background:0 0}.vis-item.vis-dot{position:absolute;padding:0;border-width:4px;border-style:solid;border-radius:4px}.vis-item.vis-range{border-style:solid;border-radius:2px;box-sizing:border-box}.vis-item.vis-background{border:none;background-color:rgba(213,221,246,.4);box-sizing:border-box;padding:0;margin:0}.vis-item .vis-item-overflow{position:relative;width:100%;height:100%;padding:0;margin:0;overflow:hidden}.vis-item.vis-range .vis-item-content{position:relative;display:inline-block}.vis-item.vis-background .vis-item-content{position:absolute;display:inline-block}.vis-item.vis-line{padding:0;position:absolute;width:0;border-left-width:1px;border-left-style:solid}.vis-item .vis-item-content{white-space:nowrap;box-sizing:border-box;padding:5px}.vis-item .vis-delete{background:url(img/timeline/delete.png) center no-repeat;position:absolute;width:24px;height:24px;top:-4px;right:-24px;cursor:pointer}.vis-item.vis-range .vis-drag-left{position:absolute;width:24px;max-width:20%;min-width:2px;height:100%;top:0;left:-4px;cursor:w-resize}.vis-item.vis-range .vis-drag-right{position:absolute;width:24px;max-width:20%;min-width:2px;height:100%;top:0;right:-4px;cursor:e-resize}.vis-time-axis{position:relative;overflow:hidden}.vis-time-axis.vis-foreground{top:0;left:0;width:100%}.vis-time-axis.vis-background{position:absolute;top:0;left:0;width:100%;height:100%}.vis-time-axis .vis-text{position:absolute;color:#4d4d4d;padding:3px;overflow:hidden;box-sizing:border-box;white-space:nowrap}.vis-time-axis .vis-text.vis-measure{position:absolute;padding-left:0;padding-right:0;margin-left:0;margin-right:0;visibility:hidden}.vis-time-axis .vis-grid.vis-vertical{position:absolute;border-left:1px solid}.vis-time-axis .vis-grid.vis-minor{border-color:#e5e5e5}.vis-time-axis .vis-grid.vis-major{border-color:#bfbfbf}.vis-current-time{background-color:#FF7F6E;width:2px;z-index:1}.vis-custom-time{background-color:#6E94FF;width:2px;cursor:move;z-index:1}.vis-panel.vis-background.vis-horizontal .vis-grid.vis-horizontal{position:absolute;width:100%;height:0;border-bottom:1px solid}.vis-panel.vis-background.vis-horizontal .vis-grid.vis-minor{border-color:#e5e5e5}.vis-panel.vis-background.vis-horizontal .vis-grid.vis-major{border-color:#bfbfbf}.vis-data-axis .vis-y-axis.vis-major{width:100%;position:absolute;color:#4d4d4d;white-space:nowrap}.vis-data-axis .vis-y-axis.vis-major.vis-measure{padding:0;margin:0;border:0;visibility:hidden;width:auto}.vis-data-axis .vis-y-axis.vis-minor{position:absolute;width:100%;color:#bebebe;white-space:nowrap}.vis-data-axis .vis-y-axis.vis-minor.vis-measure{padding:0;margin:0;border:0;visibility:hidden;width:auto}.vis-data-axis .vis-y-axis.vis-title{position:absolute;color:#4d4d4d;white-space:nowrap;bottom:20px;text-align:center}.vis-data-axis .vis-y-axis.vis-title.vis-measure{padding:0;margin:0;visibility:hidden;width:auto}.vis-data-axis .vis-y-axis.vis-title.vis-left{bottom:0;-webkit-transform-origin:left top;-moz-transform-origin:left top;-ms-transform-origin:left top;-o-transform-origin:left top;transform-origin:left bottom;-webkit-transform:rotate(-90deg);-moz-transform:rotate(-90deg);-ms-transform:rotate(-90deg);-o-transform:rotate(-90deg);transform:rotate(-90deg)}.vis-data-axis .vis-y-axis.vis-title.vis-right{bottom:0;-webkit-transform-origin:right bottom;-moz-transform-origin:right bottom;-ms-transform-origin:right bottom;-o-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:rotate(90deg);-moz-transform:rotate(90deg);-ms-transform:rotate(90deg);-o-transform:rotate(90deg);transform:rotate(90deg)}.vis-legend{background-color:rgba(247,252,255,.65);padding:5px;border:1px solid #b3b3b3;box-shadow:2px 2px 10px rgba(154,154,154,.55)}.vis-legend-text{white-space:nowrap;display:inline-block}.vis-graph-group0{fill:#4f81bd;fill-opacity:0;stroke-width:2px;stroke:#4f81bd}.vis-graph-group1{fill:#f79646;fill-opacity:0;stroke-width:2px;stroke:#f79646}.vis-graph-group2{fill:#8c51cf;fill-opacity:0;stroke-width:2px;stroke:#8c51cf}.vis-graph-group3{fill:#75c841;fill-opacity:0;stroke-width:2px;stroke:#75c841}.vis-graph-group4{fill:#ff0100;fill-opacity:0;stroke-width:2px;stroke:#ff0100}.vis-graph-group5{fill:#37d8e6;fill-opacity:0;stroke-width:2px;stroke:#37d8e6}.vis-graph-group6{fill:#042662;fill-opacity:0;stroke-width:2px;stroke:#042662}.vis-graph-group7{fill:#00ff26;fill-opacity:0;stroke-width:2px;stroke:#00ff26}.vis-graph-group8{fill:#f0f;fill-opacity:0;stroke-width:2px;stroke:#f0f}.vis-graph-group9{fill:#8f3938;fill-opacity:0;stroke-width:2px;stroke:#8f3938}.vis-timeline .vis-fill{fill-opacity:.1;stroke:none}.vis-timeline .vis-bar{fill-opacity:.5;stroke-width:1px}.vis-timeline .vis-point{stroke-width:2px;fill-opacity:1}.vis-timeline .vis-legend-background{stroke-width:1px;fill-opacity:.9;fill:#fff;stroke:#c2c2c2}.vis-timeline .vis-outline{stroke-width:1px;fill-opacity:1;fill:#fff;stroke:#e5e5e5}.vis-timeline .vis-icon-fill{fill-opacity:.3;stroke:none}div.vis-network div.vis-manipulation{border-width:0;border-bottom:1px;border-style:solid;border-color:#d6d9d8;background:#fff;background:-moz-linear-gradient(top,#fff 0,#fcfcfc 48%,#fafafa 50%,#fcfcfc 100%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#fff),color-stop(48%,#fcfcfc),color-stop(50%,#fafafa),color-stop(100%,#fcfcfc));background:-webkit-linear-gradient(top,#fff 0,#fcfcfc 48%,#fafafa 50%,#fcfcfc 100%);background:-o-linear-gradient(top,#fff 0,#fcfcfc 48%,#fafafa 50%,#fcfcfc 100%);background:-ms-linear-gradient(top,#fff 0,#fcfcfc 48%,#fafafa 50%,#fcfcfc 100%);background:linear-gradient(to bottom,#fff 0,#fcfcfc 48%,#fafafa 50%,#fcfcfc 100%);filter:progid:DXImageTransform.Microsoft.gradient( startColorstr='#ffffff', endColorstr='#fcfcfc', GradientType=0 );position:absolute;left:0;top:0;width:100%;height:30px}div.vis-network div.vis-edit-mode{position:absolute;left:0;top:15px;height:30px}div.vis-network div.vis-close{position:absolute;right:0;top:0;width:30px;height:30px;background-position:20px 3px;background-repeat:no-repeat;background-image:url(img/network/cross.png);cursor:pointer;-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}div.vis-network div.vis-close:hover{opacity:.6}div.vis-network div.vis-edit-mode div.vis-button,div.vis-network div.vis-manipulation div.vis-button{position:relative;top:-7px;font-family:verdana;font-size:12px;-moz-border-radius:15px;border-radius:15px;background-position:0 0;height:24px;margin:0 0 0 10px;vertical-align:middle;cursor:pointer;padding:0 8px;user-select:none}div.vis-network div.vis-edit-mode div.vis-button,div.vis-network div.vis-manipulation div.vis-button,div.vis-network div.vis-navigation div.vis-button{display:inline-block;background-repeat:no-repeat;-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none}div.vis-network div.vis-manipulation div.vis-button:hover{box-shadow:1px 1px 8px rgba(0,0,0,.2)}div.vis-network div.vis-manipulation div.vis-button:active{box-shadow:1px 1px 8px rgba(0,0,0,.5)}div.vis-network div.vis-manipulation div.vis-button.vis-back{background-image:url(img/network/backIcon.png)}div.vis-network div.vis-manipulation div.vis-button.vis-none:hover{box-shadow:1px 1px 8px transparent;cursor:default}div.vis-network div.vis-manipulation div.vis-button.vis-none:active{box-shadow:1px 1px 8px transparent}div.vis-network div.vis-manipulation div.vis-button.vis-none{padding:0}div.vis-network div.vis-manipulation div.notification{margin:2px;font-weight:700}div.vis-network div.vis-manipulation div.vis-button.vis-add{background-image:url(img/network/addNodeIcon.png)}div.vis-network div.vis-edit-mode div.vis-button.vis-edit,div.vis-network div.vis-manipulation div.vis-button.vis-edit{background-image:url(img/network/editIcon.png)}div.vis-network div.vis-edit-mode div.vis-button.vis-edit.vis-edit-mode{background-color:#fcfcfc;border:1px solid #ccc}div.vis-network div.vis-manipulation div.vis-button.vis-connect{background-image:url(img/network/connectIcon.png)}div.vis-network div.vis-manipulation div.vis-button.vis-delete{background-image:url(img/network/deleteIcon.png)}div.vis-network div.vis-edit-mode div.vis-label,div.vis-network div.vis-manipulation div.vis-label{margin:0 0 0 23px;line-height:25px}div.vis-network div.vis-manipulation div.vis-separator-line{display:inline-block;width:1px;height:20px;background-color:#bdbdbd;margin:5px 7px 0 15px}div.vis-network-tooltip{position:absolute;visibility:hidden;padding:5px;white-space:nowrap;font-family:verdana;font-size:14px;font-color:#000;background-color:#f5f4ed;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px;border:1px solid #808074;box-shadow:3px 3px 10px rgba(0,0,0,.2);pointer-events:none}div.vis-network div.vis-navigation div.vis-button{width:34px;height:34px;-moz-border-radius:17px;border-radius:17px;position:absolute;background-position:2px 2px;cursor:pointer;user-select:none}div.vis-network div.vis-navigation div.vis-button:hover{box-shadow:0 0 3px 3px rgba(56,207,21,.3)}div.vis-network div.vis-navigation div.vis-button:active{box-shadow:0 0 1px 3px rgba(56,207,21,.95)}div.vis-network div.vis-navigation div.vis-button.vis-up{background-image:url(img/network/upArrow.png);bottom:50px;left:55px}div.vis-network div.vis-navigation div.vis-button.vis-down{background-image:url(img/network/downArrow.png);bottom:10px;left:55px}div.vis-network div.vis-navigation div.vis-button.vis-left{background-image:url(img/network/leftArrow.png);bottom:10px;left:15px}div.vis-network div.vis-navigation div.vis-button.vis-right{background-image:url(img/network/rightArrow.png);bottom:10px;left:95px}div.vis-network div.vis-navigation div.vis-button.vis-zoomIn{background-image:url(img/network/plus.png);bottom:10px;right:15px}div.vis-network div.vis-navigation div.vis-button.vis-zoomOut{background-image:url(img/network/minus.png);bottom:10px;right:55px}div.vis-network div.vis-navigation div.vis-button.vis-zoomExtends{background-image:url(img/network/zoomExtends.png);bottom:50px;right:15px}div.vis-color-picker{position:absolute;margin-top:-140px;margin-left:30px;width:293px;height:425px;padding:10px;border-radius:15px;background-color:#fff;display:none;box-shadow:rgba(0,0,0,.5) 0 0 10px 0}div.vis-color-picker div.vis-arrow{position:absolute;top:147px;left:5px}div.vis-color-picker div.vis-arrow:after,div.vis-color-picker div.vis-arrow:before{right:100%;top:50%;border:solid transparent;content:" ";height:0;width:0;position:absolute;pointer-events:none}div.vis-color-picker div.vis-arrow:after{border-color:rgba(255,255,255,0);border-right-color:#fff;border-width:30px;margin-top:-30px}div.vis-color-picker div.vis-color{position:absolute;width:289px;height:289px;cursor:pointer}div.vis-color-picker div.vis-brightness{position:absolute;top:313px}div.vis-color-picker div.vis-opacity{position:absolute;top:350px}div.vis-color-picker div.vis-selector{position:absolute;top:137px;left:137px;width:15px;height:15px;border-radius:15px;border:1px solid #fff;background:#4c4c4c;background:-moz-linear-gradient(top,#4c4c4c 0,#595959 12%,#666 25%,#474747 39%,#2c2c2c 50%,#000 51%,#111 60%,#2b2b2b 76%,#1c1c1c 91%,#131313 100%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#4c4c4c),color-stop(12%,#595959),color-stop(25%,#666),color-stop(39%,#474747),color-stop(50%,#2c2c2c),color-stop(51%,#000),color-stop(60%,#111),color-stop(76%,#2b2b2b),color-stop(91%,#1c1c1c),color-stop(100%,#131313));background:-webkit-linear-gradient(top,#4c4c4c 0,#595959 12%,#666 25%,#474747 39%,#2c2c2c 50%,#000 51%,#111 60%,#2b2b2b 76%,#1c1c1c 91%,#131313 100%);background:-o-linear-gradient(top,#4c4c4c 0,#595959 12%,#666 25%,#474747 39%,#2c2c2c 50%,#000 51%,#111 60%,#2b2b2b 76%,#1c1c1c 91%,#131313 100%);background:-ms-linear-gradient(top,#4c4c4c 0,#595959 12%,#666 25%,#474747 39%,#2c2c2c 50%,#000 51%,#111 60%,#2b2b2b 76%,#1c1c1c 91%,#131313 100%);background:linear-gradient(to bottom,#4c4c4c 0,#595959 12%,#666 25%,#474747 39%,#2c2c2c 50%,#000 51%,#111 60%,#2b2b2b 76%,#1c1c1c 91%,#131313 100%);filter:progid:DXImageTransform.Microsoft.gradient( startColorstr='#4c4c4c', endColorstr='#131313', GradientType=0 )}div.vis-color-picker div.vis-initial-color,div.vis-color-picker div.vis-new-color{position:absolute;vertical-align:middle;width:140px;height:20px;top:380px;font-size:10px;color:rgba(0,0,0,.4);line-height:20px}div.vis-color-picker div.vis-new-color{border:1px solid rgba(0,0,0,.1);border-radius:5px;left:159px;text-align:right;padding-right:2px}div.vis-color-picker div.vis-initial-color{border:1px solid rgba(0,0,0,.1);border-radius:5px;left:10px;text-align:left;padding-left:2px}div.vis-color-picker div.vis-label{position:absolute;width:300px;left:10px}div.vis-color-picker div.vis-label.vis-brightness{top:300px}div.vis-color-picker div.vis-label.vis-opacity{top:338px}div.vis-color-picker div.vis-button{position:absolute;width:68px;height:25px;border-radius:10px;vertical-align:middle;text-align:center;line-height:25px;top:410px;border:2px solid #d9d9d9;background-color:#f7f7f7;cursor:pointer}div.vis-color-picker div.vis-button.vis-cancel{left:5px}div.vis-color-picker div.vis-button.vis-load{left:82px}div.vis-color-picker div.vis-button.vis-apply{left:159px}div.vis-color-picker div.vis-button.vis-save{left:236px}div.vis-color-picker input.vis-range{width:290px;height:20px} \ No newline at end of file diff --git a/examples/network/exampleUtil.js b/examples/network/exampleUtil.js index a5554ced..aeeb2df1 100644 --- a/examples/network/exampleUtil.js +++ b/examples/network/exampleUtil.js @@ -66,5 +66,61 @@ function getScaleFreeNetwork(nodeCount) { } } + return {nodes:nodes, edges:edges}; +} + +var randomSeed = 764; // Math.round(Math.random()*1000); +function seededRandom() { + var x = Math.sin(randomSeed++) * 10000; + return x - Math.floor(x); +} + +function getScaleFreeNetworkSeeded(nodeCount) { + var nodes = []; + var edges = []; + var connectionCount = []; + + // randomly create some nodes and edges + for (var i = 0; i < nodeCount; i++) { + nodes.push({ + id: i, + label: String(i) + }); + + connectionCount[i] = 0; + + // create edges in a scale-free-network way + if (i == 1) { + var from = i; + var to = 0; + edges.push({ + from: from, + to: to + }); + connectionCount[from]++; + connectionCount[to]++; + } + else if (i > 1) { + var conn = edges.length * 2; + var rand = Math.floor(seededRandom() * conn); + var cum = 0; + var j = 0; + while (j < connectionCount.length && cum < rand) { + cum += connectionCount[j]; + j++; + } + + + var from = i; + var to = j; + edges.push({ + from: from, + to: to + }); + connectionCount[from]++; + connectionCount[to]++; + } + } + return {nodes:nodes, edges:edges}; } \ No newline at end of file diff --git a/lib/network/NetworkUtil.js b/lib/network/NetworkUtil.js new file mode 100644 index 00000000..44523e63 --- /dev/null +++ b/lib/network/NetworkUtil.js @@ -0,0 +1,77 @@ + +class NetworkUtil { + constructor() {} + + /** + * Find the center position of the network considering the bounding boxes + * @private + */ + static _getRange(allNodes, specificNodes = []) { + var minY = 1e9, maxY = -1e9, minX = 1e9, maxX = -1e9, node; + if (specificNodes.length > 0) { + for (var i = 0; i < specificNodes.length; i++) { + node = allNodes[specificNodes[i]]; + if (minX > node.shape.boundingBox.left) { + minX = node.shape.boundingBox.left; + } + if (maxX < node.shape.boundingBox.right) { + maxX = node.shape.boundingBox.right; + } + if (minY > node.shape.boundingBox.top) { + minY = node.shape.boundingBox.top; + } // top is negative, bottom is positive + if (maxY < node.shape.boundingBox.bottom) { + maxY = node.shape.boundingBox.bottom; + } // top is negative, bottom is positive + } + } + + if (minX === 1e9 && maxX === -1e9 && minY === 1e9 && maxY === -1e9) { + minY = 0, maxY = 0, minX = 0, maxX = 0; + } + return {minX: minX, maxX: maxX, minY: minY, maxY: maxY}; + } + + /** + * Find the center position of the network + * @private + */ + static _getRangeCore(allNodes, specificNodes = []) { + var minY = 1e9, maxY = -1e9, minX = 1e9, maxX = -1e9, node; + if (specificNodes.length > 0) { + for (var i = 0; i < specificNodes.length; i++) { + node = allNodes[specificNodes[i]]; + if (minX > node.x) { + minX = node.x; + } + if (maxX < node.x) { + maxX = node.x; + } + if (minY > node.y) { + minY = node.y; + } // top is negative, bottom is positive + if (maxY < node.y) { + maxY = node.y; + } // top is negative, bottom is positive + } + } + + if (minX === 1e9 && maxX === -1e9 && minY === 1e9 && maxY === -1e9) { + minY = 0, maxY = 0, minX = 0, maxX = 0; + } + return {minX: minX, maxX: maxX, minY: minY, maxY: maxY}; + } + + + /** + * @param {object} range = {minX: minX, maxX: maxX, minY: minY, maxY: maxY}; + * @returns {{x: number, y: number}} + * @private + */ + static _findCenter(range) { + return {x: (0.5 * (range.maxX + range.minX)), + y: (0.5 * (range.maxY + range.minY))}; + } +} + +export default NetworkUtil; \ No newline at end of file diff --git a/lib/network/modules/Canvas.js b/lib/network/modules/Canvas.js index 0b7fe972..55acb2df 100644 --- a/lib/network/modules/Canvas.js +++ b/lib/network/modules/Canvas.js @@ -87,10 +87,10 @@ class Canvas { * Get and store the cameraState * @private */ - _getCameraState() { - this.cameraState.previousWidth = this.frame.canvas.width; + _getCameraState(pixelRatio = this.pixelRatio) { + this.cameraState.previousWidth = this.frame.canvas.width / pixelRatio; this.cameraState.scale = this.body.view.scale; - this.cameraState.position = this.DOMtoCanvas({x: 0.5 * this.frame.canvas.width, y: 0.5 * this.frame.canvas.height}); + this.cameraState.position = this.DOMtoCanvas({x: 0.5 * this.frame.canvas.width / pixelRatio, y: 0.5 * this.frame.canvas.height / pixelRatio}); } /** @@ -99,16 +99,17 @@ class Canvas { */ _setCameraState() { if (this.cameraState.scale !== undefined) { - this.body.view.scale = this.body.view.scale * (this.frame.canvas.clientWidth / this.cameraState.previousWidth); + this.body.view.scale = this.cameraState.scale * ((this.frame.canvas.width / this.pixelRatio) / this.cameraState.previousWidth); // this comes from the view module. - var viewCenter = this.DOMtoCanvas({ + var currentViewCenter = this.DOMtoCanvas({ x: 0.5 * this.frame.canvas.clientWidth, y: 0.5 * this.frame.canvas.clientHeight }); + var distanceFromCenter = { // offset from view, distance view has to change by these x and y to center the node - x: viewCenter.x - this.cameraState.position.x, - y: viewCenter.y - this.cameraState.position.y + x: currentViewCenter.x - this.cameraState.position.x, + y: currentViewCenter.y - this.cameraState.position.y }; this.body.view.translation.x += distanceFromCenter.x * this.body.view.scale; this.body.view.translation.y += distanceFromCenter.y * this.body.view.scale; @@ -127,7 +128,7 @@ class Canvas { return value + 'px'; } } - throw new Error('Could not use the value supplie for width or height:' + value); + throw new Error('Could not use the value supplied for width or height:' + value); } @@ -227,7 +228,6 @@ class Canvas { * or '30%') */ setSize(width = this.options.width, height = this.options.height) { - this._getCameraState(); width = this._prepareValue(width); height= this._prepareValue(height); @@ -235,7 +235,18 @@ class Canvas { let oldWidth = this.frame.canvas.width; let oldHeight = this.frame.canvas.height; + // update the pixelratio + let ctx = this.frame.canvas.getContext("2d"); + let previousRation = this.pixelRatio; // we cache this because the camera state storage needs the old value + this.pixelRatio = (window.devicePixelRatio || 1) / (ctx.webkitBackingStorePixelRatio || + ctx.mozBackingStorePixelRatio || + ctx.msBackingStorePixelRatio || + ctx.oBackingStorePixelRatio || + ctx.backingStorePixelRatio || 1); + if (width != this.options.width || height != this.options.height || this.frame.style.width != width || this.frame.style.height != height) { + this._getCameraState(previousRation); + this.frame.style.width = width; this.frame.style.height = height; @@ -254,6 +265,11 @@ class Canvas { // this would adapt the width of the canvas to the width from 100% if and only if // there is a change. + // store the camera if there is a change in size. + if (this.frame.canvas.width != Math.round(this.frame.canvas.clientWidth * this.pixelRatio) || this.frame.canvas.height != Math.round(this.frame.canvas.clientHeight * this.pixelRatio)) { + this._getCameraState(previousRation); + } + if (this.frame.canvas.width != Math.round(this.frame.canvas.clientWidth * this.pixelRatio)) { this.frame.canvas.width = Math.round(this.frame.canvas.clientWidth * this.pixelRatio); emitEvent = true; @@ -271,8 +287,11 @@ class Canvas { oldWidth: Math.round(oldWidth / this.pixelRatio), oldHeight: Math.round(oldHeight / this.pixelRatio) }); + + // restore the camera on change. + this._setCameraState(); } - this._setCameraState(); + return emitEvent; }; diff --git a/lib/network/modules/CanvasRenderer.js b/lib/network/modules/CanvasRenderer.js index 8673fdd3..9ddbb6a1 100644 --- a/lib/network/modules/CanvasRenderer.js +++ b/lib/network/modules/CanvasRenderer.js @@ -147,13 +147,11 @@ class CanvasRenderer { this.canvas.setSize(); } - if (this.pixelRatio === undefined) { - this.pixelRatio = (window.devicePixelRatio || 1) / (ctx.webkitBackingStorePixelRatio || - ctx.mozBackingStorePixelRatio || - ctx.msBackingStorePixelRatio || - ctx.oBackingStorePixelRatio || - ctx.backingStorePixelRatio || 1); - } + this.pixelRatio = (window.devicePixelRatio || 1) / (ctx.webkitBackingStorePixelRatio || + ctx.mozBackingStorePixelRatio || + ctx.msBackingStorePixelRatio || + ctx.oBackingStorePixelRatio || + ctx.backingStorePixelRatio || 1); ctx.setTransform(this.pixelRatio, 0, 0, this.pixelRatio, 0, 0); diff --git a/lib/network/modules/LayoutEngine.js b/lib/network/modules/LayoutEngine.js index 8c42ce9a..1c5fde68 100644 --- a/lib/network/modules/LayoutEngine.js +++ b/lib/network/modules/LayoutEngine.js @@ -1,6 +1,7 @@ 'use strict' let util = require('../../util'); +import NetworkUtil from '../NetworkUtil'; class LayoutEngine { constructor(body) { @@ -207,6 +208,7 @@ class LayoutEngine { let after = this.body.nodeIndices.length; if ((before == after && levels % 3 !== 0) || levels > MAX_LEVELS) { this._declusterAll(); + this.body.emitter.emit("_layoutFailed"); console.info("This network could not be positioned by this version of the improved layout algorithm."); return; } @@ -218,6 +220,15 @@ class LayoutEngine { // position the system for these nodes and edges this.body.modules.kamadaKawai.solve(this.body.nodeIndices, this.body.edgeIndices, true); + // shift to center point + this._shiftToCenter(); + + // perturb the nodes a little bit to force the physics to kick in + for (let i = 0; i < this.body.nodeIndices.length; i++) { + this.body.nodes[this.body.nodeIndices[i]].x += (0.5 - this.seededRandom())*50; + this.body.nodes[this.body.nodeIndices[i]].y += (0.5 - this.seededRandom())*50; + } + // uncluster all clusters this._declusterAll(); @@ -227,6 +238,19 @@ class LayoutEngine { } } + /** + * Move all the nodes towards to the center so gravitational pull wil not move the nodes away from view + * @private + */ + _shiftToCenter() { + let range = NetworkUtil._getRangeCore(this.body.nodes, this.body.nodeIndices); + let center = NetworkUtil._findCenter(range); + for (let i = 0; i < this.body.nodeIndices.length; i++) { + this.body.nodes[this.body.nodeIndices[i]].x -= center.x; + this.body.nodes[this.body.nodeIndices[i]].y -= center.y; + } + } + _declusterAll() { let clustersPresent = true; while (clustersPresent === true) { diff --git a/lib/network/modules/PhysicsEngine.js b/lib/network/modules/PhysicsEngine.js index c1a2c3fe..16169f81 100644 --- a/lib/network/modules/PhysicsEngine.js +++ b/lib/network/modules/PhysicsEngine.js @@ -86,12 +86,14 @@ class PhysicsEngine { }; util.extend(this.options, this.defaultOptions); this.timestep = 0.5; + this.layoutFailed = false; this.bindEventListeners(); } bindEventListeners() { this.body.emitter.on('initPhysics', () => {this.initPhysics();}); + this.body.emitter.on('_layoutFailed', () => {this.layoutFailed = true;}); this.body.emitter.on('resetPhysics', () => {this.stopSimulation(); this.ready = false;}); this.body.emitter.on('disablePhysics', () => {this.physicsEnabled = false; this.stopSimulation();}); this.body.emitter.on('restorePhysics', () => { @@ -191,7 +193,7 @@ class PhysicsEngine { else { this.stabilized = false; this.ready = true; - this.body.emitter.emit('fit', {}, false); + this.body.emitter.emit('fit', {}, this.layoutFailed); // if the layout failed, we use the approximation for the zoom this.startSimulation(); } } diff --git a/lib/network/modules/View.js b/lib/network/modules/View.js index 58683115..d8e71c3e 100644 --- a/lib/network/modules/View.js +++ b/lib/network/modules/View.js @@ -1,4 +1,6 @@ -var util = require('../../util'); +let util = require('../../util'); + +import NetworkUtil from '../NetworkUtil'; class View { constructor(body, canvas) { @@ -29,80 +31,25 @@ class View { } - /** - * Find the center position of the network - * @private - */ - _getRange(specificNodes = []) { - var minY = 1e9, maxY = -1e9, minX = 1e9, maxX = -1e9, node; - if (specificNodes.length > 0) { - for (var i = 0; i < specificNodes.length; i++) { - node = this.body.nodes[specificNodes[i]]; - if (minX > (node.shape.boundingBox.left)) { - minX = node.shape.boundingBox.left; - } - if (maxX < (node.shape.boundingBox.right)) { - maxX = node.shape.boundingBox.right; - } - if (minY > (node.shape.boundingBox.top)) { - minY = node.shape.boundingBox.top; - } // top is negative, bottom is positive - if (maxY < (node.shape.boundingBox.bottom)) { - maxY = node.shape.boundingBox.bottom; - } // top is negative, bottom is positive - } - } - else { - for (var i = 0; i < this.body.nodeIndices.length; i++) { - node = this.body.nodes[this.body.nodeIndices[i]]; - if (minX > (node.shape.boundingBox.left)) { - minX = node.shape.boundingBox.left; - } - if (maxX < (node.shape.boundingBox.right)) { - maxX = node.shape.boundingBox.right; - } - if (minY > (node.shape.boundingBox.top)) { - minY = node.shape.boundingBox.top; - } // top is negative, bottom is positive - if (maxY < (node.shape.boundingBox.bottom)) { - maxY = node.shape.boundingBox.bottom; - } // top is negative, bottom is positive - } - } - - if (minX === 1e9 && maxX === -1e9 && minY === 1e9 && maxY === -1e9) { - minY = 0, maxY = 0, minX = 0, maxX = 0; - } - return {minX: minX, maxX: maxX, minY: minY, maxY: maxY}; - } - - - /** - * @param {object} range = {minX: minX, maxX: maxX, minY: minY, maxY: maxY}; - * @returns {{x: number, y: number}} - * @private - */ - _findCenter(range) { - return {x: (0.5 * (range.maxX + range.minX)), - y: (0.5 * (range.maxY + range.minY))}; - } - - /** * This function zooms out to fit all data on screen based on amount of nodes * @param {Object} Options * @param {Boolean} [initialZoom] | zoom based on fitted formula or range, true = fitted, default = false; */ fit(options = {nodes:[]}, initialZoom = false) { - var range; - var zoomLevel; + let range; + let zoomLevel; + if (options.nodes === undefined || options.nodes.length === 0) { + options.nodes = this.body.nodeIndices; + } + if (initialZoom === true) { // check if more than half of the nodes have a predefined position. If so, we use the range, not the approximation. - var positionDefined = 0; - for (var nodeId in this.body.nodes) { + let positionDefined = 0; + for (let nodeId in this.body.nodes) { if (this.body.nodes.hasOwnProperty(nodeId)) { - var node = this.body.nodes[nodeId]; + let node = this.body.nodes[nodeId]; if (node.predefinedPosition === true) { positionDefined += 1; } @@ -113,24 +60,24 @@ class View { return; } - range = this._getRange(options.nodes); + range = NetworkUtil._getRange(this.body.nodes, options.nodes); - var numberOfNodes = this.body.nodeIndices.length; + let numberOfNodes = this.body.nodeIndices.length; zoomLevel = 12.662 / (numberOfNodes + 7.4147) + 0.0964822; // this is obtained from fitting a dataset from 5 points with scale levels that looked good. // correct for larger canvasses. - var factor = Math.min(this.canvas.frame.canvas.clientWidth / 600, this.canvas.frame.canvas.clientHeight / 600); + let factor = Math.min(this.canvas.frame.canvas.clientWidth / 600, this.canvas.frame.canvas.clientHeight / 600); zoomLevel *= factor; } else { this.body.emitter.emit("_resizeNodes"); - range = this._getRange(options.nodes); + range = NetworkUtil._getRange(this.body.nodes, options.nodes); - var xDistance = Math.abs(range.maxX - range.minX) * 1.1; - var yDistance = Math.abs(range.maxY - range.minY) * 1.1; + let xDistance = Math.abs(range.maxX - range.minX) * 1.1; + let yDistance = Math.abs(range.maxY - range.minY) * 1.1; - var xZoomLevel = this.canvas.frame.canvas.clientWidth / xDistance; - var yZoomLevel = this.canvas.frame.canvas.clientHeight / yDistance; + let xZoomLevel = this.canvas.frame.canvas.clientWidth / xDistance; + let yZoomLevel = this.canvas.frame.canvas.clientHeight / yDistance; zoomLevel = (xZoomLevel <= yZoomLevel) ? xZoomLevel : yZoomLevel; } @@ -142,8 +89,8 @@ class View { zoomLevel = 1.0; } - var center = this._findCenter(range); - var animationOptions = {position: center, scale: zoomLevel, animation: options.animation}; + let center = NetworkUtil._findCenter(range); + let animationOptions = {position: center, scale: zoomLevel, animation: options.animation}; this.moveTo(animationOptions); } @@ -157,7 +104,7 @@ class View { */ focus(nodeId, options = {}) { if (this.body.nodes[nodeId] !== undefined) { - var nodePosition = {x: this.body.nodes[nodeId].x, y: this.body.nodes[nodeId].y}; + let nodePosition = {x: this.body.nodes[nodeId].x, y: this.body.nodes[nodeId].y}; options.position = nodePosition; options.lockedOnNode = nodeId; @@ -229,9 +176,9 @@ class View { // set the scale so the viewCenter is based on the correct zoom level. This is overridden in the transitionRedraw // but at least then we'll have the target transition this.body.view.scale = this.targetScale; - var viewCenter = this.canvas.DOMtoCanvas({x: 0.5 * this.canvas.frame.canvas.clientWidth, y: 0.5 * this.canvas.frame.canvas.clientHeight}); + let viewCenter = this.canvas.DOMtoCanvas({x: 0.5 * this.canvas.frame.canvas.clientWidth, y: 0.5 * this.canvas.frame.canvas.clientHeight}); - var distanceFromCenter = { // offset from view, distance view has to change by these x and y to center the node + let distanceFromCenter = { // offset from view, distance view has to change by these x and y to center the node x: viewCenter.x - options.position.x, y: viewCenter.y - options.position.y }; @@ -268,14 +215,14 @@ class View { * @private */ _lockedRedraw() { - var nodePosition = {x: this.body.nodes[this.lockedOnNodeId].x, y: this.body.nodes[this.lockedOnNodeId].y}; - var viewCenter = this.canvas.DOMtoCanvas({x: 0.5 * this.canvas.frame.canvas.clientWidth, y: 0.5 * this.canvas.frame.canvas.clientHeight}); - var distanceFromCenter = { // offset from view, distance view has to change by these x and y to center the node + let nodePosition = {x: this.body.nodes[this.lockedOnNodeId].x, y: this.body.nodes[this.lockedOnNodeId].y}; + let viewCenter = this.canvas.DOMtoCanvas({x: 0.5 * this.canvas.frame.canvas.clientWidth, y: 0.5 * this.canvas.frame.canvas.clientHeight}); + let distanceFromCenter = { // offset from view, distance view has to change by these x and y to center the node x: viewCenter.x - nodePosition.x, y: viewCenter.y - nodePosition.y }; - var sourceTranslation = this.body.view.translation; - var targetTranslation = { + let sourceTranslation = this.body.view.translation; + let targetTranslation = { x: sourceTranslation.x + distanceFromCenter.x * this.body.view.scale + this.lockedOnNodeOffset.x, y: sourceTranslation.y + distanceFromCenter.y * this.body.view.scale + this.lockedOnNodeOffset.y }; @@ -300,7 +247,7 @@ class View { this.easingTime += this.animationSpeed; this.easingTime = finished === true ? 1.0 : this.easingTime; - var progress = util.easingFunctions[this.animationEasingFunction](this.easingTime); + let progress = util.easingFunctions[this.animationEasingFunction](this.easingTime); this.body.view.scale = this.sourceScale + (this.targetScale - this.sourceScale) * progress; this.body.view.translation = { diff --git a/test/networkTest.html b/test/networkTest.html index 441a5a08..a6627699 100644 --- a/test/networkTest.html +++ b/test/networkTest.html @@ -1,74 +1,95 @@ - Network | Basic usage - - - + Vis Popup Example - - - -

- Create a simple network with some nodes and edges. -

- -
- - + + + + + + + + + +

Popup Example

+ + - +
- + \ No newline at end of file From 21fc4833c7d5496c456172121302a00c6bc5fafb Mon Sep 17 00:00:00 2001 From: Alex de Mulder Date: Sun, 6 Sep 2015 15:41:09 +0200 Subject: [PATCH 004/205] Fixed unselectAll method --- HISTORY.md | 1 + dist/vis.js | 76 ++++++++++++++++++++++++++++-------------- lib/network/Network.js | 5 ++- 3 files changed, 56 insertions(+), 26 deletions(-) diff --git a/HISTORY.md b/HISTORY.md index bfb1741c..7aef9f36 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -8,6 +8,7 @@ http://visjs.org - Added German (de) locale. Thanks @Tooa. - Fixed critical camera zoom bug #1273. +- Fixed unselectAll method. #1256 ### Timeline diff --git a/dist/vis.js b/dist/vis.js index cdace7bc..ac903761 100644 --- a/dist/vis.js +++ b/dist/vis.js @@ -16651,7 +16651,7 @@ return /******/ (function(modules) { // webpackBootstrap item: dragLeftItem, initialX: event.center.x, dragLeft: true, - data: util.extend({}, item.data) // clone the items data + data: this._cloneItemData(item.data) }; this.touchParams.itemProps = [props]; @@ -16660,7 +16660,7 @@ return /******/ (function(modules) { // webpackBootstrap item: dragRightItem, initialX: event.center.x, dragRight: true, - data: util.extend({}, item.data) // clone the items data + data: this._cloneItemData(item.data) }; this.touchParams.itemProps = [props]; @@ -16669,18 +16669,16 @@ return /******/ (function(modules) { // webpackBootstrap var baseGroupIndex = this._getGroupIndex(item.data.group); - this.touchParams.itemProps = this.getSelection().map(function (id) { + this.touchParams.itemProps = this.getSelection().map((function (id) { var item = me.items[id]; var groupIndex = me._getGroupIndex(item.data.group); - var props = { + return { item: item, initialX: event.center.x, groupOffset: baseGroupIndex - groupIndex, - data: util.extend({}, item.data) // clone the items data + data: this._cloneItemData(item.data) }; - - return props; - }); + }).bind(this)); } event.stopPropagation(); @@ -16722,14 +16720,14 @@ return /******/ (function(modules) { // webpackBootstrap var newItem = new RangeItem(itemData, this.conversion, this.options); newItem.id = id; // TODO: not so nice setting id afterwards - newItem.data = itemData; + newItem.data = this._cloneItemData(itemData); this._addItem(newItem); var props = { item: newItem, dragRight: true, initialX: event.center.x, - data: util.extend({}, itemData) + data: newItem.data }; this.touchParams.itemProps = [props]; @@ -16768,14 +16766,12 @@ return /******/ (function(modules) { // webpackBootstrap } // move - this.touchParams.itemProps.forEach(function (props) { - var newProps = {}; + this.touchParams.itemProps.forEach((function (props) { var current = me.body.util.toTime(event.center.x - xOffset); var initial = me.body.util.toTime(props.initialX - xOffset); - var offset = current - initial; - - var itemData = util.extend({}, props.item.data); // clone the data + var offset = current - initial; // ms + var itemData = this._cloneItemData(props.item.data); // clone the data if (props.item.editable === false) { return; } @@ -16788,6 +16784,7 @@ return /******/ (function(modules) { // webpackBootstrap if (itemData.start != undefined) { var initialStart = util.convert(props.data.start, 'Date'); var start = new Date(initialStart.valueOf() + offset); + // TODO: pass a Moment instead of a Date to snap(). (Breaking change) itemData.start = snap ? snap(start, scale, step) : start; } } else if (props.dragRight) { @@ -16795,6 +16792,7 @@ return /******/ (function(modules) { // webpackBootstrap if (itemData.end != undefined) { var initialEnd = util.convert(props.data.end, 'Date'); var end = new Date(initialEnd.valueOf() + offset); + // TODO: pass a Moment instead of a Date to snap(). (Breaking change) itemData.end = snap ? snap(end, scale, step) : end; } } else { @@ -16807,9 +16805,11 @@ return /******/ (function(modules) { // webpackBootstrap var initialEnd = util.convert(props.data.end, 'Date'); var duration = initialEnd.valueOf() - initialStart.valueOf(); + // TODO: pass a Moment instead of a Date to snap(). (Breaking change) itemData.start = snap ? snap(start, scale, step) : start; itemData.end = new Date(itemData.start.valueOf() + duration); } else { + // TODO: pass a Moment instead of a Date to snap(). (Breaking change) itemData.start = snap ? snap(start, scale, step) : start; } } @@ -16831,12 +16831,13 @@ return /******/ (function(modules) { // webpackBootstrap } // confirm moving the item + itemData = this._cloneItemData(itemData); // convert start and end to the correct type me.options.onMoving(itemData, function (itemData) { if (itemData) { props.item.setData(itemData); } }); - }); + }).bind(this)); this.stackDirty = true; // force re-stacking of all items next redraw this.body.emitter.emit('change'); @@ -16876,7 +16877,7 @@ return /******/ (function(modules) { // webpackBootstrap var itemProps = this.touchParams.itemProps; this.touchParams.itemProps = null; - itemProps.forEach(function (props) { + itemProps.forEach((function (props) { var id = props.item.id; var exists = me.itemsData.get(id, me.itemOptions) != null; @@ -16894,7 +16895,7 @@ return /******/ (function(modules) { // webpackBootstrap }); } else { // update existing item - var itemData = util.extend({}, props.item.data); // clone the data + var itemData = this._cloneItemData(props.item.data); // convert start and end to the correct type me.options.onMove(itemData, function (itemData) { if (itemData) { // apply changes @@ -16909,7 +16910,7 @@ return /******/ (function(modules) { // webpackBootstrap } }); } - }); + }).bind(this)); } }; @@ -17150,7 +17151,7 @@ return /******/ (function(modules) { // webpackBootstrap var scale = this.body.util.getScale(); var step = this.body.util.getStep(); - var newItem = { + var newItemData = { start: snap ? snap(start, scale, step) : start, content: 'new item' }; @@ -17158,18 +17159,19 @@ return /******/ (function(modules) { // webpackBootstrap // when default type is a range, add a default end date to the new item if (this.options.type === 'range') { var end = this.body.util.toTime(x + this.props.width / 5); - newItem.end = snap ? snap(end, scale, step) : end; + newItemData.end = snap ? snap(end, scale, step) : end; } - newItem[this.itemsData._fieldId] = util.randomUUID(); + newItemData[this.itemsData._fieldId] = util.randomUUID(); var group = this.groupFromTarget(event); if (group) { - newItem.group = group.groupId; + newItemData.group = group.groupId; } // execute async handler to customize (or cancel) adding an item - this.options.onAdd(newItem, function (item) { + newItemData = this._cloneItemData(newItemData); // convert start and end to the correct type + this.options.onAdd(newItemData, function (item) { if (item) { me.itemsData.getDataSet().add(item); // TODO: need to trigger a redraw? @@ -17336,6 +17338,29 @@ return /******/ (function(modules) { // webpackBootstrap return null; }; + /** + * Clone the data of an item, and "normalize" it: convert the start and end date + * to the type (Date, Moment, ...) configured in the DataSet. If not configured, + * start and end are converted to Date. + * @param {Object} itemData, typically `item.data` + * @return {Object} The cloned object + * @private + */ + ItemSet.prototype._cloneItemData = function (itemData) { + var clone = util.extend({}, itemData); + + // convert start and end date to the type (Date, Moment, ...) configured in the DataSet + var type = this.itemsData.getDataSet()._options.type; + if (clone.start != undefined) { + clone.start = util.convert(clone.start, type && type.start || 'Date'); + } + if (clone.end != undefined) { + clone.end = util.convert(clone.end, type && type.end || 'Date'); + } + + return clone; + }; + module.exports = ItemSet; /***/ }, @@ -27366,7 +27391,8 @@ return /******/ (function(modules) { // webpackBootstrap return this.selectionHandler.selectEdges.apply(this.selectionHandler, arguments); }; Network.prototype.unselectAll = function () { - return this.selectionHandler.unselectAll.apply(this.selectionHandler, arguments); + this.selectionHandler.unselectAll.apply(this.selectionHandler, arguments); + this.redraw(); }; Network.prototype.redraw = function () { return this.renderer.redraw.apply(this.renderer, arguments); diff --git a/lib/network/Network.js b/lib/network/Network.js index 57ad80b5..7b3ae0e1 100644 --- a/lib/network/Network.js +++ b/lib/network/Network.js @@ -485,7 +485,10 @@ Network.prototype.getEdgeAt = function() { }; Network.prototype.selectNodes = function() {return this.selectionHandler.selectNodes.apply(this.selectionHandler,arguments);}; Network.prototype.selectEdges = function() {return this.selectionHandler.selectEdges.apply(this.selectionHandler,arguments);}; -Network.prototype.unselectAll = function() {return this.selectionHandler.unselectAll.apply(this.selectionHandler,arguments);}; +Network.prototype.unselectAll = function() { + this.selectionHandler.unselectAll.apply(this.selectionHandler,arguments); + this.redraw(); +}; Network.prototype.redraw = function() {return this.renderer.redraw.apply(this.renderer,arguments);}; Network.prototype.getScale = function() {return this.view.getScale.apply(this.view,arguments);}; Network.prototype.getViewPosition = function() {return this.view.getViewPosition.apply(this.view,arguments);}; From 6581f56c638ce9f31c482d90ca0e66f22c392a43 Mon Sep 17 00:00:00 2001 From: Alex de Mulder Date: Sun, 6 Sep 2015 16:07:27 +0200 Subject: [PATCH 005/205] - Fixed bug that broke the network if drawn in a hidden div #1254 --- HISTORY.md | 1 + dist/vis.js | 8 +++- lib/network/modules/Canvas.js | 7 ++- lib/network/modules/CanvasRenderer.js | 5 +++ test/networkTest.html | 63 +++++++++++++-------------- 5 files changed, 50 insertions(+), 34 deletions(-) diff --git a/HISTORY.md b/HISTORY.md index 7aef9f36..53f0fe68 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -9,6 +9,7 @@ http://visjs.org - Added German (de) locale. Thanks @Tooa. - Fixed critical camera zoom bug #1273. - Fixed unselectAll method. #1256 +- Fixed bug that broke the network if drawn in a hidden div #1254 ### Timeline diff --git a/dist/vis.js b/dist/vis.js index ac903761..50d54588 100644 --- a/dist/vis.js +++ b/dist/vis.js @@ -35946,6 +35946,11 @@ return /******/ (function(modules) { // webpackBootstrap var h = this.canvas.frame.canvas.clientHeight; ctx.clearRect(0, 0, w, h); + // if the div is hidden, we stop the redraw here for performance. + if (this.canvas.frame.clientWidth === 0) { + return; + } + // set scaling and translation ctx.save(); ctx.translate(this.body.view.translation.x, this.body.view.translation.y); @@ -36267,7 +36272,8 @@ return /******/ (function(modules) { // webpackBootstrap }, { key: '_setCameraState', value: function _setCameraState() { - if (this.cameraState.scale !== undefined) { + if (this.cameraState.scale !== undefined && this.frame.canvas.clientWidth !== 0 && this.frame.canvas.clientHeight !== 0 && this.pixelRatio !== 0 && this.cameraState.previousWidth > 0) { + this.body.view.scale = this.cameraState.scale * (this.frame.canvas.width / this.pixelRatio / this.cameraState.previousWidth); // this comes from the view module. diff --git a/lib/network/modules/Canvas.js b/lib/network/modules/Canvas.js index 55acb2df..f13de18a 100644 --- a/lib/network/modules/Canvas.js +++ b/lib/network/modules/Canvas.js @@ -98,7 +98,12 @@ class Canvas { * @private */ _setCameraState() { - if (this.cameraState.scale !== undefined) { + if (this.cameraState.scale !== undefined && + this.frame.canvas.clientWidth !== 0 && + this.frame.canvas.clientHeight !== 0 && + this.pixelRatio !== 0 && + this.cameraState.previousWidth > 0) { + this.body.view.scale = this.cameraState.scale * ((this.frame.canvas.width / this.pixelRatio) / this.cameraState.previousWidth); // this comes from the view module. diff --git a/lib/network/modules/CanvasRenderer.js b/lib/network/modules/CanvasRenderer.js index 9ddbb6a1..b6ec0b86 100644 --- a/lib/network/modules/CanvasRenderer.js +++ b/lib/network/modules/CanvasRenderer.js @@ -160,6 +160,11 @@ class CanvasRenderer { let h = this.canvas.frame.canvas.clientHeight; ctx.clearRect(0, 0, w, h); + // if the div is hidden, we stop the redraw here for performance. + if (this.canvas.frame.clientWidth === 0) { + return; + } + // set scaling and translation ctx.save(); ctx.translate(this.body.view.translation.x, this.body.view.translation.y); diff --git a/test/networkTest.html b/test/networkTest.html index a6627699..9d9d6b67 100644 --- a/test/networkTest.html +++ b/test/networkTest.html @@ -15,11 +15,11 @@ } - - - - - + + + + + @@ -81,7 +80,7 @@

Popup Example

-