From f1f6989f8e8e5b552541d88e2ddab8b3c9c9fe92 Mon Sep 17 00:00:00 2001 From: Alex de Mulder Date: Tue, 2 Jun 2015 11:00:55 +0200 Subject: [PATCH] make sure an stabilized event is always fired atleast once. --- dist/vis.js | 5324 +++++++++++++------------- lib/network/modules/PhysicsEngine.js | 4 +- 2 files changed, 2666 insertions(+), 2662 deletions(-) diff --git a/dist/vis.js b/dist/vis.js index b15a5fd3..562b23ca 100644 --- a/dist/vis.js +++ b/dist/vis.js @@ -5,7 +5,7 @@ * A dynamic, browser-based visualization library. * * @version 4.1.1-SNAPSHOT - * @date 2015-06-01 + * @date 2015-06-02 * * @license * Copyright (C) 2011-2014 Almende B.V, http://almende.com @@ -85,59 +85,59 @@ return /******/ (function(modules) { // webpackBootstrap 'use strict'; exports.util = __webpack_require__(3); - exports.DOMutil = __webpack_require__(11); + exports.DOMutil = __webpack_require__(8); // data - exports.DataSet = __webpack_require__(12); - exports.DataView = __webpack_require__(14); - exports.Queue = __webpack_require__(13); + exports.DataSet = __webpack_require__(9); + exports.DataView = __webpack_require__(11); + exports.Queue = __webpack_require__(10); // Graph3d - exports.Graph3d = __webpack_require__(15); + exports.Graph3d = __webpack_require__(12); exports.graph3d = { - Camera: __webpack_require__(19), - Filter: __webpack_require__(20), - Point2d: __webpack_require__(16), - Point3d: __webpack_require__(18), - Slider: __webpack_require__(21), - StepNumber: __webpack_require__(22) + Camera: __webpack_require__(16), + Filter: __webpack_require__(17), + Point2d: __webpack_require__(13), + Point3d: __webpack_require__(15), + Slider: __webpack_require__(18), + StepNumber: __webpack_require__(19) }; // Timeline - exports.Timeline = __webpack_require__(23); - exports.Graph2d = __webpack_require__(52); + exports.Timeline = __webpack_require__(20); + exports.Graph2d = __webpack_require__(50); exports.timeline = { - DateUtil: __webpack_require__(33), - DataStep: __webpack_require__(55), - Range: __webpack_require__(31), - stack: __webpack_require__(37), - TimeStep: __webpack_require__(40), + DateUtil: __webpack_require__(30), + DataStep: __webpack_require__(53), + Range: __webpack_require__(28), + stack: __webpack_require__(34), + TimeStep: __webpack_require__(37), components: { items: { - Item: __webpack_require__(39), - BackgroundItem: __webpack_require__(44), - BoxItem: __webpack_require__(42), - PointItem: __webpack_require__(43), - RangeItem: __webpack_require__(38) + Item: __webpack_require__(36), + BackgroundItem: __webpack_require__(41), + BoxItem: __webpack_require__(39), + PointItem: __webpack_require__(40), + RangeItem: __webpack_require__(35) }, - Component: __webpack_require__(25), - CurrentTime: __webpack_require__(24), - CustomTime: __webpack_require__(48), - DataAxis: __webpack_require__(54), - GraphGroup: __webpack_require__(56), - Group: __webpack_require__(36), - BackgroundGroup: __webpack_require__(41), - ItemSet: __webpack_require__(35), - Legend: __webpack_require__(60), - LineGraph: __webpack_require__(53), - TimeAxis: __webpack_require__(45) + Component: __webpack_require__(22), + CurrentTime: __webpack_require__(21), + CustomTime: __webpack_require__(45), + DataAxis: __webpack_require__(52), + GraphGroup: __webpack_require__(54), + Group: __webpack_require__(33), + BackgroundGroup: __webpack_require__(38), + ItemSet: __webpack_require__(32), + Legend: __webpack_require__(58), + LineGraph: __webpack_require__(51), + TimeAxis: __webpack_require__(42) } }; // Network - exports.Network = __webpack_require__(5); + exports.Network = __webpack_require__(60); exports.network = { Images: __webpack_require__(112), dotparser: __webpack_require__(110), @@ -157,9 +157,9 @@ return /******/ (function(modules) { // webpackBootstrap }; // bundled external libraries - exports.moment = __webpack_require__(7); - exports.hammer = __webpack_require__(27); // TODO: deprecate exports.hammer some day - exports.Hammer = __webpack_require__(27); + exports.moment = __webpack_require__(4); + exports.hammer = __webpack_require__(24); // TODO: deprecate exports.hammer some day + exports.Hammer = __webpack_require__(24); /***/ }, /* 1 */ @@ -190,669 +190,612 @@ return /******/ (function(modules) { // webpackBootstrap function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } - var _ColorPicker = __webpack_require__(49); + var _componentsPhysicsBarnesHutSolver = __webpack_require__(89); - var _ColorPicker2 = _interopRequireDefault(_ColorPicker); + var _componentsPhysicsBarnesHutSolver2 = _interopRequireDefault(_componentsPhysicsBarnesHutSolver); + + var _componentsPhysicsRepulsionSolver = __webpack_require__(90); + + var _componentsPhysicsRepulsionSolver2 = _interopRequireDefault(_componentsPhysicsRepulsionSolver); + + var _componentsPhysicsHierarchicalRepulsionSolver = __webpack_require__(91); + + var _componentsPhysicsHierarchicalRepulsionSolver2 = _interopRequireDefault(_componentsPhysicsHierarchicalRepulsionSolver); + + var _componentsPhysicsSpringSolver = __webpack_require__(92); + + var _componentsPhysicsSpringSolver2 = _interopRequireDefault(_componentsPhysicsSpringSolver); + + var _componentsPhysicsHierarchicalSpringSolver = __webpack_require__(93); + + var _componentsPhysicsHierarchicalSpringSolver2 = _interopRequireDefault(_componentsPhysicsHierarchicalSpringSolver); + + var _componentsPhysicsCentralGravitySolver = __webpack_require__(94); + + var _componentsPhysicsCentralGravitySolver2 = _interopRequireDefault(_componentsPhysicsCentralGravitySolver); + + var _componentsPhysicsFA2BasedRepulsionSolver = __webpack_require__(95); + + var _componentsPhysicsFA2BasedRepulsionSolver2 = _interopRequireDefault(_componentsPhysicsFA2BasedRepulsionSolver); + + var _componentsPhysicsFA2BasedCentralGravitySolver = __webpack_require__(96); + + var _componentsPhysicsFA2BasedCentralGravitySolver2 = _interopRequireDefault(_componentsPhysicsFA2BasedCentralGravitySolver); var util = __webpack_require__(3); - /** - * 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 - * Number options should be written as array: [default value, min value, max value, stepsize] - * Colors should be written as array: ['color', '#ffffff'] - * Strings with should be written as array: [option1, option2, option3, ..] - * - * The options are matched with their counterparts in each of the modules and the values used in the configuration are - * - * @param parentModule | the location where parentModule.setOptions() can be called - * @param defaultContainer | the default container of the module - * @param configureOptions | the fully configured and predefined options set found in allOptions.js - * @param pixelRatio | canvas pixel ratio - */ + var PhysicsEngine = (function () { + function PhysicsEngine(body) { + _classCallCheck(this, PhysicsEngine); - var Configurator = (function () { - function Configurator(parentModule, defaultContainer, configureOptions) { - var pixelRatio = arguments[3] === undefined ? 1 : arguments[3]; + this.body = body; + this.physicsBody = { physicsNodeIndices: [], physicsEdgeIndices: [], forces: {}, velocities: {} }; - _classCallCheck(this, Configurator); + this.physicsEnabled = true; + this.simulationInterval = 1000 / 60; + this.requiresTimeout = true; + this.previousStates = {}; + this.freezeCache = {}; + this.renderTimer = undefined; + this.initialStabilizationEmitted = false; - this.parent = parentModule; - this.changedOptions = []; - this.container = defaultContainer; - this.allowCreation = false; + this.stabilized = false; + this.startedStabilization = false; + this.stabilizationIterations = 0; + this.ready = false; // will be set to true if the stabilize + // default options this.options = {}; this.defaultOptions = { - enabled: false, - filter: true, - container: undefined, - showButton: true + barnesHut: { + theta: 0.5, + gravitationalConstant: -2000, + centralGravity: 0.3, + springLength: 95, + springConstant: 0.04, + damping: 0.09, + avoidOverlap: 0 + }, + forceAtlas2Based: { + theta: 0.5, + gravitationalConstant: -50, + centralGravity: 0.01, + springConstant: 0.08, + springLength: 100, + damping: 0.4, + avoidOverlap: 0 + }, + repulsion: { + centralGravity: 0.2, + springLength: 200, + springConstant: 0.05, + nodeDistance: 100, + damping: 0.09, + avoidOverlap: 0 + }, + hierarchicalRepulsion: { + centralGravity: 0, + springLength: 100, + springConstant: 0.01, + nodeDistance: 120, + damping: 0.09 + }, + maxVelocity: 50, + minVelocity: 0.1, // px/s + solver: 'barnesHut', + stabilization: { + enabled: true, + iterations: 1000, // maximum number of iteration to stabilize + updateInterval: 50, + onlyDynamicEdges: false, + fit: true + }, + timestep: 0.5 }; util.extend(this.options, this.defaultOptions); - this.configureOptions = configureOptions; - this.moduleOptions = {}; - this.domElements = []; - this.colorPicker = new _ColorPicker2['default'](pixelRatio); - this.wrapper = undefined; + this.bindEventListeners(); } - _createClass(Configurator, [{ - key: 'setOptions', + _createClass(PhysicsEngine, [{ + key: 'bindEventListeners', + value: function bindEventListeners() { + var _this = this; - /** - * 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) { - var enabled = true; - if (typeof options === 'string') { - this.options.filter = options; - } else if (options instanceof Array) { - this.options.filter = options.join(); - } else if (typeof options === 'object') { - if (options.container !== undefined) { - this.options.container = options.container; - } - if (options.filter !== undefined) { - this.options.filter = options.filter; - } - if (options.showButton !== undefined) { - this.options.showButton = options.showButton; - } - if (options.enabled !== undefined) { - enabled = options.enabled; - } - } else if (typeof options === 'boolean') { - this.options.filter = true; - enabled = options; - } else if (typeof options === 'function') { - this.options.filter = options; - enabled = true; + this.body.emitter.on('initPhysics', function () { + _this.initPhysics(); + }); + this.body.emitter.on('resetPhysics', function () { + _this.stopSimulation();_this.ready = false; + }); + this.body.emitter.on('disablePhysics', function () { + _this.physicsEnabled = false;_this.stopSimulation(); + }); + this.body.emitter.on('restorePhysics', function () { + _this.setOptions(_this.options); + if (_this.ready === true) { + _this.startSimulation(); } - if (this.options.filter === false) { - enabled = false; + }); + this.body.emitter.on('startSimulation', function () { + if (_this.ready === true) { + _this.startSimulation(); } - - this.options.enabled = enabled; - } - this._clean(); + }); + this.body.emitter.on('stopSimulation', function () { + _this.stopSimulation(); + }); + this.body.emitter.on('destroy', function () { + _this.stopSimulation(false); + _this.body.emitter.off(); + }); } }, { - key: 'setModuleOptions', - value: function setModuleOptions(moduleOptions) { - this.moduleOptions = moduleOptions; - if (this.options.enabled === true) { - this._clean(); - if (this.options.container !== undefined) { - this.container = this.options.container; + key: 'setOptions', + value: function setOptions(options) { + if (options !== undefined) { + if (options === false) { + this.physicsEnabled = false; + this.stopSimulation(); + } else { + this.physicsEnabled = true; + util.selectiveNotDeepExtend(['stabilization'], this.options, options); + util.mergeOptions(this.options, options, 'stabilization'); } - this._create(); } + this.init(); } }, { - key: '_create', - - /** - * Create all DOM elements - * @private - */ - value: function _create() { - var _this = this; - - this._clean(); - this.changedOptions = []; - - var filter = this.options.filter; - var counter = 0; - var show = false; - for (var option in this.configureOptions) { - if (this.configureOptions.hasOwnProperty(option)) { - this.allowCreation = false; - show = false; - if (typeof filter === 'function') { - show = filter(option, []); - show = show || this._handleObject(this.configureOptions[option], [option], true); - } else if (filter === true || filter.indexOf(option) !== -1) { - show = true; - } - - if (show !== false) { - this.allowCreation = true; - - // linebreak between categories - if (counter > 0) { - this._makeItem([]); - } - // a header for the category - this._makeHeader(option); - - // get the suboptions - this._handleObject(this.configureOptions[option], [option]); - } - counter++; - } - } - - if (this.options.showButton === true) { - (function () { - var generateButton = document.createElement('div'); - generateButton.className = 'vis-network-configuration button'; - generateButton.innerHTML = 'generate options'; - generateButton.onclick = function () { - _this._printOptions(); - }; - generateButton.onmouseover = function () { - generateButton.className = 'vis-network-configuration button hover'; - }; - generateButton.onmouseout = function () { - generateButton.className = 'vis-network-configuration button'; - }; - - _this.optionsContainer = document.createElement('div'); - _this.optionsContainer.className = 'vis-network-configuration vis-option-container'; - - _this.domElements.push(_this.optionsContainer); - _this.domElements.push(generateButton); - })(); + key: 'init', + value: function init() { + var options; + if (this.options.solver === 'forceAtlas2Based') { + options = this.options.forceAtlas2Based; + this.nodesSolver = new _componentsPhysicsFA2BasedRepulsionSolver2['default'](this.body, this.physicsBody, options); + this.edgesSolver = new _componentsPhysicsSpringSolver2['default'](this.body, this.physicsBody, options); + this.gravitySolver = new _componentsPhysicsFA2BasedCentralGravitySolver2['default'](this.body, this.physicsBody, options); + } else if (this.options.solver === 'repulsion') { + options = this.options.repulsion; + this.nodesSolver = new _componentsPhysicsRepulsionSolver2['default'](this.body, this.physicsBody, options); + this.edgesSolver = new _componentsPhysicsSpringSolver2['default'](this.body, this.physicsBody, options); + this.gravitySolver = new _componentsPhysicsCentralGravitySolver2['default'](this.body, this.physicsBody, options); + } else if (this.options.solver === 'hierarchicalRepulsion') { + options = this.options.hierarchicalRepulsion; + this.nodesSolver = new _componentsPhysicsHierarchicalRepulsionSolver2['default'](this.body, this.physicsBody, options); + this.edgesSolver = new _componentsPhysicsHierarchicalSpringSolver2['default'](this.body, this.physicsBody, options); + this.gravitySolver = new _componentsPhysicsCentralGravitySolver2['default'](this.body, this.physicsBody, options); + } else { + // barnesHut + options = this.options.barnesHut; + this.nodesSolver = new _componentsPhysicsBarnesHutSolver2['default'](this.body, this.physicsBody, options); + this.edgesSolver = new _componentsPhysicsSpringSolver2['default'](this.body, this.physicsBody, options); + this.gravitySolver = new _componentsPhysicsCentralGravitySolver2['default'](this.body, this.physicsBody, options); } - this._push(); - this.colorPicker.insertTo(this.container); + this.modelOptions = options; } }, { - key: '_push', - - /** - * draw all DOM elements on the screen - * @private - */ - value: function _push() { - this.wrapper = document.createElement('div'); - this.wrapper.className = 'vis-network-configuration-wrapper'; - this.container.appendChild(this.wrapper); - for (var i = 0; i < this.domElements.length; i++) { - this.wrapper.appendChild(this.domElements[i]); + key: 'initPhysics', + value: function initPhysics() { + if (this.physicsEnabled === true) { + if (this.options.stabilization.enabled === true) { + this.stabilize(); + } else { + this.stabilized = false; + this.ready = true; + this.body.emitter.emit('fit', {}, true); + this.startSimulation(); + } + } else { + this.ready = true; + this.body.emitter.emit('fit'); } } }, { - key: '_clean', + key: 'startSimulation', /** - * delete all DOM elements - * @private + * Start the simulation */ - value: function _clean() { - for (var i = 0; i < this.domElements.length; i++) { - this.wrapper.removeChild(this.domElements[i]); - } + value: function startSimulation() { + if (this.physicsEnabled === true) { + this.stabilized = false; - if (this.wrapper !== undefined) { - this.container.removeChild(this.wrapper); - this.wrapper = undefined; + // this sets the width of all nodes initially which could be required for the avoidOverlap + this.body.emitter.emit('_resizeNodes'); + if (this.viewFunction === undefined) { + this.viewFunction = this.simulationStep.bind(this); + this.body.emitter.on('initRedraw', this.viewFunction); + this.body.emitter.emit('_startRendering'); + } + } else { + this.body.emitter.emit('_redraw'); } - this.domElements = []; } }, { - key: '_getValue', + key: 'stopSimulation', /** - * get the value from the actualOptions if it exists - * @param {array} path | where to look for the actual option - * @returns {*} - * @private + * Stop the simulation, force stabilization. */ - value: function _getValue(path) { - var base = this.moduleOptions; - for (var i = 0; i < path.length; i++) { - if (base[path[i]] !== undefined) { - base = base[path[i]]; - } else { - base = undefined; - break; + value: function stopSimulation() { + var emit = arguments[0] === undefined ? true : arguments[0]; + + this.stabilized = true; + if (emit === true) { + this._emitStabilized(); + } + if (this.viewFunction !== undefined) { + this.body.emitter.off('initRedraw', this.viewFunction); + this.viewFunction = undefined; + if (emit === true) { + this.body.emitter.emit('_stopRendering'); } } - return base; } }, { - key: '_makeItem', + key: 'simulationStep', /** - * all option elements are wrapped in an item - * @param path - * @param domElements - * @private + * The viewFunction inserts this step into each renderloop. It calls the physics tick and handles the cleanup at stabilized. + * */ - value: function _makeItem(path) { - var _this2 = this; + value: function simulationStep() { + // check if the physics have settled + var startTime = Date.now(); + this.physicsTick(); + var physicsTime = Date.now() - startTime; - for (var _len = arguments.length, domElements = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { - domElements[_key - 1] = arguments[_key]; + // run double speed if it is a little graph + if ((physicsTime < 0.4 * this.simulationInterval || this.runDoubleSpeed === true) && this.stabilized === false) { + this.physicsTick(); + + // this makes sure there is no jitter. The decision is taken once to run it at double speed. + this.runDoubleSpeed = true; } - if (this.allowCreation === true) { - (function () { - var item = document.createElement('div'); - item.className = 'vis-network-configuration item s' + path.length; - domElements.forEach(function (element) { - item.appendChild(element); - }); - _this2.domElements.push(item); - })(); + if (this.stabilized === true) { + if (this.stabilizationIterations > 1) { + // trigger the 'stabilized' event. + // The event is triggered on the next tick, to prevent the case that + // it is fired while initializing the Network, in which case you would not + // be able to catch it + this.startedStabilization = false; + //this._emitStabilized(); + } + this.stopSimulation(); } } }, { - key: '_makeHeader', + key: '_emitStabilized', + value: function _emitStabilized() { + var _this2 = this; - /** - * header for major subjects - * @param name - * @private - */ - value: function _makeHeader(name) { - var div = document.createElement('div'); - div.className = 'vis-network-configuration header'; - div.innerHTML = name; - this._makeItem([], div); + if (this.stabilizationIterations > 1 || this.initialStabilizationEmitted === false) { + this.initialStabilizationEmitted = true; + setTimeout(function () { + _this2.body.emitter.emit('stabilized', { iterations: _this2.stabilizationIterations }); + _this2.stabilizationIterations = 0; + }, 0); + } } }, { - key: '_makeLabel', + key: 'physicsTick', /** - * make a label, if it is an object label, it gets different styling. - * @param name - * @param path - * @param objectLabel - * @returns {HTMLElement} + * A single simulation step (or 'tick') in the physics simulation + * * @private */ - value: function _makeLabel(name, path) { - var objectLabel = arguments[2] === undefined ? false : arguments[2]; + value: function physicsTick() { + if (this.stabilized === false) { + this.calculateForces(); + this.stabilized = this.moveNodes(); - var div = document.createElement('div'); - div.className = 'vis-network-configuration label s' + path.length; - if (objectLabel === true) { - div.innerHTML = '' + name + ':'; - } else { - div.innerHTML = name + ':'; + // determine if the network has stabilzied + if (this.stabilized === true) { + this.revert(); + } else { + // this is here to ensure that there is no start event when the network is already stable. + if (this.startedStabilization === false) { + this.body.emitter.emit('startStabilizing'); + this.startedStabilization = true; + } + } + + this.stabilizationIterations++; } - return div; } }, { - key: '_makeDropdown', + key: 'updatePhysicsData', /** - * make a dropdown list for multiple possible string optoins - * @param arr - * @param value - * @param path + * 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 */ - value: function _makeDropdown(arr, value, path) { - var select = document.createElement('select'); - select.className = 'vis-network-configuration select'; - var selectedValue = 0; - if (value !== undefined) { - if (arr.indexOf(value) !== -1) { - selectedValue = arr.indexOf(value); + value: function updatePhysicsData() { + this.physicsBody.forces = {}; + this.physicsBody.physicsNodeIndices = []; + this.physicsBody.physicsEdgeIndices = []; + var nodes = this.body.nodes; + var edges = this.body.edges; + + // get node indices for physics + for (var nodeId in nodes) { + if (nodes.hasOwnProperty(nodeId)) { + if (nodes[nodeId].options.physics === true) { + this.physicsBody.physicsNodeIndices.push(nodeId); + } } } - for (var i = 0; i < arr.length; i++) { - var option = document.createElement('option'); - option.value = arr[i]; - if (i === selectedValue) { - option.selected = 'selected'; + // get edge indices for physics + for (var edgeId in edges) { + if (edges.hasOwnProperty(edgeId)) { + if (edges[edgeId].options.physics === true) { + this.physicsBody.physicsEdgeIndices.push(edgeId); + } } - option.innerHTML = arr[i]; - select.appendChild(option); } - var me = this; - select.onchange = function () { - me._update(this.value, path); - }; - - var label = this._makeLabel(path[path.length - 1], path); - this._makeItem(path, label, select); - } - }, { - key: '_makeRange', - - /** - * make a range object for numeric options - * @param arr - * @param value - * @param path - * @private - */ - value: function _makeRange(arr, value, path) { - var defaultValue = arr[0]; - var min = arr[1]; - var max = arr[2]; - var step = arr[3]; - var range = document.createElement('input'); - range.type = 'range'; - range.className = 'vis-network-configuration range'; - range.min = min; - range.max = max; - range.step = step; + // get the velocity and the forces vector + for (var i = 0; i < this.physicsBody.physicsNodeIndices.length; i++) { + var nodeId = this.physicsBody.physicsNodeIndices[i]; + this.physicsBody.forces[nodeId] = { x: 0, y: 0 }; - if (value !== undefined) { - if (value < 0 && value * 2 < min) { - range.min = value * 2; - } else if (value * 0.1 < min) { - range.min = value / 10; - } - if (value * 2 > max && max !== 1) { - range.max = value * 2; + // forces can be reset because they are recalculated. Velocities have to persist. + if (this.physicsBody.velocities[nodeId] === undefined) { + this.physicsBody.velocities[nodeId] = { x: 0, y: 0 }; } - range.value = value; - } else { - range.value = defaultValue; } - var input = document.createElement('input'); - input.className = 'vis-network-configuration rangeinput'; - input.value = range.value; - - var me = this; - range.onchange = function () { - input.value = this.value;me._update(Number(this.value), path); - }; - range.oninput = function () { - input.value = this.value; - }; - - var label = this._makeLabel(path[path.length - 1], path); - this._makeItem(path, label, range, input); + // clean deleted nodes from the velocity vector + for (var nodeId in this.physicsBody.velocities) { + if (nodes[nodeId] === undefined) { + delete this.physicsBody.velocities[nodeId]; + } + } } }, { - key: '_makeCheckbox', + key: 'revert', /** - * make a checkbox for boolean options. - * @param defaultValue - * @param value - * @param path - * @private + * Revert the simulation one step. This is done so after stabilization, every new start of the simulation will also say stabilized. */ - value: function _makeCheckbox(defaultValue, value, path) { - var checkbox = document.createElement('input'); - checkbox.type = 'checkbox'; - checkbox.className = 'vis-network-configuration checkbox'; - checkbox.checked = defaultValue; - if (value !== undefined) { - checkbox.checked = value; - if (value !== defaultValue) { - if (typeof defaultValue === 'object') { - if (value !== defaultValue.enabled) { - this.changedOptions.push({ path: path, value: value }); - } - } else { - this.changedOptions.push({ path: path, value: value }); + value: function revert() { + var nodeIds = Object.keys(this.previousStates); + var nodes = this.body.nodes; + var velocities = this.physicsBody.velocities; + + for (var i = 0; i < nodeIds.length; i++) { + var nodeId = nodeIds[i]; + if (nodes[nodeId] !== undefined) { + if (nodes[nodeId].options.physics === true) { + velocities[nodeId].x = this.previousStates[nodeId].vx; + velocities[nodeId].y = this.previousStates[nodeId].vy; + nodes[nodeId].x = this.previousStates[nodeId].x; + nodes[nodeId].y = this.previousStates[nodeId].y; } + } else { + delete this.previousStates[nodeId]; } } - - var me = this; - checkbox.onchange = function () { - me._update(this.checked, path); - }; - - var label = this._makeLabel(path[path.length - 1], path); - this._makeItem(path, label, checkbox); } }, { - key: '_makeTextInput', + key: 'moveNodes', /** - * make a text input field for string options. - * @param defaultValue - * @param value - * @param path - * @private + * move the nodes one timestap and check if they are stabilized + * @returns {boolean} */ - value: function _makeTextInput(defaultValue, value, path) { - var checkbox = document.createElement('input'); - checkbox.type = 'text'; - checkbox.className = 'vis-network-configuration text'; - checkbox.value = value; - if (value !== defaultValue) { - this.changedOptions.push({ path: path, value: value }); - } + value: function moveNodes() { + var nodesPresent = false; + var nodeIndices = this.physicsBody.physicsNodeIndices; + var maxVelocity = this.options.maxVelocity ? this.options.maxVelocity : 1000000000; + var stabilized = true; + var vminCorrected = this.options.minVelocity / Math.max(this.body.view.scale, 0.05); - var me = this; - checkbox.onchange = function () { - me._update(this.value, path); - }; + for (var i = 0; i < nodeIndices.length; i++) { + var nodeId = nodeIndices[i]; + var nodeVelocity = this._performStep(nodeId, maxVelocity); + // stabilized is true if stabilized is true and velocity is smaller than vmin --> all nodes must be stabilized + stabilized = nodeVelocity < vminCorrected && stabilized === true; + nodesPresent = true; + } - var label = this._makeLabel(path[path.length - 1], path); - this._makeItem(path, label, checkbox); + if (nodesPresent === true) { + if (vminCorrected > 0.5 * this.options.maxVelocity) { + return false; + } else { + return stabilized; + } + } + return true; } }, { - key: '_makeColorField', + key: '_performStep', /** - * make a color field with a color picker for color fields - * @param arr - * @param value - * @param path + * Perform the actual step + * + * @param nodeId + * @param maxVelocity + * @returns {number} * @private */ - value: function _makeColorField(arr, value, path) { - var _this3 = this; + value: function _performStep(nodeId, maxVelocity) { + var node = this.body.nodes[nodeId]; + var timestep = this.options.timestep; + var forces = this.physicsBody.forces; + var velocities = this.physicsBody.velocities; - var defaultColor = arr[1]; - var div = document.createElement('div'); - value = value === undefined ? defaultColor : value; + // store the state so we can revert + this.previousStates[nodeId] = { x: node.x, y: node.y, vx: velocities[nodeId].x, vy: velocities[nodeId].y }; - if (value !== 'none') { - div.className = 'vis-network-configuration colorBlock'; - div.style.backgroundColor = value; + if (node.options.fixed.x === false) { + var dx = this.modelOptions.damping * velocities[nodeId].x; // damping force + var ax = (forces[nodeId].x - dx) / node.options.mass; // acceleration + velocities[nodeId].x += ax * timestep; // velocity + 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 { - div.className = 'vis-network-configuration colorBlock none'; + forces[nodeId].x = 0; + velocities[nodeId].x = 0; } - value = value === undefined ? defaultColor : value; - div.onclick = function () { - _this3._showColorPicker(value, div, path); - }; + if (node.options.fixed.y === false) { + var dy = this.modelOptions.damping * velocities[nodeId].y; // damping force + var ay = (forces[nodeId].y - dy) / node.options.mass; // acceleration + velocities[nodeId].y += ay * timestep; // velocity + 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; + } - var label = this._makeLabel(path[path.length - 1], path); - this._makeItem(path, label, div); + var totalVelocity = Math.sqrt(Math.pow(velocities[nodeId].x, 2) + Math.pow(velocities[nodeId].y, 2)); + return totalVelocity; } }, { - key: '_showColorPicker', + key: 'calculateForces', /** - * used by the color buttons to call the color picker. - * @param event - * @param value - * @param div - * @param path - * @private + * calculate the forces for one physics iteration. */ - value: function _showColorPicker(value, div, path) { - var _this4 = this; - - var rect = div.getBoundingClientRect(); - var bodyRect = document.body.getBoundingClientRect(); - var pickerX = rect.left + rect.width + 5; - var pickerY = rect.top - bodyRect.top + rect.height * 0.5; - this.colorPicker.show(pickerX, pickerY); - this.colorPicker.setColor(value); - this.colorPicker.setCallback(function (color) { - var colorString = 'rgba(' + color.r + ',' + color.g + ',' + color.b + ',' + color.a + ')'; - div.style.backgroundColor = colorString; - _this4._update(colorString, path); - }); + value: function calculateForces() { + this.gravitySolver.solve(); + this.nodesSolver.solve(); + this.edgesSolver.solve(); } }, { - key: '_handleObject', + key: '_freezeNodes', /** - * parse an object and draw the correct items - * @param obj - * @param path + * When initializing and stabilizing, we can freeze nodes with a predefined position. This greatly speeds up stabilization + * because only the supportnodes for the smoothCurves have to settle. + * * @private */ - value: function _handleObject(obj) { - var path = arguments[1] === undefined ? [] : arguments[1]; - var checkOnly = arguments[2] === undefined ? false : arguments[2]; - - var show = false; - var filter = this.options.filter; - var visibleInSet = false; - for (var subObj in obj) { - if (obj.hasOwnProperty(subObj)) { - show = true; - var item = obj[subObj]; - var newPath = util.copyAndExtendArray(path, subObj); - if (typeof filter === 'function') { - show = filter(subObj, path); - - // if needed we must go deeper into the object. - if (show === false) { - if (!(item instanceof Array) && typeof item !== 'string' && typeof item !== 'boolean' && item instanceof Object) { - this.allowCreation = false; - show = this._handleObject(item, newPath, true); - this.allowCreation = checkOnly === false; - } - } - } - - if (show !== false) { - visibleInSet = true; - var value = this._getValue(newPath); - - if (item instanceof Array) { - this._handleArray(item, value, newPath); - } else if (typeof item === 'string') { - this._makeTextInput(item, value, newPath); - } else if (typeof item === 'boolean') { - this._makeCheckbox(item, value, newPath); - } else if (item instanceof Object) { - // collapse the physics options that are not enabled - var draw = true; - if (path.indexOf('physics') !== -1) { - if (this.moduleOptions.physics.solver !== subObj) { - draw = false; - } - } - - if (draw === true) { - // initially collapse options with an disabled enabled option. - if (item.enabled !== undefined) { - var enabledPath = util.copyAndExtendArray(newPath, 'enabled'); - var enabledValue = this._getValue(enabledPath); - if (enabledValue === true) { - var label = this._makeLabel(subObj, newPath, true); - this._makeItem(newPath, label); - visibleInSet = this._handleObject(item, newPath) || visibleInSet; - } else { - this._makeCheckbox(item, enabledValue, newPath); - } - } else { - var label = this._makeLabel(subObj, newPath, true); - this._makeItem(newPath, label); - visibleInSet = this._handleObject(item, newPath) || visibleInSet; - } - } - } else { - console.error('dont know how to handle', item, subObj, newPath); - } + value: function _freezeNodes() { + var nodes = this.body.nodes; + for (var id in nodes) { + if (nodes.hasOwnProperty(id)) { + if (nodes[id].x && nodes[id].y) { + this.freezeCache[id] = { x: nodes[id].options.fixed.x, y: nodes[id].options.fixed.y }; + nodes[id].options.fixed.x = true; + nodes[id].options.fixed.y = true; } } } - return visibleInSet; } }, { - key: '_handleArray', + key: '_restoreFrozenNodes', /** - * handle the array type of option - * @param optionName - * @param arr - * @param value - * @param path + * Unfreezes the nodes that have been frozen by _freezeDefinedNodes. + * * @private */ - value: function _handleArray(arr, value, path) { - if (typeof arr[0] === 'string' && arr[0] === 'color') { - this._makeColorField(arr, value, path); - if (arr[1] !== value) { - this.changedOptions.push({ path: path, value: value }); - } - } else if (typeof arr[0] === 'string') { - this._makeDropdown(arr, value, path); - if (arr[0] !== value) { - this.changedOptions.push({ path: path, value: value }); - } - } else if (typeof arr[0] === 'number') { - this._makeRange(arr, value, path); - if (arr[0] !== value) { - this.changedOptions.push({ path: path, value: Number(value) }); + value: function _restoreFrozenNodes() { + var nodes = this.body.nodes; + for (var id in nodes) { + if (nodes.hasOwnProperty(id)) { + if (this.freezeCache[id] !== undefined) { + nodes[id].options.fixed.x = this.freezeCache[id].x; + nodes[id].options.fixed.y = this.freezeCache[id].y; + } } } + this.freezeCache = {}; } }, { - key: '_update', + key: 'stabilize', /** - * called to update the network with the new settings. - * @param value - * @param path + * Find a stable position for all nodes * @private */ - value: function _update(value, path) { - var options = this._constructOptions(value, path); - this.parent.setOptions(options); - } - }, { - key: '_constructOptions', - value: function _constructOptions(value, path) { - var optionsObj = arguments[2] === undefined ? {} : arguments[2]; + value: function stabilize() { + var _this3 = this; - var pointer = optionsObj; + var iterations = arguments[0] === undefined ? this.options.stabilization.iterations : arguments[0]; - // when dropdown boxes can be string or boolean, we typecast it into correct types - value = value === 'true' ? true : value; - value = value === 'false' ? false : value; + if (typeof iterations !== 'number') { + console.log('The stabilize method needs a numeric amount of iterations. Switching to default: ', this.options.stabilization.iterations); + iterations = this.options.stabilization.iterations; + } - for (var i = 0; i < path.length; i++) { - if (path[i] !== 'global') { - if (pointer[path[i]] === undefined) { - pointer[path[i]] = {}; - } - if (i !== path.length - 1) { - pointer = pointer[path[i]]; - } else { - pointer[path[i]] = value; - } - } + // this sets the width of all nodes initially which could be required for the avoidOverlap + this.body.emitter.emit('_resizeNodes'); + + // stop the render loop + this.stopSimulation(); + + // set stabilze to false + this.stabilized = false; + + // block redraw requests + this.body.emitter.emit('_blockRedrawRequests'); + this.targetIterations = iterations; + + // start the stabilization + if (this.options.stabilization.onlyDynamicEdges === true) { + this._freezeNodes(); } - return optionsObj; + this.stabilizationIterations = 0; + + setTimeout(function () { + return _this3._stabilizationBatch(); + }, 0); } }, { - key: '_printOptions', - value: function _printOptions() { - var options = {}; - for (var i = 0; i < this.changedOptions.length; i++) { - this._constructOptions(this.changedOptions[i].value, this.changedOptions[i].path, options); + key: '_stabilizationBatch', + value: function _stabilizationBatch() { + var count = 0; + while (this.stabilized === false && count < this.options.stabilization.updateInterval && this.stabilizationIterations < this.targetIterations) { + this.physicsTick(); + this.stabilizationIterations++; + count++; } - this.optionsContainer.innerHTML = '
var options = ' + JSON.stringify(options, null, 2) + '
'; + + if (this.stabilized === false && this.stabilizationIterations < this.targetIterations) { + this.body.emitter.emit('stabilizationProgress', { iterations: this.stabilizationIterations, total: this.targetIterations }); + setTimeout(this._stabilizationBatch.bind(this), 0); + } else { + this._finalizeStabilization(); + } + } + }, { + key: '_finalizeStabilization', + value: function _finalizeStabilization() { + this.body.emitter.emit('_allowRedrawRequests'); + if (this.options.stabilization.fit === true) { + this.body.emitter.emit('fit'); + } + + if (this.options.stabilization.onlyDynamicEdges === true) { + this._restoreFrozenNodes(); + } + + this.body.emitter.emit('stabilizationIterationsDone'); + this.body.emitter.emit('_requestRedraw'); + + if (this.stabilized === true) { + this._emitStabilized(); + } else { + this.startSimulation(); + } + + this.ready = true; } }]); - return Configurator; + return PhysicsEngine; })(); - exports['default'] = Configurator; + exports['default'] = PhysicsEngine; module.exports = exports['default']; /***/ }, @@ -866,8 +809,8 @@ return /******/ (function(modules) { // webpackBootstrap 'use strict'; - var moment = __webpack_require__(7); - var uuid = __webpack_require__(10); + var moment = __webpack_require__(4); + var uuid = __webpack_require__(7); /** * Test whether given object is a number @@ -2203,1373 +2146,16 @@ return /******/ (function(modules) { // webpackBootstrap /***/ }, /* 4 */ -/***/ 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; }; })(); - - 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 _componentsPhysicsBarnesHutSolver = __webpack_require__(90); - - var _componentsPhysicsBarnesHutSolver2 = _interopRequireDefault(_componentsPhysicsBarnesHutSolver); - - var _componentsPhysicsRepulsionSolver = __webpack_require__(91); - - var _componentsPhysicsRepulsionSolver2 = _interopRequireDefault(_componentsPhysicsRepulsionSolver); - - var _componentsPhysicsHierarchicalRepulsionSolver = __webpack_require__(92); - - var _componentsPhysicsHierarchicalRepulsionSolver2 = _interopRequireDefault(_componentsPhysicsHierarchicalRepulsionSolver); - - var _componentsPhysicsSpringSolver = __webpack_require__(93); - - var _componentsPhysicsSpringSolver2 = _interopRequireDefault(_componentsPhysicsSpringSolver); - - var _componentsPhysicsHierarchicalSpringSolver = __webpack_require__(6); - - var _componentsPhysicsHierarchicalSpringSolver2 = _interopRequireDefault(_componentsPhysicsHierarchicalSpringSolver); - - var _componentsPhysicsCentralGravitySolver = __webpack_require__(94); - - var _componentsPhysicsCentralGravitySolver2 = _interopRequireDefault(_componentsPhysicsCentralGravitySolver); - - var _componentsPhysicsFA2BasedRepulsionSolver = __webpack_require__(95); - - var _componentsPhysicsFA2BasedRepulsionSolver2 = _interopRequireDefault(_componentsPhysicsFA2BasedRepulsionSolver); - - var _componentsPhysicsFA2BasedCentralGravitySolver = __webpack_require__(96); - - var _componentsPhysicsFA2BasedCentralGravitySolver2 = _interopRequireDefault(_componentsPhysicsFA2BasedCentralGravitySolver); - - var util = __webpack_require__(3); - - var PhysicsEngine = (function () { - function PhysicsEngine(body) { - _classCallCheck(this, PhysicsEngine); - - this.body = body; - this.physicsBody = { physicsNodeIndices: [], physicsEdgeIndices: [], forces: {}, velocities: {} }; - - this.physicsEnabled = true; - this.simulationInterval = 1000 / 60; - this.requiresTimeout = true; - this.previousStates = {}; - this.freezeCache = {}; - this.renderTimer = undefined; - - this.stabilized = false; - this.startedStabilization = false; - this.stabilizationIterations = 0; - this.ready = false; // will be set to true if the stabilize - - // default options - this.options = {}; - this.defaultOptions = { - barnesHut: { - theta: 0.5, - gravitationalConstant: -2000, - centralGravity: 0.3, - springLength: 95, - springConstant: 0.04, - damping: 0.09, - avoidOverlap: 0 - }, - forceAtlas2Based: { - theta: 0.5, - gravitationalConstant: -50, - centralGravity: 0.01, - springConstant: 0.08, - springLength: 100, - damping: 0.4, - avoidOverlap: 0 - }, - repulsion: { - centralGravity: 0.2, - springLength: 200, - springConstant: 0.05, - nodeDistance: 100, - damping: 0.09, - avoidOverlap: 0 - }, - hierarchicalRepulsion: { - centralGravity: 0, - springLength: 100, - springConstant: 0.01, - nodeDistance: 120, - damping: 0.09 - }, - maxVelocity: 50, - minVelocity: 0.1, // px/s - solver: 'barnesHut', - stabilization: { - enabled: true, - iterations: 1000, // maximum number of iteration to stabilize - updateInterval: 50, - onlyDynamicEdges: false, - fit: true - }, - timestep: 0.5 - }; - util.extend(this.options, this.defaultOptions); - - this.bindEventListeners(); - } - - _createClass(PhysicsEngine, [{ - key: 'bindEventListeners', - value: function bindEventListeners() { - var _this = this; - - this.body.emitter.on('initPhysics', function () { - _this.initPhysics(); - }); - this.body.emitter.on('resetPhysics', function () { - _this.stopSimulation();_this.ready = false; - }); - this.body.emitter.on('disablePhysics', function () { - _this.physicsEnabled = false;_this.stopSimulation(); - }); - this.body.emitter.on('restorePhysics', function () { - _this.setOptions(_this.options); - if (_this.ready === true) { - _this.startSimulation(); - } - }); - this.body.emitter.on('startSimulation', function () { - if (_this.ready === true) { - _this.startSimulation(); - } - }); - this.body.emitter.on('stopSimulation', function () { - _this.stopSimulation(); - }); - this.body.emitter.on('destroy', function () { - _this.stopSimulation(false); - _this.body.emitter.off(); - }); - } - }, { - key: 'setOptions', - value: function setOptions(options) { - if (options !== undefined) { - if (options === false) { - this.physicsEnabled = false; - this.stopSimulation(); - } else { - this.physicsEnabled = true; - util.selectiveNotDeepExtend(['stabilization'], this.options, options); - util.mergeOptions(this.options, options, 'stabilization'); - } - } - this.init(); - } - }, { - key: 'init', - value: function init() { - var options; - if (this.options.solver === 'forceAtlas2Based') { - options = this.options.forceAtlas2Based; - this.nodesSolver = new _componentsPhysicsFA2BasedRepulsionSolver2['default'](this.body, this.physicsBody, options); - this.edgesSolver = new _componentsPhysicsSpringSolver2['default'](this.body, this.physicsBody, options); - this.gravitySolver = new _componentsPhysicsFA2BasedCentralGravitySolver2['default'](this.body, this.physicsBody, options); - } else if (this.options.solver === 'repulsion') { - options = this.options.repulsion; - this.nodesSolver = new _componentsPhysicsRepulsionSolver2['default'](this.body, this.physicsBody, options); - this.edgesSolver = new _componentsPhysicsSpringSolver2['default'](this.body, this.physicsBody, options); - this.gravitySolver = new _componentsPhysicsCentralGravitySolver2['default'](this.body, this.physicsBody, options); - } else if (this.options.solver === 'hierarchicalRepulsion') { - options = this.options.hierarchicalRepulsion; - this.nodesSolver = new _componentsPhysicsHierarchicalRepulsionSolver2['default'](this.body, this.physicsBody, options); - this.edgesSolver = new _componentsPhysicsHierarchicalSpringSolver2['default'](this.body, this.physicsBody, options); - this.gravitySolver = new _componentsPhysicsCentralGravitySolver2['default'](this.body, this.physicsBody, options); - } else { - // barnesHut - options = this.options.barnesHut; - this.nodesSolver = new _componentsPhysicsBarnesHutSolver2['default'](this.body, this.physicsBody, options); - this.edgesSolver = new _componentsPhysicsSpringSolver2['default'](this.body, this.physicsBody, options); - this.gravitySolver = new _componentsPhysicsCentralGravitySolver2['default'](this.body, this.physicsBody, options); - } - - this.modelOptions = options; - } - }, { - key: 'initPhysics', - value: function initPhysics() { - if (this.physicsEnabled === true) { - if (this.options.stabilization.enabled === true) { - this.stabilize(); - } else { - this.stabilized = false; - this.ready = true; - this.body.emitter.emit('fit', {}, true); - this.startSimulation(); - } - } else { - this.ready = true; - this.body.emitter.emit('fit'); - } - } - }, { - key: 'startSimulation', - - /** - * Start the simulation - */ - value: function startSimulation() { - if (this.physicsEnabled === true) { - this.stabilized = false; - - // this sets the width of all nodes initially which could be required for the avoidOverlap - this.body.emitter.emit('_resizeNodes'); - if (this.viewFunction === undefined) { - this.viewFunction = this.simulationStep.bind(this); - this.body.emitter.on('initRedraw', this.viewFunction); - this.body.emitter.emit('_startRendering'); - } - } else { - this.body.emitter.emit('_redraw'); - } - } - }, { - key: 'stopSimulation', - - /** - * Stop the simulation, force stabilization. - */ - value: function stopSimulation() { - var emit = arguments[0] === undefined ? true : arguments[0]; - - this.stabilized = true; - if (emit === true) { - this._emitStabilized(); - } - if (this.viewFunction !== undefined) { - this.body.emitter.off('initRedraw', this.viewFunction); - this.viewFunction = undefined; - if (emit === true) { - this.body.emitter.emit('_stopRendering'); - } - } - } - }, { - key: 'simulationStep', - - /** - * The viewFunction inserts this step into each renderloop. It calls the physics tick and handles the cleanup at stabilized. - * - */ - value: function simulationStep() { - // check if the physics have settled - var startTime = Date.now(); - this.physicsTick(); - var physicsTime = Date.now() - startTime; - - // run double speed if it is a little graph - if ((physicsTime < 0.4 * this.simulationInterval || this.runDoubleSpeed === true) && this.stabilized === false) { - this.physicsTick(); - - // this makes sure there is no jitter. The decision is taken once to run it at double speed. - this.runDoubleSpeed = true; - } - - if (this.stabilized === true) { - if (this.stabilizationIterations > 1) { - // trigger the 'stabilized' event. - // The event is triggered on the next tick, to prevent the case that - // it is fired while initializing the Network, in which case you would not - // be able to catch it - this.startedStabilization = false; - //this._emitStabilized(); - } - this.stopSimulation(); - } - } - }, { - key: '_emitStabilized', - value: function _emitStabilized() { - var _this2 = this; - - if (this.stabilizationIterations > 0) { - setTimeout(function () { - _this2.body.emitter.emit('stabilized', { iterations: _this2.stabilizationIterations }); - _this2.stabilizationIterations = 0; - }, 0); - } - } - }, { - key: 'physicsTick', - - /** - * A single simulation step (or 'tick') in the physics simulation - * - * @private - */ - value: function physicsTick() { - if (this.stabilized === false) { - this.calculateForces(); - this.stabilized = this.moveNodes(); - - // determine if the network has stabilzied - if (this.stabilized === true) { - this.revert(); - } else { - // this is here to ensure that there is no start event when the network is already stable. - if (this.startedStabilization === false) { - this.body.emitter.emit('startStabilizing'); - this.startedStabilization = true; - } - } - - 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 - */ - value: function updatePhysicsData() { - this.physicsBody.forces = {}; - this.physicsBody.physicsNodeIndices = []; - this.physicsBody.physicsEdgeIndices = []; - var nodes = this.body.nodes; - var edges = this.body.edges; - - // get node indices for physics - for (var nodeId in nodes) { - if (nodes.hasOwnProperty(nodeId)) { - if (nodes[nodeId].options.physics === true) { - this.physicsBody.physicsNodeIndices.push(nodeId); - } - } - } - - // get edge indices for physics - for (var edgeId in edges) { - if (edges.hasOwnProperty(edgeId)) { - if (edges[edgeId].options.physics === true) { - this.physicsBody.physicsEdgeIndices.push(edgeId); - } - } - } - - // get the velocity and the forces vector - for (var i = 0; i < this.physicsBody.physicsNodeIndices.length; i++) { - var nodeId = this.physicsBody.physicsNodeIndices[i]; - this.physicsBody.forces[nodeId] = { x: 0, y: 0 }; - - // forces can be reset because they are recalculated. Velocities have to persist. - if (this.physicsBody.velocities[nodeId] === undefined) { - this.physicsBody.velocities[nodeId] = { x: 0, y: 0 }; - } - } - - // clean deleted nodes from the velocity vector - for (var nodeId in this.physicsBody.velocities) { - if (nodes[nodeId] === undefined) { - delete this.physicsBody.velocities[nodeId]; - } - } - } - }, { - key: 'revert', - - /** - * Revert the simulation one step. This is done so after stabilization, every new start of the simulation will also say stabilized. - */ - value: function revert() { - var nodeIds = Object.keys(this.previousStates); - var nodes = this.body.nodes; - var velocities = this.physicsBody.velocities; - - for (var i = 0; i < nodeIds.length; i++) { - var nodeId = nodeIds[i]; - if (nodes[nodeId] !== undefined) { - if (nodes[nodeId].options.physics === true) { - velocities[nodeId].x = this.previousStates[nodeId].vx; - velocities[nodeId].y = this.previousStates[nodeId].vy; - nodes[nodeId].x = this.previousStates[nodeId].x; - nodes[nodeId].y = this.previousStates[nodeId].y; - } - } else { - delete this.previousStates[nodeId]; - } - } - } - }, { - key: 'moveNodes', - - /** - * move the nodes one timestap and check if they are stabilized - * @returns {boolean} - */ - value: function moveNodes() { - var nodesPresent = false; - var nodeIndices = this.physicsBody.physicsNodeIndices; - var maxVelocity = this.options.maxVelocity ? this.options.maxVelocity : 1000000000; - var stabilized = true; - var vminCorrected = this.options.minVelocity / Math.max(this.body.view.scale, 0.05); - - for (var i = 0; i < nodeIndices.length; i++) { - var nodeId = nodeIndices[i]; - var nodeVelocity = this._performStep(nodeId, maxVelocity); - // stabilized is true if stabilized is true and velocity is smaller than vmin --> all nodes must be stabilized - stabilized = nodeVelocity < vminCorrected && stabilized === true; - nodesPresent = true; - } - - if (nodesPresent === true) { - if (vminCorrected > 0.5 * this.options.maxVelocity) { - return false; - } else { - return stabilized; - } - } - return true; - } - }, { - key: '_performStep', - - /** - * Perform the actual step - * - * @param nodeId - * @param maxVelocity - * @returns {number} - * @private - */ - value: function _performStep(nodeId, maxVelocity) { - var node = this.body.nodes[nodeId]; - var timestep = this.options.timestep; - var forces = this.physicsBody.forces; - var velocities = this.physicsBody.velocities; - - // store the state so we can revert - this.previousStates[nodeId] = { x: node.x, y: node.y, vx: velocities[nodeId].x, vy: velocities[nodeId].y }; - - if (node.options.fixed.x === false) { - var dx = this.modelOptions.damping * velocities[nodeId].x; // damping force - var ax = (forces[nodeId].x - dx) / node.options.mass; // acceleration - velocities[nodeId].x += ax * timestep; // velocity - 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; - } - - if (node.options.fixed.y === false) { - var dy = this.modelOptions.damping * velocities[nodeId].y; // damping force - var ay = (forces[nodeId].y - dy) / node.options.mass; // acceleration - velocities[nodeId].y += ay * timestep; // velocity - 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; - } - - 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. - */ - 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 - * because only the supportnodes for the smoothCurves have to settle. - * - * @private - */ - value: function _freezeNodes() { - var nodes = this.body.nodes; - for (var id in nodes) { - if (nodes.hasOwnProperty(id)) { - if (nodes[id].x && nodes[id].y) { - this.freezeCache[id] = { x: nodes[id].options.fixed.x, y: nodes[id].options.fixed.y }; - nodes[id].options.fixed.x = true; - nodes[id].options.fixed.y = true; - } - } - } - } - }, { - key: '_restoreFrozenNodes', - - /** - * Unfreezes the nodes that have been frozen by _freezeDefinedNodes. - * - * @private - */ - value: function _restoreFrozenNodes() { - var nodes = this.body.nodes; - for (var id in nodes) { - if (nodes.hasOwnProperty(id)) { - if (this.freezeCache[id] !== undefined) { - nodes[id].options.fixed.x = this.freezeCache[id].x; - nodes[id].options.fixed.y = this.freezeCache[id].y; - } - } - } - this.freezeCache = {}; - } - }, { - key: 'stabilize', - - /** - * Find a stable position for all nodes - * @private - */ - value: function stabilize() { - var _this3 = this; - - var iterations = arguments[0] === undefined ? this.options.stabilization.iterations : arguments[0]; - - if (typeof iterations !== 'number') { - console.log('The stabilize method needs a numeric amount of iterations. Switching to default: ', this.options.stabilization.iterations); - iterations = this.options.stabilization.iterations; - } - - // this sets the width of all nodes initially which could be required for the avoidOverlap - this.body.emitter.emit('_resizeNodes'); - - // stop the render loop - this.stopSimulation(); - - // set stabilze to false - this.stabilized = false; - - // block redraw requests - this.body.emitter.emit('_blockRedrawRequests'); - this.targetIterations = iterations; - - // start the stabilization - if (this.options.stabilization.onlyDynamicEdges === true) { - this._freezeNodes(); - } - this.stabilizationIterations = 0; - - setTimeout(function () { - return _this3._stabilizationBatch(); - }, 0); - } - }, { - key: '_stabilizationBatch', - value: function _stabilizationBatch() { - var count = 0; - while (this.stabilized === false && count < this.options.stabilization.updateInterval && this.stabilizationIterations < this.targetIterations) { - this.physicsTick(); - this.stabilizationIterations++; - count++; - } - - if (this.stabilized === false && this.stabilizationIterations < this.targetIterations) { - this.body.emitter.emit('stabilizationProgress', { iterations: this.stabilizationIterations, total: this.targetIterations }); - setTimeout(this._stabilizationBatch.bind(this), 0); - } else { - this._finalizeStabilization(); - } - } - }, { - key: '_finalizeStabilization', - value: function _finalizeStabilization() { - this.body.emitter.emit('_allowRedrawRequests'); - if (this.options.stabilization.fit === true) { - this.body.emitter.emit('fit'); - } - - if (this.options.stabilization.onlyDynamicEdges === true) { - this._restoreFrozenNodes(); - } - - this.body.emitter.emit('stabilizationIterationsDone'); - this.body.emitter.emit('_requestRedraw'); - - if (this.stabilized === true) { - this._emitStabilized(); - } else { - this.startSimulation(); - } - - this.ready = true; - } - }]); - - return PhysicsEngine; - })(); - - exports['default'] = PhysicsEngine; - module.exports = exports['default']; - -/***/ }, -/* 5 */ -/***/ function(module, exports, __webpack_require__) { - - // Load custom shapes into CanvasRenderingContext2D - 'use strict'; - - function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } - - var _modulesGroups = __webpack_require__(62); - - var _modulesGroups2 = _interopRequireDefault(_modulesGroups); - - var _modulesNodesHandler = __webpack_require__(63); - - var _modulesNodesHandler2 = _interopRequireDefault(_modulesNodesHandler); - - var _modulesEdgesHandler = __webpack_require__(83); - - var _modulesEdgesHandler2 = _interopRequireDefault(_modulesEdgesHandler); - - var _modulesPhysicsEngine = __webpack_require__(4); - - var _modulesPhysicsEngine2 = _interopRequireDefault(_modulesPhysicsEngine); - - var _modulesClustering = __webpack_require__(97); - - var _modulesClustering2 = _interopRequireDefault(_modulesClustering); - - var _modulesCanvasRenderer = __webpack_require__(99); - - var _modulesCanvasRenderer2 = _interopRequireDefault(_modulesCanvasRenderer); - - var _modulesCanvas = __webpack_require__(100); - - var _modulesCanvas2 = _interopRequireDefault(_modulesCanvas); - - var _modulesView = __webpack_require__(101); - - var _modulesView2 = _interopRequireDefault(_modulesView); - - var _modulesInteractionHandler = __webpack_require__(102); - - var _modulesInteractionHandler2 = _interopRequireDefault(_modulesInteractionHandler); - - var _modulesSelectionHandler = __webpack_require__(105); - - var _modulesSelectionHandler2 = _interopRequireDefault(_modulesSelectionHandler); - - var _modulesLayoutEngine = __webpack_require__(106); - - var _modulesLayoutEngine2 = _interopRequireDefault(_modulesLayoutEngine); - - var _modulesManipulationSystem = __webpack_require__(107); - - var _modulesManipulationSystem2 = _interopRequireDefault(_modulesManipulationSystem); - - var _sharedConfigurator = __webpack_require__(2); - - var _sharedConfigurator2 = _interopRequireDefault(_sharedConfigurator); - - var _sharedValidator = __webpack_require__(50); - - var _sharedValidator2 = _interopRequireDefault(_sharedValidator); - - var _optionsJs = __webpack_require__(108); - - __webpack_require__(109); - - var Emitter = __webpack_require__(17); - var Hammer = __webpack_require__(27); - var util = __webpack_require__(3); - var DataSet = __webpack_require__(12); - var DataView = __webpack_require__(14); - var dotparser = __webpack_require__(110); - var gephiParser = __webpack_require__(111); - var Images = __webpack_require__(112); - var Activator = __webpack_require__(46); - var locales = __webpack_require__(113); - - /** - * @constructor Network - * Create a network visualization, displaying nodes and edges. - * - * @param {Element} container The DOM element in which the Network will - * be created. Normally a div element. - * @param {Object} data An object containing parameters - * {Array} nodes - * {Array} edges - * @param {Object} options Options - */ - function Network(container, data, options) { - var _this = this; - - if (!(this instanceof Network)) { - throw new SyntaxError('Constructor must be called with the new operator'); - } - - // set constant values - this.options = {}; - this.defaultOptions = { - locale: 'en', - locales: locales, - clickToUse: false - }; - util.extend(this.options, this.defaultOptions); - - // containers for nodes and edges - this.body = { - container: container, - nodes: {}, - nodeIndices: [], - edges: {}, - edgeIndices: [], - emitter: { - on: this.on.bind(this), - off: this.off.bind(this), - emit: this.emit.bind(this), - once: this.once.bind(this) - }, - eventListeners: { - onTap: function onTap() {}, - onTouch: function onTouch() {}, - onDoubleTap: function onDoubleTap() {}, - onHold: function onHold() {}, - onDragStart: function onDragStart() {}, - onDrag: function onDrag() {}, - onDragEnd: function onDragEnd() {}, - onMouseWheel: function onMouseWheel() {}, - onPinch: function onPinch() {}, - onMouseMove: function onMouseMove() {}, - onRelease: function onRelease() {}, - onContext: function onContext() {} - }, - data: { - nodes: null, // A DataSet or DataView - edges: null // A DataSet or DataView - }, - functions: { - createNode: function createNode() {}, - createEdge: function createEdge() {}, - getPointer: function getPointer() {} - }, - view: { - scale: 1, - translation: { x: 0, y: 0 } - } - }; - - // bind the event listeners - this.bindEventListeners(); - - // setting up all modules - this.images = new Images(function () { - 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 - this.selectionHandler = new _modulesSelectionHandler2['default'](this.body, this.canvas); // Selection handler - this.interactionHandler = new _modulesInteractionHandler2['default'](this.body, this.canvas, this.selectionHandler); // Interaction handler handles all the hammer bindings (that are bound by canvas), key - this.view = new _modulesView2['default'](this.body, this.canvas); // camera handler, does animations and zooms - this.renderer = new _modulesCanvasRenderer2['default'](this.body, this.canvas); // renderer, starts renderloop, has events that modules can hook into - this.physics = new _modulesPhysicsEngine2['default'](this.body); // physics engine, does all the simulations - this.layoutEngine = new _modulesLayoutEngine2['default'](this.body); // layout engine for inital layout and hierarchical layout - this.clustering = new _modulesClustering2['default'](this.body); // clustering api - this.manipulation = new _modulesManipulationSystem2['default'](this.body, this.canvas, this.selectionHandler); // data manipulation system - - 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 - - // create the DOM elements - this.canvas._create(); - - // setup configuration system - this.configurator = new _sharedConfigurator2['default'](this, this.body.container, _optionsJs.configureOptions, this.canvas.pixelRatio); - - // apply options - this.setOptions(options); - - // load data (the disable start variable will be the same as the enabled clustering) - this.setData(data); - } - - // Extend Network with an Emitter mixin - Emitter(Network.prototype); - - /** - * Set options - * @param {Object} options - */ - Network.prototype.setOptions = function (options) { - var _this2 = this; - - if (options !== undefined) { - - var errorFound = _sharedValidator2['default'].validate(options, _optionsJs.allOptions); - if (errorFound === true) { - console.log('%cErrors have been found in the supplied options object.', _sharedValidator.printStyle); - } - - // copy the global fields over - var fields = ['locale', 'locales', 'clickToUse']; - util.selectiveDeepExtend(fields, this.options, options); - - // the hierarchical system can adapt the edges and the physics to it's own options because not all combinations work with the hierarichical system. - options = this.layoutEngine.setOptions(options.layout, options); - - this.canvas.setOptions(options); // options for canvas are in globals - - // pass the options to the modules - this.groups.setOptions(options.groups); - this.nodesHandler.setOptions(options.nodes); - this.edgesHandler.setOptions(options.edges); - this.physics.setOptions(options.physics); - this.manipulation.setOptions(options.manipulation, options, this.options); // manipulation uses the locales in the globals - - this.interactionHandler.setOptions(options.interaction); - this.renderer.setOptions(options.interaction); // options for rendering are in interaction - this.selectionHandler.setOptions(options.interaction); // options for selection are in interaction - - // reload the settings of the nodes to apply changes in groups that are not referenced by pointer. - if (options.groups !== undefined) { - this.body.emitter.emit('refreshNodes'); - } - // these two do not have options at the moment, here for completeness - //this.view.setOptions(options.view); - //this.clustering.setOptions(options.clustering); - - this.configurator.setOptions(options.configure); - - // if the configuration system is enabled, copy all options and put them into the config system - if (this.configurator.options.enabled === true) { - var networkOptions = { nodes: {}, edges: {}, layout: {}, interaction: {}, manipulation: {}, physics: {}, global: {} }; - util.deepExtend(networkOptions.nodes, this.nodesHandler.options); - util.deepExtend(networkOptions.edges, this.edgesHandler.options); - util.deepExtend(networkOptions.layout, this.layoutEngine.options); - // load the selectionHandler and rendere default options in to the interaction group - util.deepExtend(networkOptions.interaction, this.selectionHandler.options); - util.deepExtend(networkOptions.interaction, this.renderer.options); - - util.deepExtend(networkOptions.interaction, this.interactionHandler.options); - util.deepExtend(networkOptions.manipulation, this.manipulation.options); - util.deepExtend(networkOptions.physics, this.physics.options); - - // load globals into the global object - util.deepExtend(networkOptions.global, this.canvas.options); - util.deepExtend(networkOptions.global, this.options); - - this.configurator.setModuleOptions(networkOptions); - } - - // handle network global options - if (options.clickToUse !== undefined) { - if (options.clickToUse === true) { - if (this.activator === undefined) { - this.activator = new Activator(this.canvas.frame); - this.activator.on('change', function () { - _this2.body.emitter.emit('activate'); - }); - } - } else { - if (this.activator !== undefined) { - this.activator.destroy(); - delete this.activator; - } - this.body.emitter.emit('activate'); - } - } else { - this.body.emitter.emit('activate'); - } - - this.canvas.setSize(); - // start the physics simulation. Can be safely called multiple times. - this.body.emitter.emit('startSimulation'); - } - }; - - /** - * Update the this.body.nodeIndices with the most recent node index list - * @private - */ - Network.prototype._updateVisibleIndices = function () { - var nodes = this.body.nodes; - var edges = this.body.edges; - this.body.nodeIndices = []; - this.body.edgeIndices = []; - - for (var nodeId in nodes) { - if (nodes.hasOwnProperty(nodeId)) { - if (nodes[nodeId].options.hidden === false) { - this.body.nodeIndices.push(nodeId); - } - } - } - - for (var edgeId in edges) { - if (edges.hasOwnProperty(edgeId)) { - if (edges[edgeId].options.hidden === false) { - this.body.edgeIndices.push(edgeId); - } - } - } - }; - - /** - * Bind all events - */ - Network.prototype.bindEventListeners = function () { - 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 () { - // update shortcut lists - _this3._updateVisibleIndices(); - _this3.physics.updatePhysicsData(); - - // call the dataUpdated event because the only difference between the two is the updating of the indices - _this3.body.emitter.emit('_dataUpdated'); - }); - - // this is called when options of EXISTING nodes or edges have changed. - 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'); - }); - }; - - /** - * Set nodes and edges, and optionally options as well. - * - * @param {Object} data Object containing parameters: - * {Array | DataSet | DataView} [nodes] Array with nodes - * {Array | DataSet | DataView} [edges] Array with edges - * {String} [dot] String containing data in DOT format - * {String} [gephi] String containing data in gephi JSON format - * {Options} [options] Object with options - */ - Network.prototype.setData = function (data) { - // reset the physics engine. - 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(); - - if (data && data.dot && (data.nodes || data.edges)) { - throw new SyntaxError('Data must contain either parameter "dot" or ' + ' parameter pair "nodes" and "edges", but not both.'); - } - - // set options - this.setOptions(data && data.options); - // set all data - if (data && data.dot) { - console.log('The dot property has been depricated. Please use the static convertDot method to convert DOT into vis.network format and use the normal data format with nodes and edges. This converter is used like this: var data = vis.network.convertDot(dotString);'); - // parse DOT file - var dotData = dotparser.DOTToGraph(data.dot); - this.setData(dotData); - return; - } else if (data && data.gephi) { - // parse DOT file - console.log('The gephi property has been depricated. Please use the static convertGephi method to convert gephi into vis.network format and use the normal data format with nodes and edges. This converter is used like this: var data = vis.network.convertGephi(gephiJson);'); - var gephiData = gephiParser.parseGephi(data.gephi); - this.setData(gephiData); - return; - } else { - this.nodesHandler.setData(data && data.nodes, true); - this.edgesHandler.setData(data && data.edges, true); - } - - // emit change in data - this.body.emitter.emit('_dataChanged'); - - // find a stable position or start animating to a stable position - this.body.emitter.emit('initPhysics'); - }; - - /** - * Cleans up all bindings of the network, removing it fully from the memory IF the variable is set to null after calling this function. - * var network = new vis.Network(..); - * network.destroy(); - * network = null; - */ - Network.prototype.destroy = function () { - this.body.emitter.emit('destroy'); - // clear events - this.body.emitter.off(); - this.off(); - - // delete modules - delete this.groups; - delete this.canvas; - delete this.selectionHandler; - delete this.interactionHandler; - delete this.view; - delete this.renderer; - delete this.physics; - delete this.layoutEngine; - delete this.clustering; - delete this.manipulation; - delete this.nodesHandler; - delete this.edgesHandler; - delete this.configurator; - delete this.images; - - for (var nodeId in this.body.nodes) { - delete this.body.nodes[nodeId]; - } - for (var edgeId in this.body.edges) { - delete this.body.edges[edgeId]; - } - - // remove the container and everything inside it recursively - util.recursiveDOMDelete(this.body.container); - }; - - /** - * Update the values of all object in the given array according to the current - * value range of the objects in the array. - * @param {Object} obj An object containing a set of Edges or Nodes - * The objects must have a method getValue() and - * setValueRange(min, max). - * @private - */ - Network.prototype._updateValueRange = function (obj) { - var id; - - // determine the range of the objects - var valueMin = undefined; - var valueMax = undefined; - var valueTotal = 0; - for (id in obj) { - if (obj.hasOwnProperty(id)) { - var value = obj[id].getValue(); - if (value !== undefined) { - valueMin = valueMin === undefined ? value : Math.min(value, valueMin); - valueMax = valueMax === undefined ? value : Math.max(value, valueMax); - valueTotal += value; - } - } - } - - // adjust the range of all objects - if (valueMin !== undefined && valueMax !== undefined) { - for (id in obj) { - if (obj.hasOwnProperty(id)) { - obj[id].setValueRange(valueMin, valueMax, valueTotal); - } - } - } - }; - - /** - * Returns true when the Network is active. - * @returns {boolean} - */ - Network.prototype.isActive = function () { - return !this.activator || this.activator.active; - }; - - Network.prototype.setSize = function () { - return this.canvas.setSize.apply(this.canvas, arguments); - }; - Network.prototype.canvasToDOM = function () { - return this.canvas.canvasToDOM.apply(this.canvas, arguments); - }; - Network.prototype.DOMtoCanvas = function () { - return this.canvas.DOMtoCanvas(this.canvas, arguments); - }; - Network.prototype.findNode = function () { - return this.clustering.findNode.apply(this.clustering, arguments); - }; - Network.prototype.isCluster = function () { - return this.clustering.isCluster.apply(this.clustering, arguments); - }; - Network.prototype.openCluster = function () { - return this.clustering.openCluster.apply(this.clustering, arguments); - }; - Network.prototype.cluster = function () { - return this.clustering.cluster.apply(this.clustering, arguments); - }; - Network.prototype.getNodesInCluster = function () { - return this.clustering.getNodesInCluster.apply(this.clustering, arguments); - }; - Network.prototype.clusterByConnection = function () { - return this.clustering.clusterByConnection.apply(this.clustering, arguments); - }; - Network.prototype.clusterByHubsize = function () { - return this.clustering.clusterByHubsize.apply(this.clustering, arguments); - }; - Network.prototype.clusterOutliers = function () { - return this.clustering.clusterOutliers.apply(this.clustering, arguments); - }; - Network.prototype.getSeed = function () { - return this.layoutEngine.getSeed.apply(this.layoutEngine, arguments); - }; - Network.prototype.enableEditMode = function () { - return this.manipulation.enableEditMode.apply(this.manipulation, arguments); - }; - Network.prototype.disableEditMode = function () { - return this.manipulation.disableEditMode.apply(this.manipulation, arguments); - }; - Network.prototype.addNodeMode = function () { - return this.manipulation.addNodeMode.apply(this.manipulation, arguments); - }; - Network.prototype.editNode = function () { - return this.manipulation.editNode.apply(this.manipulation, arguments); - }; - Network.prototype.editNodeMode = function () { - console.log('Depricated: 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); - }; - Network.prototype.editEdgeMode = function () { - return this.manipulation.editEdgeMode.apply(this.manipulation, arguments); - }; - Network.prototype.deleteSelected = function () { - return this.manipulation.deleteSelected.apply(this.manipulation, arguments); - }; - Network.prototype.getPositions = function () { - return this.nodesHandler.getPositions.apply(this.nodesHandler, arguments); - }; - Network.prototype.storePositions = function () { - return this.nodesHandler.storePositions.apply(this.nodesHandler, arguments); - }; - Network.prototype.getBoundingBox = function () { - return this.nodesHandler.getBoundingBox.apply(this.nodesHandler, arguments); - }; - Network.prototype.getConnectedNodes = function (objectId) { - if (this.body.nodes[objectId] !== undefined) { - return this.nodesHandler.getConnectedNodes.apply(this.nodesHandler, arguments); - } else { - return this.edgesHandler.getConnectedNodes.apply(this.edgesHandler, arguments); - } - }; - Network.prototype.getConnectedEdges = function () { - return this.nodesHandler.getConnectedEdges.apply(this.nodesHandler, arguments); - }; - Network.prototype.startSimulation = function () { - return this.physics.startSimulation.apply(this.physics, arguments); - }; - Network.prototype.stopSimulation = function () { - return this.physics.stopSimulation.apply(this.physics, arguments); - }; - Network.prototype.stabilize = function () { - return this.physics.stabilize.apply(this.physics, arguments); - }; - Network.prototype.getSelection = function () { - return this.selectionHandler.getSelection.apply(this.selectionHandler, arguments); - }; - Network.prototype.getSelectedNodes = function () { - return this.selectionHandler.getSelectedNodes.apply(this.selectionHandler, arguments); - }; - Network.prototype.getSelectedEdges = function () { - return this.selectionHandler.getSelectedEdges.apply(this.selectionHandler, arguments); - }; - Network.prototype.getNodeAt = function () { - var node = this.selectionHandler.getNodeAt.apply(this.selectionHandler, arguments); - if (node !== undefined && node.id !== undefined) { - return node.id; - } - return node; - }; - Network.prototype.getEdgeAt = function () { - var edge = this.selectionHandler.getEdgeAt.apply(this.selectionHandler, arguments); - if (edge !== undefined && edge.id !== undefined) { - return edge.id; - } - return edge; - }; - 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.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); - }; - Network.prototype.fit = function () { - return this.view.fit.apply(this.view, arguments); - }; - Network.prototype.moveTo = function () { - return this.view.moveTo.apply(this.view, arguments); - }; - Network.prototype.focus = function () { - return this.view.focus.apply(this.view, arguments); - }; - Network.prototype.releaseNode = function () { - return this.view.releaseNode.apply(this.view, arguments); - }; - - module.exports = Network; - -/***/ }, -/* 6 */ -/***/ 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; }; })(); - - function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - - var HierarchicalSpringSolver = (function () { - function HierarchicalSpringSolver(body, physicsBody, options) { - _classCallCheck(this, HierarchicalSpringSolver); - - this.body = body; - this.physicsBody = physicsBody; - this.setOptions(options); - } - - _createClass(HierarchicalSpringSolver, [{ - key: "setOptions", - value: function setOptions(options) { - this.options = options; - } - }, { - key: "solve", - - /** - * This function calculates the springforces on the nodes, accounting for the support nodes. - * - * @private - */ - value: function solve() { - var edgeLength, edge; - var dx, dy, fx, fy, springForce, distance; - var edges = this.body.edges; - var factor = 0.5; - - var edgeIndices = this.physicsBody.physicsEdgeIndices; - var nodeIndices = this.physicsBody.physicsNodeIndices; - var forces = this.physicsBody.forces; - - // initialize the spring force counters - for (var i = 0; i < nodeIndices.length; i++) { - var nodeId = nodeIndices[i]; - forces[nodeId].springFx = 0; - forces[nodeId].springFy = 0; - } - - // forces caused by the edges, modelled as springs - for (var i = 0; i < edgeIndices.length; i++) { - edge = edges[edgeIndices[i]]; - if (edge.connected === true) { - edgeLength = edge.options.length === undefined ? this.options.springLength : edge.options.length; - - dx = edge.from.x - edge.to.x; - dy = edge.from.y - edge.to.y; - distance = Math.sqrt(dx * dx + dy * dy); - distance = distance === 0 ? 0.01 : distance; - - // the 1/distance is so the fx and fy can be calculated without sine or cosine. - springForce = this.options.springConstant * (edgeLength - distance) / distance; - - fx = dx * springForce; - fy = dy * springForce; - - if (edge.to.level != edge.from.level) { - if (forces[edge.toId] !== undefined) { - forces[edge.toId].springFx -= fx; - forces[edge.toId].springFy -= fy; - } - if (forces[edge.fromId] !== undefined) { - forces[edge.fromId].springFx += fx; - forces[edge.fromId].springFy += fy; - } - } else { - if (forces[edge.toId] !== undefined) { - forces[edge.toId].x -= factor * fx; - forces[edge.toId].y -= factor * fy; - } - if (forces[edge.fromId] !== undefined) { - forces[edge.fromId].x += factor * fx; - forces[edge.fromId].y += factor * fy; - } - } - } - } - - // normalize spring forces - var springForce = 1; - var springFx, springFy; - for (var i = 0; i < nodeIndices.length; i++) { - var nodeId = nodeIndices[i]; - springFx = Math.min(springForce, Math.max(-springForce, forces[nodeId].springFx)); - springFy = Math.min(springForce, Math.max(-springForce, forces[nodeId].springFy)); - - forces[nodeId].x += springFx; - forces[nodeId].y += springFy; - } - - // retain energy balance - var totalFx = 0; - var totalFy = 0; - for (var i = 0; i < nodeIndices.length; i++) { - var nodeId = nodeIndices[i]; - totalFx += forces[nodeId].x; - totalFy += forces[nodeId].y; - } - var correctionFx = totalFx / nodeIndices.length; - var correctionFy = totalFy / nodeIndices.length; - - for (var i = 0; i < nodeIndices.length; i++) { - var nodeId = nodeIndices[i]; - forces[nodeId].x -= correctionFx; - forces[nodeId].y -= correctionFy; - } - } - }]); - - return HierarchicalSpringSolver; - })(); - - exports["default"] = HierarchicalSpringSolver; - module.exports = exports["default"]; - -/***/ }, -/* 7 */ /***/ function(module, exports, __webpack_require__) { // first check if moment.js is already loaded in the browser window, if so, // use this instance. Else, load via commonjs. 'use strict'; - module.exports = typeof window !== 'undefined' && window['moment'] || __webpack_require__(8); + module.exports = typeof window !== 'undefined' && window['moment'] || __webpack_require__(5); /***/ }, -/* 8 */ +/* 5 */ /***/ function(module, exports, __webpack_require__) { /* WEBPACK VAR INJECTION */(function(module) {//! moment.js @@ -6683,10 +5269,10 @@ return /******/ (function(modules) { // webpackBootstrap return _moment; })); - /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(9)(module))) + /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(6)(module))) /***/ }, -/* 9 */ +/* 6 */ /***/ function(module, exports, __webpack_require__) { module.exports = function(module) { @@ -6702,7 +5288,7 @@ return /******/ (function(modules) { // webpackBootstrap /***/ }, -/* 10 */ +/* 7 */ /***/ function(module, exports, __webpack_require__) { /* WEBPACK VAR INJECTION */(function(global) {'use strict'; @@ -6918,7 +5504,7 @@ return /******/ (function(modules) { // webpackBootstrap /* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }()))) /***/ }, -/* 11 */ +/* 8 */ /***/ function(module, exports, __webpack_require__) { // DOM utility methods @@ -7120,13 +5706,13 @@ return /******/ (function(modules) { // webpackBootstrap }; /***/ }, -/* 12 */ +/* 9 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; var util = __webpack_require__(3); - var Queue = __webpack_require__(13); + var Queue = __webpack_require__(10); /** * DataSet @@ -8015,7 +6601,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = DataSet; /***/ }, -/* 13 */ +/* 10 */ /***/ function(module, exports, __webpack_require__) { /** @@ -8220,13 +6806,13 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = Queue; /***/ }, -/* 14 */ +/* 11 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; var util = __webpack_require__(3); - var DataSet = __webpack_require__(12); + var DataSet = __webpack_require__(9); /** * DataView @@ -8568,21 +7154,21 @@ return /******/ (function(modules) { // webpackBootstrap // nothing interesting for me :-( /***/ }, -/* 15 */ +/* 12 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; - var Emitter = __webpack_require__(17); - var DataSet = __webpack_require__(12); - var DataView = __webpack_require__(14); + var Emitter = __webpack_require__(14); + var DataSet = __webpack_require__(9); + var DataView = __webpack_require__(11); var util = __webpack_require__(3); - var Point3d = __webpack_require__(18); - var Point2d = __webpack_require__(16); - var Camera = __webpack_require__(19); - var Filter = __webpack_require__(20); - var Slider = __webpack_require__(21); - var StepNumber = __webpack_require__(22); + var Point3d = __webpack_require__(15); + var Point2d = __webpack_require__(13); + var Camera = __webpack_require__(16); + var Filter = __webpack_require__(17); + var Slider = __webpack_require__(18); + var StepNumber = __webpack_require__(19); /** * @constructor Graph3d @@ -10786,7 +9372,7 @@ return /******/ (function(modules) { // webpackBootstrap // use use defaults /***/ }, -/* 16 */ +/* 13 */ /***/ function(module, exports, __webpack_require__) { /** @@ -10804,7 +9390,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = Point2d; /***/ }, -/* 17 */ +/* 14 */ /***/ function(module, exports, __webpack_require__) { @@ -10974,7 +9560,7 @@ return /******/ (function(modules) { // webpackBootstrap /***/ }, -/* 18 */ +/* 15 */ /***/ function(module, exports, __webpack_require__) { /** @@ -11057,12 +9643,12 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = Point3d; /***/ }, -/* 19 */ +/* 16 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; - var Point3d = __webpack_require__(18); + var Point3d = __webpack_require__(15); /** * @class Camera @@ -11198,12 +9784,12 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = Camera; /***/ }, -/* 20 */ +/* 17 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; - var DataView = __webpack_require__(14); + var DataView = __webpack_require__(11); /** * @class Filter @@ -11409,7 +9995,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = Filter; /***/ }, -/* 21 */ +/* 18 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; @@ -11757,7 +10343,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = Slider; /***/ }, -/* 22 */ +/* 19 */ /***/ function(module, exports, __webpack_require__) { /** @@ -11901,28 +10487,28 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = StepNumber; /***/ }, -/* 23 */ +/* 20 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; - var Emitter = __webpack_require__(17); - var Hammer = __webpack_require__(27); + var Emitter = __webpack_require__(14); + var Hammer = __webpack_require__(24); var util = __webpack_require__(3); - var DataSet = __webpack_require__(12); - var DataView = __webpack_require__(14); - var Range = __webpack_require__(31); - var Core = __webpack_require__(34); - var TimeAxis = __webpack_require__(45); - var CurrentTime = __webpack_require__(24); - var CustomTime = __webpack_require__(48); - var ItemSet = __webpack_require__(35); - - var Configurator = __webpack_require__(2); - var Validator = __webpack_require__(50)['default']; - var printStyle = __webpack_require__(50).printStyle; - var allOptions = __webpack_require__(51).allOptions; - var configureOptions = __webpack_require__(51).configureOptions; + var DataSet = __webpack_require__(9); + var DataView = __webpack_require__(11); + var Range = __webpack_require__(28); + var Core = __webpack_require__(31); + var TimeAxis = __webpack_require__(42); + var CurrentTime = __webpack_require__(21); + var CustomTime = __webpack_require__(45); + var ItemSet = __webpack_require__(32); + + var Configurator = __webpack_require__(46); + var Validator = __webpack_require__(48)['default']; + var printStyle = __webpack_require__(48).printStyle; + var allOptions = __webpack_require__(49).allOptions; + var configureOptions = __webpack_require__(49).configureOptions; /** * Create a timeline visualization @@ -12425,15 +11011,15 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = Timeline; /***/ }, -/* 24 */ +/* 21 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; var util = __webpack_require__(3); - var Component = __webpack_require__(25); - var moment = __webpack_require__(7); - var locales = __webpack_require__(26); + var Component = __webpack_require__(22); + var moment = __webpack_require__(4); + var locales = __webpack_require__(23); /** * A current time bar @@ -12601,7 +11187,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = CurrentTime; /***/ }, -/* 25 */ +/* 22 */ /***/ function(module, exports, __webpack_require__) { /** @@ -12661,7 +11247,7 @@ return /******/ (function(modules) { // webpackBootstrap // should be implemented by the component /***/ }, -/* 26 */ +/* 23 */ /***/ function(module, exports, __webpack_require__) { // English @@ -12683,7 +11269,7 @@ return /******/ (function(modules) { // webpackBootstrap exports['nl_BE'] = exports['nl']; /***/ }, -/* 27 */ +/* 24 */ /***/ function(module, exports, __webpack_require__) { // Only load hammer.js when in a browser environment @@ -12691,8 +11277,8 @@ return /******/ (function(modules) { // webpackBootstrap 'use strict'; if (typeof window !== 'undefined') { - var propagating = __webpack_require__(28); - var Hammer = window['Hammer'] || __webpack_require__(29); + var propagating = __webpack_require__(25); + var Hammer = window['Hammer'] || __webpack_require__(26); module.exports = propagating(Hammer, { preventDefault: 'mouse' }); @@ -12703,7 +11289,7 @@ return /******/ (function(modules) { // webpackBootstrap } /***/ }, -/* 28 */ +/* 25 */ /***/ function(module, exports, __webpack_require__) { var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;'use strict'; @@ -12931,7 +11517,7 @@ return /******/ (function(modules) { // webpackBootstrap /***/ }, -/* 29 */ +/* 26 */ /***/ function(module, exports, __webpack_require__) { var __WEBPACK_AMD_DEFINE_RESULT__;/*! Hammer.JS - v2.0.4 - 2014-09-28 @@ -15386,7 +13972,7 @@ return /******/ (function(modules) { // webpackBootstrap prefixed: prefixed }); - if ("function" == TYPE_FUNCTION && __webpack_require__(30)) { + if ("function" == TYPE_FUNCTION && __webpack_require__(27)) { !(__WEBPACK_AMD_DEFINE_RESULT__ = function() { return Hammer; }.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); @@ -15400,7 +13986,7 @@ return /******/ (function(modules) { // webpackBootstrap /***/ }, -/* 30 */ +/* 27 */ /***/ function(module, exports, __webpack_require__) { /* WEBPACK VAR INJECTION */(function(__webpack_amd_options__) {module.exports = __webpack_amd_options__; @@ -15408,16 +13994,16 @@ return /******/ (function(modules) { // webpackBootstrap /* WEBPACK VAR INJECTION */}.call(exports, {})) /***/ }, -/* 31 */ +/* 28 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; var util = __webpack_require__(3); - var hammerUtil = __webpack_require__(32); - var moment = __webpack_require__(7); - var Component = __webpack_require__(25); - var DateUtil = __webpack_require__(33); + var hammerUtil = __webpack_require__(29); + var moment = __webpack_require__(4); + var Component = __webpack_require__(22); + var DateUtil = __webpack_require__(30); /** * @constructor Range @@ -16084,12 +14670,12 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = Range; /***/ }, -/* 32 */ +/* 29 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; - var Hammer = __webpack_require__(27); + var Hammer = __webpack_require__(24); /** * Register a touch event, taking place before a gesture @@ -16156,12 +14742,12 @@ return /******/ (function(modules) { // webpackBootstrap exports.offRelease = exports.offTouch; /***/ }, -/* 33 */ +/* 30 */ /***/ function(module, exports, __webpack_require__) { "use strict"; - var moment = __webpack_require__(7); + var moment = __webpack_require__(4); /** * used in Core to convert the options into a volatile variable @@ -16616,23 +15202,23 @@ return /******/ (function(modules) { // webpackBootstrap }; /***/ }, -/* 34 */ +/* 31 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; - var Emitter = __webpack_require__(17); - var Hammer = __webpack_require__(27); - var hammerUtil = __webpack_require__(32); + var Emitter = __webpack_require__(14); + var Hammer = __webpack_require__(24); + var hammerUtil = __webpack_require__(29); var util = __webpack_require__(3); - var DataSet = __webpack_require__(12); - var DataView = __webpack_require__(14); - var Range = __webpack_require__(31); - var ItemSet = __webpack_require__(35); - var TimeAxis = __webpack_require__(45); - var Activator = __webpack_require__(46); - var DateUtil = __webpack_require__(33); - var CustomTime = __webpack_require__(48); + var DataSet = __webpack_require__(9); + var DataView = __webpack_require__(11); + var Range = __webpack_require__(28); + var ItemSet = __webpack_require__(32); + var TimeAxis = __webpack_require__(42); + var Activator = __webpack_require__(43); + var DateUtil = __webpack_require__(30); + var CustomTime = __webpack_require__(45); /** * Create a timeline visualization @@ -17587,23 +16173,23 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = Core; /***/ }, -/* 35 */ +/* 32 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; - var Hammer = __webpack_require__(27); + var Hammer = __webpack_require__(24); var util = __webpack_require__(3); - var DataSet = __webpack_require__(12); - var DataView = __webpack_require__(14); - var TimeStep = __webpack_require__(40); - var Component = __webpack_require__(25); - var Group = __webpack_require__(36); - var BackgroundGroup = __webpack_require__(41); - var BoxItem = __webpack_require__(42); - var PointItem = __webpack_require__(43); - var RangeItem = __webpack_require__(38); - var BackgroundItem = __webpack_require__(44); + var DataSet = __webpack_require__(9); + var DataView = __webpack_require__(11); + var TimeStep = __webpack_require__(37); + var Component = __webpack_require__(22); + var Group = __webpack_require__(33); + var BackgroundGroup = __webpack_require__(38); + var BoxItem = __webpack_require__(39); + var PointItem = __webpack_require__(40); + var RangeItem = __webpack_require__(35); + var BackgroundItem = __webpack_require__(41); var UNGROUPED = '__ungrouped__'; // reserved group id for ungrouped items var BACKGROUND = '__background__'; // reserved group id for background items without group @@ -19198,14 +17784,14 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = ItemSet; /***/ }, -/* 36 */ +/* 33 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; var util = __webpack_require__(3); - var stack = __webpack_require__(37); - var RangeItem = __webpack_require__(38); + var stack = __webpack_require__(34); + var RangeItem = __webpack_require__(35); /** * @constructor Group @@ -19784,7 +18370,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = Group; /***/ }, -/* 37 */ +/* 34 */ /***/ function(module, exports, __webpack_require__) { // Utility functions for ordering and stacking of items @@ -19908,13 +18494,13 @@ return /******/ (function(modules) { // webpackBootstrap }; /***/ }, -/* 38 */ +/* 35 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; - var Hammer = __webpack_require__(27); - var Item = __webpack_require__(39); + var Hammer = __webpack_require__(24); + var Item = __webpack_require__(36); /** * @constructor RangeItem @@ -20202,12 +18788,12 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = RangeItem; /***/ }, -/* 39 */ +/* 36 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; - var Hammer = __webpack_require__(27); + var Hammer = __webpack_require__(24); var util = __webpack_require__(3); /** @@ -20492,13 +19078,13 @@ return /******/ (function(modules) { // webpackBootstrap // should be implemented by the item /***/ }, -/* 40 */ +/* 37 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; - var moment = __webpack_require__(7); - var DateUtil = __webpack_require__(33); + var moment = __webpack_require__(4); + var DateUtil = __webpack_require__(30); var util = __webpack_require__(3); /** @@ -21182,13 +19768,13 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = TimeStep; /***/ }, -/* 41 */ +/* 38 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; var util = __webpack_require__(3); - var Group = __webpack_require__(36); + var Group = __webpack_require__(33); /** * @constructor BackgroundGroup @@ -21246,12 +19832,12 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = BackgroundGroup; /***/ }, -/* 42 */ +/* 39 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; - var Item = __webpack_require__(39); + var Item = __webpack_require__(36); var util = __webpack_require__(3); /** @@ -21484,12 +20070,12 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = BoxItem; /***/ }, -/* 43 */ +/* 40 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; - var Item = __webpack_require__(39); + var Item = __webpack_require__(36); /** * @constructor PointItem @@ -21687,15 +20273,15 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = PointItem; /***/ }, -/* 44 */ +/* 41 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; - var Hammer = __webpack_require__(27); - var Item = __webpack_require__(39); - var BackgroundGroup = __webpack_require__(41); - var RangeItem = __webpack_require__(38); + var Hammer = __webpack_require__(24); + var Item = __webpack_require__(36); + var BackgroundGroup = __webpack_require__(38); + var RangeItem = __webpack_require__(35); /** * @constructor BackgroundItem @@ -21908,16 +20494,16 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = BackgroundItem; /***/ }, -/* 45 */ +/* 42 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; var util = __webpack_require__(3); - var Component = __webpack_require__(25); - var TimeStep = __webpack_require__(40); - var DateUtil = __webpack_require__(33); - var moment = __webpack_require__(7); + var Component = __webpack_require__(22); + var TimeStep = __webpack_require__(37); + var DateUtil = __webpack_require__(30); + var moment = __webpack_require__(4); /** * A horizontal time axis @@ -22348,14 +20934,14 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = TimeAxis; /***/ }, -/* 46 */ +/* 43 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; - var keycharm = __webpack_require__(47); - var Emitter = __webpack_require__(17); - var Hammer = __webpack_require__(27); + var keycharm = __webpack_require__(44); + var Emitter = __webpack_require__(14); + var Hammer = __webpack_require__(24); var util = __webpack_require__(3); /** @@ -22464,482 +21050,1163 @@ return /******/ (function(modules) { // webpackBootstrap util.removeClassName(this.dom.container, 'vis-active'); this.keycharm.unbind('esc', this.escListener); - this.emit('change'); - this.emit('deactivate'); + this.emit('change'); + this.emit('deactivate'); + }; + + /** + * Handle a tap event: activate the container + * @param event + * @private + */ + Activator.prototype._onTapOverlay = function (event) { + // activate the container + this.activate(); + event.stopPropagation(); + }; + + /** + * Test whether the element has the requested parent element somewhere in + * its chain of parent nodes. + * @param {HTMLElement} element + * @param {HTMLElement} parent + * @returns {boolean} Returns true when the parent is found somewhere in the + * chain of parent nodes. + * @private + */ + function _hasParent(element, parent) { + while (element) { + if (element === parent) { + return true; + } + element = element.parentNode; + } + return false; + } + + module.exports = Activator; + +/***/ }, +/* 44 */ +/***/ function(module, exports, __webpack_require__) { + + var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;"use strict"; + /** + * Created by Alex on 11/6/2014. + */ + + // https://github.com/umdjs/umd/blob/master/returnExports.js#L40-L60 + // if the module has no dependencies, the above pattern can be simplified to + (function (root, factory) { + if (true) { + // AMD. Register as an anonymous module. + !(__WEBPACK_AMD_DEFINE_ARRAY__ = [], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory), __WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ? (__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); + } else if (typeof exports === 'object') { + // Node. Does not work with strict CommonJS, but + // only CommonJS-like environments that support module.exports, + // like Node. + module.exports = factory(); + } else { + // Browser globals (root is window) + root.keycharm = factory(); + } + }(this, function () { + + function keycharm(options) { + var preventDefault = options && options.preventDefault || false; + + var container = options && options.container || window; + + var _exportFunctions = {}; + var _bound = {keydown:{}, keyup:{}}; + var _keys = {}; + var i; + + // a - z + for (i = 97; i <= 122; i++) {_keys[String.fromCharCode(i)] = {code:65 + (i - 97), shift: false};} + // A - Z + for (i = 65; i <= 90; i++) {_keys[String.fromCharCode(i)] = {code:i, shift: true};} + // 0 - 9 + for (i = 0; i <= 9; i++) {_keys['' + i] = {code:48 + i, shift: false};} + // F1 - F12 + for (i = 1; i <= 12; i++) {_keys['F' + i] = {code:111 + i, shift: false};} + // num0 - num9 + for (i = 0; i <= 9; i++) {_keys['num' + i] = {code:96 + i, shift: false};} + + // numpad misc + _keys['num*'] = {code:106, shift: false}; + _keys['num+'] = {code:107, shift: false}; + _keys['num-'] = {code:109, shift: false}; + _keys['num/'] = {code:111, shift: false}; + _keys['num.'] = {code:110, shift: false}; + // arrows + _keys['left'] = {code:37, shift: false}; + _keys['up'] = {code:38, shift: false}; + _keys['right'] = {code:39, shift: false}; + _keys['down'] = {code:40, shift: false}; + // extra keys + _keys['space'] = {code:32, shift: false}; + _keys['enter'] = {code:13, shift: false}; + _keys['shift'] = {code:16, shift: undefined}; + _keys['esc'] = {code:27, shift: false}; + _keys['backspace'] = {code:8, shift: false}; + _keys['tab'] = {code:9, shift: false}; + _keys['ctrl'] = {code:17, shift: false}; + _keys['alt'] = {code:18, shift: false}; + _keys['delete'] = {code:46, shift: false}; + _keys['pageup'] = {code:33, shift: false}; + _keys['pagedown'] = {code:34, shift: false}; + // symbols + _keys['='] = {code:187, shift: false}; + _keys['-'] = {code:189, shift: false}; + _keys[']'] = {code:221, shift: false}; + _keys['['] = {code:219, shift: false}; + + + + var down = function(event) {handleEvent(event,'keydown');}; + var up = function(event) {handleEvent(event,'keyup');}; + + // handle the actualy bound key with the event + var handleEvent = function(event,type) { + if (_bound[type][event.keyCode] !== undefined) { + var bound = _bound[type][event.keyCode]; + for (var i = 0; i < bound.length; i++) { + if (bound[i].shift === undefined) { + bound[i].fn(event); + } + else if (bound[i].shift == true && event.shiftKey == true) { + bound[i].fn(event); + } + else if (bound[i].shift == false && event.shiftKey == false) { + bound[i].fn(event); + } + } + + if (preventDefault == true) { + event.preventDefault(); + } + } + }; + + // bind a key to a callback + _exportFunctions.bind = function(key, callback, type) { + if (type === undefined) { + type = 'keydown'; + } + if (_keys[key] === undefined) { + throw new Error("unsupported key: " + key); + } + if (_bound[type][_keys[key].code] === undefined) { + _bound[type][_keys[key].code] = []; + } + _bound[type][_keys[key].code].push({fn:callback, shift:_keys[key].shift}); + }; + + + // bind all keys to a call back (demo purposes) + _exportFunctions.bindAll = function(callback, type) { + if (type === undefined) { + type = 'keydown'; + } + for (var key in _keys) { + if (_keys.hasOwnProperty(key)) { + _exportFunctions.bind(key,callback,type); + } + } + }; + + // get the key label from an event + _exportFunctions.getKey = function(event) { + for (var key in _keys) { + if (_keys.hasOwnProperty(key)) { + if (event.shiftKey == true && _keys[key].shift == true && event.keyCode == _keys[key].code) { + return key; + } + else if (event.shiftKey == false && _keys[key].shift == false && event.keyCode == _keys[key].code) { + return key; + } + else if (event.keyCode == _keys[key].code && key == 'shift') { + return key; + } + } + } + return "unknown key, currently not supported"; + }; + + // unbind either a specific callback from a key or all of them (by leaving callback undefined) + _exportFunctions.unbind = function(key, callback, type) { + if (type === undefined) { + type = 'keydown'; + } + if (_keys[key] === undefined) { + throw new Error("unsupported key: " + key); + } + if (callback !== undefined) { + var newBindings = []; + var bound = _bound[type][_keys[key].code]; + if (bound !== undefined) { + for (var i = 0; i < bound.length; i++) { + if (!(bound[i].fn == callback && bound[i].shift == _keys[key].shift)) { + newBindings.push(_bound[type][_keys[key].code][i]); + } + } + } + _bound[type][_keys[key].code] = newBindings; + } + else { + _bound[type][_keys[key].code] = []; + } + }; + + // reset all bound variables. + _exportFunctions.reset = function() { + _bound = {keydown:{}, keyup:{}}; + }; + + // unbind all listeners and reset all variables. + _exportFunctions.destroy = function() { + _bound = {keydown:{}, keyup:{}}; + container.removeEventListener('keydown', down, true); + container.removeEventListener('keyup', up, true); + }; + + // create listeners. + container.addEventListener('keydown',down,true); + container.addEventListener('keyup',up,true); + + // return the public functions. + return _exportFunctions; + } + + return keycharm; + })); + + + + +/***/ }, +/* 45 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + var Hammer = __webpack_require__(24); + var util = __webpack_require__(3); + var Component = __webpack_require__(22); + var moment = __webpack_require__(4); + var locales = __webpack_require__(23); + + /** + * A custom time bar + * @param {{range: Range, dom: Object}} body + * @param {Object} [options] Available parameters: + * {number | string} id + * {string} locales + * {string} locale + * @constructor CustomTime + * @extends Component + */ + + function CustomTime(body, options) { + this.body = body; + + // default options + this.defaultOptions = { + locales: locales, + locale: 'en', + id: undefined + }; + this.options = util.extend({}, this.defaultOptions); + + if (options && options.time) { + this.customTime = options.time; + } else { + this.customTime = new Date(); + } + + this.eventParams = {}; // stores state parameters while dragging the bar + + this.setOptions(options); + + // create the DOM + this._create(); + } + + CustomTime.prototype = new Component(); + + /** + * Set options for the component. Options will be merged in current options. + * @param {Object} options Available parameters: + * {number | string} id + * {string} locales + * {string} locale + */ + CustomTime.prototype.setOptions = function (options) { + if (options) { + // copy all options that we know + util.selectiveExtend(['locale', 'locales', 'id'], this.options, options); + } + }; + + /** + * Create the DOM for the custom time + * @private + */ + CustomTime.prototype._create = function () { + var bar = document.createElement('div'); + bar['custom-time'] = this; + bar.className = 'vis-custom-time ' + (this.options.id || ''); + bar.style.position = 'absolute'; + bar.style.top = '0px'; + bar.style.height = '100%'; + this.bar = bar; + + var drag = document.createElement('div'); + drag.style.position = 'relative'; + drag.style.top = '0px'; + drag.style.left = '-10px'; + drag.style.height = '100%'; + drag.style.width = '20px'; + bar.appendChild(drag); + + // attach event listeners + this.hammer = new Hammer(drag); + this.hammer.on('panstart', this._onDragStart.bind(this)); + this.hammer.on('panmove', this._onDrag.bind(this)); + this.hammer.on('panend', this._onDragEnd.bind(this)); + // TODO: cleanup + //this.hammer.on('pan', function (event) { + // event.preventDefault(); + //}); + }; + + /** + * Destroy the CustomTime bar + */ + CustomTime.prototype.destroy = function () { + this.hide(); + + this.hammer.destroy(); + this.hammer = null; + + this.body = null; + }; + + /** + * Repaint the component + * @return {boolean} Returns true if the component is resized + */ + CustomTime.prototype.redraw = function () { + var parent = this.body.dom.backgroundVertical; + if (this.bar.parentNode != parent) { + // attach to the dom + if (this.bar.parentNode) { + this.bar.parentNode.removeChild(this.bar); + } + parent.appendChild(this.bar); + } + + var x = this.body.util.toScreen(this.customTime); + + var locale = this.options.locales[this.options.locale]; + if (!locale) { + if (!this.warned) { + console.log('WARNING: options.locales[\'' + this.options.locale + '\'] not found. See http://visjs.org/docs/timeline.html#Localization'); + this.warned = true; + } + locale = this.options.locales['en']; // fall back on english when not available + } + var title = locale.time + ': ' + moment(this.customTime).format('dddd, MMMM Do YYYY, H:mm:ss'); + title = title.charAt(0).toUpperCase() + title.substring(1); + + this.bar.style.left = x + 'px'; + this.bar.title = title; + + return false; + }; + + /** + * Remove the CustomTime from the DOM + */ + CustomTime.prototype.hide = function () { + // remove the line from the DOM + if (this.bar.parentNode) { + this.bar.parentNode.removeChild(this.bar); + } + }; + + /** + * Set custom time. + * @param {Date | number | string} time + */ + CustomTime.prototype.setCustomTime = function (time) { + this.customTime = util.convert(time, 'Date'); + this.redraw(); + }; + + /** + * Retrieve the current custom time. + * @return {Date} customTime + */ + CustomTime.prototype.getCustomTime = function () { + return new Date(this.customTime.valueOf()); + }; + + /** + * Start moving horizontally + * @param {Event} event + * @private + */ + CustomTime.prototype._onDragStart = function (event) { + this.eventParams.dragging = true; + this.eventParams.customTime = this.customTime; + + event.stopPropagation(); + }; + + /** + * Perform moving operating. + * @param {Event} event + * @private + */ + CustomTime.prototype._onDrag = function (event) { + if (!this.eventParams.dragging) return; + + var x = this.body.util.toScreen(this.eventParams.customTime) + event.deltaX; + var time = this.body.util.toTime(x); + + this.setCustomTime(time); + + // fire a timechange event + this.body.emitter.emit('timechange', { + id: this.options.id, + time: new Date(this.customTime.valueOf()) + }); + + event.stopPropagation(); }; /** - * Handle a tap event: activate the container - * @param event + * Stop moving operating. + * @param {Event} event * @private */ - Activator.prototype._onTapOverlay = function (event) { - // activate the container - this.activate(); + CustomTime.prototype._onDragEnd = function (event) { + if (!this.eventParams.dragging) return; + + // fire a timechanged event + this.body.emitter.emit('timechanged', { + id: this.options.id, + time: new Date(this.customTime.valueOf()) + }); + event.stopPropagation(); }; /** - * Test whether the element has the requested parent element somewhere in - * its chain of parent nodes. - * @param {HTMLElement} element - * @param {HTMLElement} parent - * @returns {boolean} Returns true when the parent is found somewhere in the - * chain of parent nodes. - * @private + * Find a custom time from an event target: + * searches for the attribute 'custom-time' in the event target's element tree + * @param {Event} event + * @return {CustomTime | null} customTime */ - function _hasParent(element, parent) { - while (element) { - if (element === parent) { - return true; + CustomTime.customTimeFromTarget = function (event) { + var target = event.target; + while (target) { + if (target.hasOwnProperty('custom-time')) { + return target['custom-time']; } - element = element.parentNode; + target = target.parentNode; } - return false; - } - module.exports = Activator; + return null; + }; + + module.exports = CustomTime; /***/ }, -/* 47 */ +/* 46 */ /***/ function(module, exports, __webpack_require__) { - var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;"use strict"; - /** - * Created by Alex on 11/6/2014. - */ + 'use strict'; - // https://github.com/umdjs/umd/blob/master/returnExports.js#L40-L60 - // if the module has no dependencies, the above pattern can be simplified to - (function (root, factory) { - if (true) { - // AMD. Register as an anonymous module. - !(__WEBPACK_AMD_DEFINE_ARRAY__ = [], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory), __WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ? (__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); - } else if (typeof exports === 'object') { - // Node. Does not work with strict CommonJS, but - // only CommonJS-like environments that support module.exports, - // like Node. - module.exports = factory(); - } else { - // Browser globals (root is window) - root.keycharm = factory(); - } - }(this, function () { + Object.defineProperty(exports, '__esModule', { + value: true + }); - function keycharm(options) { - var preventDefault = options && options.preventDefault || false; + 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 container = options && options.container || window; + function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } - var _exportFunctions = {}; - var _bound = {keydown:{}, keyup:{}}; - var _keys = {}; - var i; + function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } - // a - z - for (i = 97; i <= 122; i++) {_keys[String.fromCharCode(i)] = {code:65 + (i - 97), shift: false};} - // A - Z - for (i = 65; i <= 90; i++) {_keys[String.fromCharCode(i)] = {code:i, shift: true};} - // 0 - 9 - for (i = 0; i <= 9; i++) {_keys['' + i] = {code:48 + i, shift: false};} - // F1 - F12 - for (i = 1; i <= 12; i++) {_keys['F' + i] = {code:111 + i, shift: false};} - // num0 - num9 - for (i = 0; i <= 9; i++) {_keys['num' + i] = {code:96 + i, shift: false};} + var _ColorPicker = __webpack_require__(47); - // numpad misc - _keys['num*'] = {code:106, shift: false}; - _keys['num+'] = {code:107, shift: false}; - _keys['num-'] = {code:109, shift: false}; - _keys['num/'] = {code:111, shift: false}; - _keys['num.'] = {code:110, shift: false}; - // arrows - _keys['left'] = {code:37, shift: false}; - _keys['up'] = {code:38, shift: false}; - _keys['right'] = {code:39, shift: false}; - _keys['down'] = {code:40, shift: false}; - // extra keys - _keys['space'] = {code:32, shift: false}; - _keys['enter'] = {code:13, shift: false}; - _keys['shift'] = {code:16, shift: undefined}; - _keys['esc'] = {code:27, shift: false}; - _keys['backspace'] = {code:8, shift: false}; - _keys['tab'] = {code:9, shift: false}; - _keys['ctrl'] = {code:17, shift: false}; - _keys['alt'] = {code:18, shift: false}; - _keys['delete'] = {code:46, shift: false}; - _keys['pageup'] = {code:33, shift: false}; - _keys['pagedown'] = {code:34, shift: false}; - // symbols - _keys['='] = {code:187, shift: false}; - _keys['-'] = {code:189, shift: false}; - _keys[']'] = {code:221, shift: false}; - _keys['['] = {code:219, shift: false}; + var _ColorPicker2 = _interopRequireDefault(_ColorPicker); + var util = __webpack_require__(3); + /** + * 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 + * Number options should be written as array: [default value, min value, max value, stepsize] + * Colors should be written as array: ['color', '#ffffff'] + * Strings with should be written as array: [option1, option2, option3, ..] + * + * The options are matched with their counterparts in each of the modules and the values used in the configuration are + * + * @param parentModule | the location where parentModule.setOptions() can be called + * @param defaultContainer | the default container of the module + * @param configureOptions | the fully configured and predefined options set found in allOptions.js + * @param pixelRatio | canvas pixel ratio + */ - var down = function(event) {handleEvent(event,'keydown');}; - var up = function(event) {handleEvent(event,'keyup');}; + var Configurator = (function () { + function Configurator(parentModule, defaultContainer, configureOptions) { + var pixelRatio = arguments[3] === undefined ? 1 : arguments[3]; - // handle the actualy bound key with the event - var handleEvent = function(event,type) { - if (_bound[type][event.keyCode] !== undefined) { - var bound = _bound[type][event.keyCode]; - for (var i = 0; i < bound.length; i++) { - if (bound[i].shift === undefined) { - bound[i].fn(event); - } - else if (bound[i].shift == true && event.shiftKey == true) { - bound[i].fn(event); - } - else if (bound[i].shift == false && event.shiftKey == false) { - bound[i].fn(event); - } - } + _classCallCheck(this, Configurator); - if (preventDefault == true) { - event.preventDefault(); - } - } - }; + this.parent = parentModule; + this.changedOptions = []; + this.container = defaultContainer; + this.allowCreation = false; - // bind a key to a callback - _exportFunctions.bind = function(key, callback, type) { - if (type === undefined) { - type = 'keydown'; - } - if (_keys[key] === undefined) { - throw new Error("unsupported key: " + key); - } - if (_bound[type][_keys[key].code] === undefined) { - _bound[type][_keys[key].code] = []; - } - _bound[type][_keys[key].code].push({fn:callback, shift:_keys[key].shift}); + this.options = {}; + this.defaultOptions = { + enabled: false, + filter: true, + container: undefined, + showButton: true }; + util.extend(this.options, this.defaultOptions); + this.configureOptions = configureOptions; + this.moduleOptions = {}; + this.domElements = []; + this.colorPicker = new _ColorPicker2['default'](pixelRatio); + this.wrapper = undefined; + } - // bind all keys to a call back (demo purposes) - _exportFunctions.bindAll = function(callback, type) { - if (type === undefined) { - type = 'keydown'; - } - for (var key in _keys) { - if (_keys.hasOwnProperty(key)) { - _exportFunctions.bind(key,callback,type); - } - } - }; + _createClass(Configurator, [{ + key: 'setOptions', - // get the key label from an event - _exportFunctions.getKey = function(event) { - for (var key in _keys) { - if (_keys.hasOwnProperty(key)) { - if (event.shiftKey == true && _keys[key].shift == true && event.keyCode == _keys[key].code) { - return key; + /** + * 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) { + var enabled = true; + if (typeof options === 'string') { + this.options.filter = options; + } else if (options instanceof Array) { + this.options.filter = options.join(); + } else if (typeof options === 'object') { + if (options.container !== undefined) { + this.options.container = options.container; } - else if (event.shiftKey == false && _keys[key].shift == false && event.keyCode == _keys[key].code) { - return key; + if (options.filter !== undefined) { + this.options.filter = options.filter; } - else if (event.keyCode == _keys[key].code && key == 'shift') { - return key; + if (options.showButton !== undefined) { + this.options.showButton = options.showButton; } + if (options.enabled !== undefined) { + enabled = options.enabled; + } + } else if (typeof options === 'boolean') { + this.options.filter = true; + enabled = options; + } else if (typeof options === 'function') { + this.options.filter = options; + enabled = true; + } + if (this.options.filter === false) { + enabled = false; } - } - return "unknown key, currently not supported"; - }; - // unbind either a specific callback from a key or all of them (by leaving callback undefined) - _exportFunctions.unbind = function(key, callback, type) { - if (type === undefined) { - type = 'keydown'; + this.options.enabled = enabled; } - if (_keys[key] === undefined) { - throw new Error("unsupported key: " + key); + this._clean(); + } + }, { + key: 'setModuleOptions', + value: function setModuleOptions(moduleOptions) { + this.moduleOptions = moduleOptions; + if (this.options.enabled === true) { + this._clean(); + if (this.options.container !== undefined) { + this.container = this.options.container; + } + this._create(); } - if (callback !== undefined) { - var newBindings = []; - var bound = _bound[type][_keys[key].code]; - if (bound !== undefined) { - for (var i = 0; i < bound.length; i++) { - if (!(bound[i].fn == callback && bound[i].shift == _keys[key].shift)) { - newBindings.push(_bound[type][_keys[key].code][i]); + } + }, { + key: '_create', + + /** + * Create all DOM elements + * @private + */ + value: function _create() { + var _this = this; + + this._clean(); + this.changedOptions = []; + + var filter = this.options.filter; + var counter = 0; + var show = false; + for (var option in this.configureOptions) { + if (this.configureOptions.hasOwnProperty(option)) { + this.allowCreation = false; + show = false; + if (typeof filter === 'function') { + show = filter(option, []); + show = show || this._handleObject(this.configureOptions[option], [option], true); + } else if (filter === true || filter.indexOf(option) !== -1) { + show = true; + } + + if (show !== false) { + this.allowCreation = true; + + // linebreak between categories + if (counter > 0) { + this._makeItem([]); } + // a header for the category + this._makeHeader(option); + + // get the suboptions + this._handleObject(this.configureOptions[option], [option]); } + counter++; } - _bound[type][_keys[key].code] = newBindings; - } - else { - _bound[type][_keys[key].code] = []; } - }; - // reset all bound variables. - _exportFunctions.reset = function() { - _bound = {keydown:{}, keyup:{}}; - }; + if (this.options.showButton === true) { + (function () { + var generateButton = document.createElement('div'); + generateButton.className = 'vis-network-configuration button'; + generateButton.innerHTML = 'generate options'; + generateButton.onclick = function () { + _this._printOptions(); + }; + generateButton.onmouseover = function () { + generateButton.className = 'vis-network-configuration button hover'; + }; + generateButton.onmouseout = function () { + generateButton.className = 'vis-network-configuration button'; + }; - // unbind all listeners and reset all variables. - _exportFunctions.destroy = function() { - _bound = {keydown:{}, keyup:{}}; - container.removeEventListener('keydown', down, true); - container.removeEventListener('keyup', up, true); - }; + _this.optionsContainer = document.createElement('div'); + _this.optionsContainer.className = 'vis-network-configuration vis-option-container'; - // create listeners. - container.addEventListener('keydown',down,true); - container.addEventListener('keyup',up,true); + _this.domElements.push(_this.optionsContainer); + _this.domElements.push(generateButton); + })(); + } - // return the public functions. - return _exportFunctions; - } + this._push(); + this.colorPicker.insertTo(this.container); + } + }, { + key: '_push', - return keycharm; - })); + /** + * draw all DOM elements on the screen + * @private + */ + value: function _push() { + this.wrapper = document.createElement('div'); + this.wrapper.className = 'vis-network-configuration-wrapper'; + this.container.appendChild(this.wrapper); + for (var i = 0; i < this.domElements.length; i++) { + this.wrapper.appendChild(this.domElements[i]); + } + } + }, { + key: '_clean', + + /** + * delete all DOM elements + * @private + */ + value: function _clean() { + for (var i = 0; i < this.domElements.length; i++) { + this.wrapper.removeChild(this.domElements[i]); + } + if (this.wrapper !== undefined) { + this.container.removeChild(this.wrapper); + this.wrapper = undefined; + } + this.domElements = []; + } + }, { + key: '_getValue', + /** + * get the value from the actualOptions if it exists + * @param {array} path | where to look for the actual option + * @returns {*} + * @private + */ + value: function _getValue(path) { + var base = this.moduleOptions; + for (var i = 0; i < path.length; i++) { + if (base[path[i]] !== undefined) { + base = base[path[i]]; + } else { + base = undefined; + break; + } + } + return base; + } + }, { + key: '_makeItem', + /** + * all option elements are wrapped in an item + * @param path + * @param domElements + * @private + */ + value: function _makeItem(path) { + var _this2 = this; -/***/ }, -/* 48 */ -/***/ function(module, exports, __webpack_require__) { + for (var _len = arguments.length, domElements = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { + domElements[_key - 1] = arguments[_key]; + } - 'use strict'; + if (this.allowCreation === true) { + (function () { + var item = document.createElement('div'); + item.className = 'vis-network-configuration item s' + path.length; + domElements.forEach(function (element) { + item.appendChild(element); + }); + _this2.domElements.push(item); + })(); + } + } + }, { + key: '_makeHeader', - var Hammer = __webpack_require__(27); - var util = __webpack_require__(3); - var Component = __webpack_require__(25); - var moment = __webpack_require__(7); - var locales = __webpack_require__(26); + /** + * header for major subjects + * @param name + * @private + */ + value: function _makeHeader(name) { + var div = document.createElement('div'); + div.className = 'vis-network-configuration header'; + div.innerHTML = name; + this._makeItem([], div); + } + }, { + key: '_makeLabel', - /** - * A custom time bar - * @param {{range: Range, dom: Object}} body - * @param {Object} [options] Available parameters: - * {number | string} id - * {string} locales - * {string} locale - * @constructor CustomTime - * @extends Component - */ + /** + * make a label, if it is an object label, it gets different styling. + * @param name + * @param path + * @param objectLabel + * @returns {HTMLElement} + * @private + */ + value: function _makeLabel(name, path) { + var objectLabel = arguments[2] === undefined ? false : arguments[2]; - function CustomTime(body, options) { - this.body = body; + var div = document.createElement('div'); + div.className = 'vis-network-configuration label s' + path.length; + if (objectLabel === true) { + div.innerHTML = '' + name + ':'; + } else { + div.innerHTML = name + ':'; + } + return div; + } + }, { + key: '_makeDropdown', + + /** + * make a dropdown list for multiple possible string optoins + * @param arr + * @param value + * @param path + * @private + */ + value: function _makeDropdown(arr, value, path) { + var select = document.createElement('select'); + select.className = 'vis-network-configuration select'; + var selectedValue = 0; + if (value !== undefined) { + if (arr.indexOf(value) !== -1) { + selectedValue = arr.indexOf(value); + } + } - // default options - this.defaultOptions = { - locales: locales, - locale: 'en', - id: undefined - }; - this.options = util.extend({}, this.defaultOptions); + for (var i = 0; i < arr.length; i++) { + var option = document.createElement('option'); + option.value = arr[i]; + if (i === selectedValue) { + option.selected = 'selected'; + } + option.innerHTML = arr[i]; + select.appendChild(option); + } - if (options && options.time) { - this.customTime = options.time; - } else { - this.customTime = new Date(); - } + var me = this; + select.onchange = function () { + me._update(this.value, path); + }; - this.eventParams = {}; // stores state parameters while dragging the bar + var label = this._makeLabel(path[path.length - 1], path); + this._makeItem(path, label, select); + } + }, { + key: '_makeRange', - this.setOptions(options); + /** + * make a range object for numeric options + * @param arr + * @param value + * @param path + * @private + */ + value: function _makeRange(arr, value, path) { + var defaultValue = arr[0]; + var min = arr[1]; + var max = arr[2]; + var step = arr[3]; + var range = document.createElement('input'); + range.type = 'range'; + range.className = 'vis-network-configuration range'; + range.min = min; + range.max = max; + range.step = step; - // create the DOM - this._create(); - } + if (value !== undefined) { + if (value < 0 && value * 2 < min) { + range.min = value * 2; + } else if (value * 0.1 < min) { + range.min = value / 10; + } + if (value * 2 > max && max !== 1) { + range.max = value * 2; + } + range.value = value; + } else { + range.value = defaultValue; + } - CustomTime.prototype = new Component(); + var input = document.createElement('input'); + input.className = 'vis-network-configuration rangeinput'; + input.value = range.value; - /** - * Set options for the component. Options will be merged in current options. - * @param {Object} options Available parameters: - * {number | string} id - * {string} locales - * {string} locale - */ - CustomTime.prototype.setOptions = function (options) { - if (options) { - // copy all options that we know - util.selectiveExtend(['locale', 'locales', 'id'], this.options, options); - } - }; + var me = this; + range.onchange = function () { + input.value = this.value;me._update(Number(this.value), path); + }; + range.oninput = function () { + input.value = this.value; + }; - /** - * Create the DOM for the custom time - * @private - */ - CustomTime.prototype._create = function () { - var bar = document.createElement('div'); - bar['custom-time'] = this; - bar.className = 'vis-custom-time ' + (this.options.id || ''); - bar.style.position = 'absolute'; - bar.style.top = '0px'; - bar.style.height = '100%'; - this.bar = bar; + var label = this._makeLabel(path[path.length - 1], path); + this._makeItem(path, label, range, input); + } + }, { + key: '_makeCheckbox', - var drag = document.createElement('div'); - drag.style.position = 'relative'; - drag.style.top = '0px'; - drag.style.left = '-10px'; - drag.style.height = '100%'; - drag.style.width = '20px'; - bar.appendChild(drag); + /** + * make a checkbox for boolean options. + * @param defaultValue + * @param value + * @param path + * @private + */ + value: function _makeCheckbox(defaultValue, value, path) { + var checkbox = document.createElement('input'); + checkbox.type = 'checkbox'; + checkbox.className = 'vis-network-configuration checkbox'; + checkbox.checked = defaultValue; + if (value !== undefined) { + checkbox.checked = value; + if (value !== defaultValue) { + if (typeof defaultValue === 'object') { + if (value !== defaultValue.enabled) { + this.changedOptions.push({ path: path, value: value }); + } + } else { + this.changedOptions.push({ path: path, value: value }); + } + } + } - // attach event listeners - this.hammer = new Hammer(drag); - this.hammer.on('panstart', this._onDragStart.bind(this)); - this.hammer.on('panmove', this._onDrag.bind(this)); - this.hammer.on('panend', this._onDragEnd.bind(this)); - // TODO: cleanup - //this.hammer.on('pan', function (event) { - // event.preventDefault(); - //}); - }; + var me = this; + checkbox.onchange = function () { + me._update(this.checked, path); + }; - /** - * Destroy the CustomTime bar - */ - CustomTime.prototype.destroy = function () { - this.hide(); + var label = this._makeLabel(path[path.length - 1], path); + this._makeItem(path, label, checkbox); + } + }, { + key: '_makeTextInput', - this.hammer.destroy(); - this.hammer = null; + /** + * make a text input field for string options. + * @param defaultValue + * @param value + * @param path + * @private + */ + value: function _makeTextInput(defaultValue, value, path) { + var checkbox = document.createElement('input'); + checkbox.type = 'text'; + checkbox.className = 'vis-network-configuration text'; + checkbox.value = value; + if (value !== defaultValue) { + this.changedOptions.push({ path: path, value: value }); + } - this.body = null; - }; + var me = this; + checkbox.onchange = function () { + me._update(this.value, path); + }; - /** - * Repaint the component - * @return {boolean} Returns true if the component is resized - */ - CustomTime.prototype.redraw = function () { - var parent = this.body.dom.backgroundVertical; - if (this.bar.parentNode != parent) { - // attach to the dom - if (this.bar.parentNode) { - this.bar.parentNode.removeChild(this.bar); + var label = this._makeLabel(path[path.length - 1], path); + this._makeItem(path, label, checkbox); } - parent.appendChild(this.bar); - } + }, { + key: '_makeColorField', - var x = this.body.util.toScreen(this.customTime); + /** + * make a color field with a color picker for color fields + * @param arr + * @param value + * @param path + * @private + */ + value: function _makeColorField(arr, value, path) { + var _this3 = this; - var locale = this.options.locales[this.options.locale]; - if (!locale) { - if (!this.warned) { - console.log('WARNING: options.locales[\'' + this.options.locale + '\'] not found. See http://visjs.org/docs/timeline.html#Localization'); - this.warned = true; - } - locale = this.options.locales['en']; // fall back on english when not available - } - var title = locale.time + ': ' + moment(this.customTime).format('dddd, MMMM Do YYYY, H:mm:ss'); - title = title.charAt(0).toUpperCase() + title.substring(1); + var defaultColor = arr[1]; + var div = document.createElement('div'); + value = value === undefined ? defaultColor : value; - this.bar.style.left = x + 'px'; - this.bar.title = title; + if (value !== 'none') { + div.className = 'vis-network-configuration colorBlock'; + div.style.backgroundColor = value; + } else { + div.className = 'vis-network-configuration colorBlock none'; + } - return false; - }; + value = value === undefined ? defaultColor : value; + div.onclick = function () { + _this3._showColorPicker(value, div, path); + }; - /** - * Remove the CustomTime from the DOM - */ - CustomTime.prototype.hide = function () { - // remove the line from the DOM - if (this.bar.parentNode) { - this.bar.parentNode.removeChild(this.bar); - } - }; + var label = this._makeLabel(path[path.length - 1], path); + this._makeItem(path, label, div); + } + }, { + key: '_showColorPicker', - /** - * Set custom time. - * @param {Date | number | string} time - */ - CustomTime.prototype.setCustomTime = function (time) { - this.customTime = util.convert(time, 'Date'); - this.redraw(); - }; + /** + * used by the color buttons to call the color picker. + * @param event + * @param value + * @param div + * @param path + * @private + */ + value: function _showColorPicker(value, div, path) { + var _this4 = this; - /** - * Retrieve the current custom time. - * @return {Date} customTime - */ - CustomTime.prototype.getCustomTime = function () { - return new Date(this.customTime.valueOf()); - }; + var rect = div.getBoundingClientRect(); + var bodyRect = document.body.getBoundingClientRect(); + var pickerX = rect.left + rect.width + 5; + var pickerY = rect.top - bodyRect.top + rect.height * 0.5; + this.colorPicker.show(pickerX, pickerY); + this.colorPicker.setColor(value); + this.colorPicker.setCallback(function (color) { + var colorString = 'rgba(' + color.r + ',' + color.g + ',' + color.b + ',' + color.a + ')'; + div.style.backgroundColor = colorString; + _this4._update(colorString, path); + }); + } + }, { + key: '_handleObject', - /** - * Start moving horizontally - * @param {Event} event - * @private - */ - CustomTime.prototype._onDragStart = function (event) { - this.eventParams.dragging = true; - this.eventParams.customTime = this.customTime; + /** + * parse an object and draw the correct items + * @param obj + * @param path + * @private + */ + value: function _handleObject(obj) { + var path = arguments[1] === undefined ? [] : arguments[1]; + var checkOnly = arguments[2] === undefined ? false : arguments[2]; - event.stopPropagation(); - }; + var show = false; + var filter = this.options.filter; + var visibleInSet = false; + for (var subObj in obj) { + if (obj.hasOwnProperty(subObj)) { + show = true; + var item = obj[subObj]; + var newPath = util.copyAndExtendArray(path, subObj); + if (typeof filter === 'function') { + show = filter(subObj, path); - /** - * Perform moving operating. - * @param {Event} event - * @private - */ - CustomTime.prototype._onDrag = function (event) { - if (!this.eventParams.dragging) return; + // if needed we must go deeper into the object. + if (show === false) { + if (!(item instanceof Array) && typeof item !== 'string' && typeof item !== 'boolean' && item instanceof Object) { + this.allowCreation = false; + show = this._handleObject(item, newPath, true); + this.allowCreation = checkOnly === false; + } + } + } - var x = this.body.util.toScreen(this.eventParams.customTime) + event.deltaX; - var time = this.body.util.toTime(x); + if (show !== false) { + visibleInSet = true; + var value = this._getValue(newPath); - this.setCustomTime(time); + if (item instanceof Array) { + this._handleArray(item, value, newPath); + } else if (typeof item === 'string') { + this._makeTextInput(item, value, newPath); + } else if (typeof item === 'boolean') { + this._makeCheckbox(item, value, newPath); + } else if (item instanceof Object) { + // collapse the physics options that are not enabled + var draw = true; + if (path.indexOf('physics') !== -1) { + if (this.moduleOptions.physics.solver !== subObj) { + draw = false; + } + } - // fire a timechange event - this.body.emitter.emit('timechange', { - id: this.options.id, - time: new Date(this.customTime.valueOf()) - }); + if (draw === true) { + // initially collapse options with an disabled enabled option. + if (item.enabled !== undefined) { + var enabledPath = util.copyAndExtendArray(newPath, 'enabled'); + var enabledValue = this._getValue(enabledPath); + if (enabledValue === true) { + var label = this._makeLabel(subObj, newPath, true); + this._makeItem(newPath, label); + visibleInSet = this._handleObject(item, newPath) || visibleInSet; + } else { + this._makeCheckbox(item, enabledValue, newPath); + } + } else { + var label = this._makeLabel(subObj, newPath, true); + this._makeItem(newPath, label); + visibleInSet = this._handleObject(item, newPath) || visibleInSet; + } + } + } else { + console.error('dont know how to handle', item, subObj, newPath); + } + } + } + } + return visibleInSet; + } + }, { + key: '_handleArray', - event.stopPropagation(); - }; + /** + * handle the array type of option + * @param optionName + * @param arr + * @param value + * @param path + * @private + */ + value: function _handleArray(arr, value, path) { + if (typeof arr[0] === 'string' && arr[0] === 'color') { + this._makeColorField(arr, value, path); + if (arr[1] !== value) { + this.changedOptions.push({ path: path, value: value }); + } + } else if (typeof arr[0] === 'string') { + this._makeDropdown(arr, value, path); + if (arr[0] !== value) { + this.changedOptions.push({ path: path, value: value }); + } + } else if (typeof arr[0] === 'number') { + this._makeRange(arr, value, path); + if (arr[0] !== value) { + this.changedOptions.push({ path: path, value: Number(value) }); + } + } + } + }, { + key: '_update', - /** - * Stop moving operating. - * @param {Event} event - * @private - */ - CustomTime.prototype._onDragEnd = function (event) { - if (!this.eventParams.dragging) return; + /** + * called to update the network with the new settings. + * @param value + * @param path + * @private + */ + value: function _update(value, path) { + var options = this._constructOptions(value, path); + this.parent.setOptions(options); + } + }, { + key: '_constructOptions', + value: function _constructOptions(value, path) { + var optionsObj = arguments[2] === undefined ? {} : arguments[2]; - // fire a timechanged event - this.body.emitter.emit('timechanged', { - id: this.options.id, - time: new Date(this.customTime.valueOf()) - }); + var pointer = optionsObj; - event.stopPropagation(); - }; + // when dropdown boxes can be string or boolean, we typecast it into correct types + value = value === 'true' ? true : value; + value = value === 'false' ? false : value; - /** - * Find a custom time from an event target: - * searches for the attribute 'custom-time' in the event target's element tree - * @param {Event} event - * @return {CustomTime | null} customTime - */ - CustomTime.customTimeFromTarget = function (event) { - var target = event.target; - while (target) { - if (target.hasOwnProperty('custom-time')) { - return target['custom-time']; + for (var i = 0; i < path.length; i++) { + if (path[i] !== 'global') { + if (pointer[path[i]] === undefined) { + pointer[path[i]] = {}; + } + if (i !== path.length - 1) { + pointer = pointer[path[i]]; + } else { + pointer[path[i]] = value; + } + } + } + return optionsObj; } - target = target.parentNode; - } + }, { + key: '_printOptions', + value: function _printOptions() { + var options = {}; + for (var i = 0; i < this.changedOptions.length; i++) { + this._constructOptions(this.changedOptions[i].value, this.changedOptions[i].path, options); + } + this.optionsContainer.innerHTML = '
var options = ' + JSON.stringify(options, null, 2) + '
'; + } + }]); - return null; - }; + return Configurator; + })(); - module.exports = CustomTime; + exports['default'] = Configurator; + module.exports = exports['default']; /***/ }, -/* 49 */ +/* 47 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; @@ -22952,8 +22219,8 @@ return /******/ (function(modules) { // webpackBootstrap function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } - var Hammer = __webpack_require__(27); - var hammerUtil = __webpack_require__(32); + var Hammer = __webpack_require__(24); + var hammerUtil = __webpack_require__(29); var util = __webpack_require__(3); var ColorPicker = (function () { @@ -23519,7 +22786,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = exports['default']; /***/ }, -/* 50 */ +/* 48 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; @@ -23838,7 +23105,7 @@ return /******/ (function(modules) { // webpackBootstrap // item is a function, which is allowed /***/ }, -/* 51 */ +/* 49 */ /***/ function(module, exports, __webpack_require__) { /** @@ -24055,28 +23322,28 @@ return /******/ (function(modules) { // webpackBootstrap exports.configureOptions = configureOptions; /***/ }, -/* 52 */ +/* 50 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; - var Emitter = __webpack_require__(17); - var Hammer = __webpack_require__(27); + var Emitter = __webpack_require__(14); + var Hammer = __webpack_require__(24); var util = __webpack_require__(3); - var DataSet = __webpack_require__(12); - var DataView = __webpack_require__(14); - var Range = __webpack_require__(31); - var Core = __webpack_require__(34); - var TimeAxis = __webpack_require__(45); - var CurrentTime = __webpack_require__(24); - var CustomTime = __webpack_require__(48); - var LineGraph = __webpack_require__(53); - - var Configurator = __webpack_require__(2); - var Validator = __webpack_require__(50)['default']; - var printStyle = __webpack_require__(50).printStyle; - var allOptions = __webpack_require__(61).allOptions; - var configureOptions = __webpack_require__(61).configureOptions; + var DataSet = __webpack_require__(9); + var DataView = __webpack_require__(11); + var Range = __webpack_require__(28); + var Core = __webpack_require__(31); + var TimeAxis = __webpack_require__(42); + var CurrentTime = __webpack_require__(21); + var CustomTime = __webpack_require__(45); + var LineGraph = __webpack_require__(51); + + var Configurator = __webpack_require__(46); + var Validator = __webpack_require__(48)['default']; + var printStyle = __webpack_require__(48).printStyle; + var allOptions = __webpack_require__(59).allOptions; + var configureOptions = __webpack_require__(59).configureOptions; /** * Create a timeline visualization @@ -24385,21 +23652,21 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = Graph2d; /***/ }, -/* 53 */ +/* 51 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; var util = __webpack_require__(3); - var DOMutil = __webpack_require__(11); - var DataSet = __webpack_require__(12); - var DataView = __webpack_require__(14); - var Component = __webpack_require__(25); - var DataAxis = __webpack_require__(54); - var GraphGroup = __webpack_require__(56); - var Legend = __webpack_require__(60); - var BarFunctions = __webpack_require__(59); - var LineFunctions = __webpack_require__(57); + var DOMutil = __webpack_require__(8); + var DataSet = __webpack_require__(9); + var DataView = __webpack_require__(11); + var Component = __webpack_require__(22); + var DataAxis = __webpack_require__(52); + var GraphGroup = __webpack_require__(54); + var Legend = __webpack_require__(58); + var BarFunctions = __webpack_require__(57); + var LineFunctions = __webpack_require__(55); var UNGROUPED = '__ungrouped__'; // reserved group id for ungrouped items @@ -25361,15 +24628,15 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = LineGraph; /***/ }, -/* 54 */ +/* 52 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; var util = __webpack_require__(3); - var DOMutil = __webpack_require__(11); - var Component = __webpack_require__(25); - var DataStep = __webpack_require__(55); + var DOMutil = __webpack_require__(8); + var Component = __webpack_require__(22); + var DataStep = __webpack_require__(53); /** * A horizontal time axis @@ -25965,7 +25232,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = DataAxis; /***/ }, -/* 55 */ +/* 53 */ /***/ function(module, exports, __webpack_require__) { /** @@ -26192,16 +25459,16 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = DataStep; /***/ }, -/* 56 */ +/* 54 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; var util = __webpack_require__(3); - var DOMutil = __webpack_require__(11); - var Line = __webpack_require__(57); - var Bar = __webpack_require__(59); - var Points = __webpack_require__(58); + var DOMutil = __webpack_require__(8); + var Line = __webpack_require__(55); + var Bar = __webpack_require__(57); + var Points = __webpack_require__(56); /** * /** @@ -26386,13 +25653,13 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = GraphGroup; /***/ }, -/* 57 */ +/* 55 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; - var DOMutil = __webpack_require__(11); - var Points = __webpack_require__(58); + var DOMutil = __webpack_require__(8); + var Points = __webpack_require__(56); function Line(groupId, options) { this.groupId = groupId; @@ -26681,12 +25948,12 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = Line; /***/ }, -/* 58 */ +/* 56 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; - var DOMutil = __webpack_require__(11); + var DOMutil = __webpack_require__(8); function Points(groupId, options) { this.groupId = groupId; @@ -26728,13 +25995,13 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = Points; /***/ }, -/* 59 */ +/* 57 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; - var DOMutil = __webpack_require__(11); - var Points = __webpack_require__(58); + var DOMutil = __webpack_require__(8); + var Points = __webpack_require__(56); function Bargraph(groupId, options) { this.groupId = groupId; @@ -26976,14 +26243,14 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = Bargraph; /***/ }, -/* 60 */ +/* 58 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; var util = __webpack_require__(3); - var DOMutil = __webpack_require__(11); - var Component = __webpack_require__(25); + var DOMutil = __webpack_require__(8); + var Component = __webpack_require__(22); /** * Legend for Graph2d @@ -27190,7 +26457,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = Legend; /***/ }, -/* 61 */ +/* 59 */ /***/ function(module, exports, __webpack_require__) { /** @@ -27356,112 +26623,718 @@ return /******/ (function(modules) { // webpackBootstrap __type__: { object: object } }; - var configureOptions = { - global: { - //yAxisOrientation: ['left','right'], // TDOO: enable as soon as Grahp2d doesn't crash when changing this on the fly - sort: true, - sampling: true, - stack: false, - shaded: { - enabled: false, - orientation: ['top', 'bottom'] // top, bottom - }, - style: ['line', 'bar', 'points'], // line, bar - barChart: { - width: [50, 5, 100, 5], - sideBySide: false, - align: ['left', 'center', 'right'] // left, center, right - }, - interpolation: { - enabled: true, - parametrization: ['centripetal', 'chordal', 'uniform'] // uniform (alpha = 0.0), chordal (alpha = 1.0), centripetal (alpha = 0.5) - }, - drawPoints: { - enabled: true, - size: [6, 2, 30, 1], - style: ['square', 'circle'] // square, circle - }, - dataAxis: { - showMinorLabels: true, - showMajorLabels: true, - icons: false, - width: [40, 0, 200, 1], - visible: true, - alignZeros: true, - left: { - //range: {min:undefined,max:undefined}, - //format: function (value) {return value;}, - title: { text: '', style: '' } - }, - right: { - //range: {min:undefined,max:undefined}, - //format: function (value) {return value;}, - title: { text: '', style: '' } - } - }, - legend: { - enabled: false, - icons: true, - left: { - visible: true, - position: ['top-right', 'bottom-right', 'top-left', 'bottom-left'] // top/bottom - left,right - }, - right: { - visible: true, - position: ['top-right', 'bottom-right', 'top-left', 'bottom-left'] // top/bottom - left,right + var configureOptions = { + global: { + //yAxisOrientation: ['left','right'], // TDOO: enable as soon as Grahp2d doesn't crash when changing this on the fly + sort: true, + sampling: true, + stack: false, + shaded: { + enabled: false, + orientation: ['top', 'bottom'] // top, bottom + }, + style: ['line', 'bar', 'points'], // line, bar + barChart: { + width: [50, 5, 100, 5], + sideBySide: false, + align: ['left', 'center', 'right'] // left, center, right + }, + interpolation: { + enabled: true, + parametrization: ['centripetal', 'chordal', 'uniform'] // uniform (alpha = 0.0), chordal (alpha = 1.0), centripetal (alpha = 0.5) + }, + drawPoints: { + enabled: true, + size: [6, 2, 30, 1], + style: ['square', 'circle'] // square, circle + }, + dataAxis: { + showMinorLabels: true, + showMajorLabels: true, + icons: false, + width: [40, 0, 200, 1], + visible: true, + alignZeros: true, + left: { + //range: {min:undefined,max:undefined}, + //format: function (value) {return value;}, + title: { text: '', style: '' } + }, + right: { + //range: {min:undefined,max:undefined}, + //format: function (value) {return value;}, + title: { text: '', style: '' } + } + }, + legend: { + enabled: false, + icons: true, + left: { + visible: true, + position: ['top-right', 'bottom-right', 'top-left', 'bottom-left'] // top/bottom - left,right + }, + right: { + visible: true, + position: ['top-right', 'bottom-right', 'top-left', 'bottom-left'] // top/bottom - left,right + } + }, + + autoResize: true, + clickToUse: false, + end: '', + 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: '' + } + }, + + height: '', + locale: '', + max: '', + maxHeight: '', + min: '', + minHeight: '', + moveable: true, + orientation: ['both', 'bottom', 'top'], + showCurrentTime: false, + showMajorLabels: true, + showMinorLabels: true, + start: '', + width: '100%', + zoomable: true, + zoomMax: [315360000000000, 10, 315360000000000, 1], + zoomMin: [10, 10, 315360000000000, 1] + } + }; + + exports.allOptions = allOptions; + exports.configureOptions = configureOptions; + +/***/ }, +/* 60 */ +/***/ function(module, exports, __webpack_require__) { + + // Load custom shapes into CanvasRenderingContext2D + 'use strict'; + + function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } + + var _modulesGroups = __webpack_require__(61); + + var _modulesGroups2 = _interopRequireDefault(_modulesGroups); + + var _modulesNodesHandler = __webpack_require__(62); + + var _modulesNodesHandler2 = _interopRequireDefault(_modulesNodesHandler); + + var _modulesEdgesHandler = __webpack_require__(82); + + var _modulesEdgesHandler2 = _interopRequireDefault(_modulesEdgesHandler); + + var _modulesPhysicsEngine = __webpack_require__(2); + + var _modulesPhysicsEngine2 = _interopRequireDefault(_modulesPhysicsEngine); + + var _modulesClustering = __webpack_require__(97); + + var _modulesClustering2 = _interopRequireDefault(_modulesClustering); + + var _modulesCanvasRenderer = __webpack_require__(99); + + var _modulesCanvasRenderer2 = _interopRequireDefault(_modulesCanvasRenderer); + + var _modulesCanvas = __webpack_require__(100); + + var _modulesCanvas2 = _interopRequireDefault(_modulesCanvas); + + var _modulesView = __webpack_require__(101); + + var _modulesView2 = _interopRequireDefault(_modulesView); + + var _modulesInteractionHandler = __webpack_require__(102); + + var _modulesInteractionHandler2 = _interopRequireDefault(_modulesInteractionHandler); + + var _modulesSelectionHandler = __webpack_require__(105); + + var _modulesSelectionHandler2 = _interopRequireDefault(_modulesSelectionHandler); + + var _modulesLayoutEngine = __webpack_require__(106); + + var _modulesLayoutEngine2 = _interopRequireDefault(_modulesLayoutEngine); + + var _modulesManipulationSystem = __webpack_require__(107); + + var _modulesManipulationSystem2 = _interopRequireDefault(_modulesManipulationSystem); + + var _sharedConfigurator = __webpack_require__(46); + + var _sharedConfigurator2 = _interopRequireDefault(_sharedConfigurator); + + var _sharedValidator = __webpack_require__(48); + + var _sharedValidator2 = _interopRequireDefault(_sharedValidator); + + var _optionsJs = __webpack_require__(108); + + __webpack_require__(109); + + var Emitter = __webpack_require__(14); + var Hammer = __webpack_require__(24); + var util = __webpack_require__(3); + var DataSet = __webpack_require__(9); + var DataView = __webpack_require__(11); + var dotparser = __webpack_require__(110); + var gephiParser = __webpack_require__(111); + var Images = __webpack_require__(112); + var Activator = __webpack_require__(43); + var locales = __webpack_require__(113); + + /** + * @constructor Network + * Create a network visualization, displaying nodes and edges. + * + * @param {Element} container The DOM element in which the Network will + * be created. Normally a div element. + * @param {Object} data An object containing parameters + * {Array} nodes + * {Array} edges + * @param {Object} options Options + */ + function Network(container, data, options) { + var _this = this; + + if (!(this instanceof Network)) { + throw new SyntaxError('Constructor must be called with the new operator'); + } + + // set constant values + this.options = {}; + this.defaultOptions = { + locale: 'en', + locales: locales, + clickToUse: false + }; + util.extend(this.options, this.defaultOptions); + + // containers for nodes and edges + this.body = { + container: container, + nodes: {}, + nodeIndices: [], + edges: {}, + edgeIndices: [], + emitter: { + on: this.on.bind(this), + off: this.off.bind(this), + emit: this.emit.bind(this), + once: this.once.bind(this) + }, + eventListeners: { + onTap: function onTap() {}, + onTouch: function onTouch() {}, + onDoubleTap: function onDoubleTap() {}, + onHold: function onHold() {}, + onDragStart: function onDragStart() {}, + onDrag: function onDrag() {}, + onDragEnd: function onDragEnd() {}, + onMouseWheel: function onMouseWheel() {}, + onPinch: function onPinch() {}, + onMouseMove: function onMouseMove() {}, + onRelease: function onRelease() {}, + onContext: function onContext() {} + }, + data: { + nodes: null, // A DataSet or DataView + edges: null // A DataSet or DataView + }, + functions: { + createNode: function createNode() {}, + createEdge: function createEdge() {}, + getPointer: function getPointer() {} + }, + view: { + scale: 1, + translation: { x: 0, y: 0 } + } + }; + + // bind the event listeners + this.bindEventListeners(); + + // setting up all modules + this.images = new Images(function () { + 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 + this.selectionHandler = new _modulesSelectionHandler2['default'](this.body, this.canvas); // Selection handler + this.interactionHandler = new _modulesInteractionHandler2['default'](this.body, this.canvas, this.selectionHandler); // Interaction handler handles all the hammer bindings (that are bound by canvas), key + this.view = new _modulesView2['default'](this.body, this.canvas); // camera handler, does animations and zooms + this.renderer = new _modulesCanvasRenderer2['default'](this.body, this.canvas); // renderer, starts renderloop, has events that modules can hook into + this.physics = new _modulesPhysicsEngine2['default'](this.body); // physics engine, does all the simulations + this.layoutEngine = new _modulesLayoutEngine2['default'](this.body); // layout engine for inital layout and hierarchical layout + this.clustering = new _modulesClustering2['default'](this.body); // clustering api + this.manipulation = new _modulesManipulationSystem2['default'](this.body, this.canvas, this.selectionHandler); // data manipulation system + + 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 + + // create the DOM elements + this.canvas._create(); + + // setup configuration system + this.configurator = new _sharedConfigurator2['default'](this, this.body.container, _optionsJs.configureOptions, this.canvas.pixelRatio); + + // apply options + this.setOptions(options); + + // load data (the disable start variable will be the same as the enabled clustering) + this.setData(data); + } + + // Extend Network with an Emitter mixin + Emitter(Network.prototype); + + /** + * Set options + * @param {Object} options + */ + Network.prototype.setOptions = function (options) { + var _this2 = this; + + if (options !== undefined) { + + var errorFound = _sharedValidator2['default'].validate(options, _optionsJs.allOptions); + if (errorFound === true) { + console.log('%cErrors have been found in the supplied options object.', _sharedValidator.printStyle); + } + + // copy the global fields over + var fields = ['locale', 'locales', 'clickToUse']; + util.selectiveDeepExtend(fields, this.options, options); + + // the hierarchical system can adapt the edges and the physics to it's own options because not all combinations work with the hierarichical system. + options = this.layoutEngine.setOptions(options.layout, options); + + this.canvas.setOptions(options); // options for canvas are in globals + + // pass the options to the modules + this.groups.setOptions(options.groups); + this.nodesHandler.setOptions(options.nodes); + this.edgesHandler.setOptions(options.edges); + this.physics.setOptions(options.physics); + this.manipulation.setOptions(options.manipulation, options, this.options); // manipulation uses the locales in the globals + + this.interactionHandler.setOptions(options.interaction); + this.renderer.setOptions(options.interaction); // options for rendering are in interaction + this.selectionHandler.setOptions(options.interaction); // options for selection are in interaction + + // reload the settings of the nodes to apply changes in groups that are not referenced by pointer. + if (options.groups !== undefined) { + this.body.emitter.emit('refreshNodes'); + } + // these two do not have options at the moment, here for completeness + //this.view.setOptions(options.view); + //this.clustering.setOptions(options.clustering); + + this.configurator.setOptions(options.configure); + + // if the configuration system is enabled, copy all options and put them into the config system + if (this.configurator.options.enabled === true) { + var networkOptions = { nodes: {}, edges: {}, layout: {}, interaction: {}, manipulation: {}, physics: {}, global: {} }; + util.deepExtend(networkOptions.nodes, this.nodesHandler.options); + util.deepExtend(networkOptions.edges, this.edgesHandler.options); + util.deepExtend(networkOptions.layout, this.layoutEngine.options); + // load the selectionHandler and rendere default options in to the interaction group + util.deepExtend(networkOptions.interaction, this.selectionHandler.options); + util.deepExtend(networkOptions.interaction, this.renderer.options); + + util.deepExtend(networkOptions.interaction, this.interactionHandler.options); + util.deepExtend(networkOptions.manipulation, this.manipulation.options); + util.deepExtend(networkOptions.physics, this.physics.options); + + // load globals into the global object + util.deepExtend(networkOptions.global, this.canvas.options); + util.deepExtend(networkOptions.global, this.options); + + this.configurator.setModuleOptions(networkOptions); + } + + // handle network global options + if (options.clickToUse !== undefined) { + if (options.clickToUse === true) { + if (this.activator === undefined) { + this.activator = new Activator(this.canvas.frame); + this.activator.on('change', function () { + _this2.body.emitter.emit('activate'); + }); + } + } else { + if (this.activator !== undefined) { + this.activator.destroy(); + delete this.activator; + } + this.body.emitter.emit('activate'); + } + } else { + this.body.emitter.emit('activate'); + } + + this.canvas.setSize(); + // start the physics simulation. Can be safely called multiple times. + this.body.emitter.emit('startSimulation'); + } + }; + + /** + * Update the this.body.nodeIndices with the most recent node index list + * @private + */ + Network.prototype._updateVisibleIndices = function () { + var nodes = this.body.nodes; + var edges = this.body.edges; + this.body.nodeIndices = []; + this.body.edgeIndices = []; + + for (var nodeId in nodes) { + if (nodes.hasOwnProperty(nodeId)) { + if (nodes[nodeId].options.hidden === false) { + this.body.nodeIndices.push(nodeId); + } + } + } + + for (var edgeId in edges) { + if (edges.hasOwnProperty(edgeId)) { + if (edges[edgeId].options.hidden === false) { + this.body.edgeIndices.push(edgeId); + } + } + } + }; + + /** + * Bind all events + */ + Network.prototype.bindEventListeners = function () { + 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 () { + // update shortcut lists + _this3._updateVisibleIndices(); + _this3.physics.updatePhysicsData(); + + // call the dataUpdated event because the only difference between the two is the updating of the indices + _this3.body.emitter.emit('_dataUpdated'); + }); + + // this is called when options of EXISTING nodes or edges have changed. + 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'); + }); + }; + + /** + * Set nodes and edges, and optionally options as well. + * + * @param {Object} data Object containing parameters: + * {Array | DataSet | DataView} [nodes] Array with nodes + * {Array | DataSet | DataView} [edges] Array with edges + * {String} [dot] String containing data in DOT format + * {String} [gephi] String containing data in gephi JSON format + * {Options} [options] Object with options + */ + Network.prototype.setData = function (data) { + // reset the physics engine. + 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(); + + if (data && data.dot && (data.nodes || data.edges)) { + throw new SyntaxError('Data must contain either parameter "dot" or ' + ' parameter pair "nodes" and "edges", but not both.'); + } + + // set options + this.setOptions(data && data.options); + // set all data + if (data && data.dot) { + console.log('The dot property has been depricated. Please use the static convertDot method to convert DOT into vis.network format and use the normal data format with nodes and edges. This converter is used like this: var data = vis.network.convertDot(dotString);'); + // parse DOT file + var dotData = dotparser.DOTToGraph(data.dot); + this.setData(dotData); + return; + } else if (data && data.gephi) { + // parse DOT file + console.log('The gephi property has been depricated. Please use the static convertGephi method to convert gephi into vis.network format and use the normal data format with nodes and edges. This converter is used like this: var data = vis.network.convertGephi(gephiJson);'); + var gephiData = gephiParser.parseGephi(data.gephi); + this.setData(gephiData); + return; + } else { + this.nodesHandler.setData(data && data.nodes, true); + this.edgesHandler.setData(data && data.edges, true); + } + + // emit change in data + this.body.emitter.emit('_dataChanged'); + + // find a stable position or start animating to a stable position + this.body.emitter.emit('initPhysics'); + }; + + /** + * Cleans up all bindings of the network, removing it fully from the memory IF the variable is set to null after calling this function. + * var network = new vis.Network(..); + * network.destroy(); + * network = null; + */ + Network.prototype.destroy = function () { + this.body.emitter.emit('destroy'); + // clear events + this.body.emitter.off(); + this.off(); + + // delete modules + delete this.groups; + delete this.canvas; + delete this.selectionHandler; + delete this.interactionHandler; + delete this.view; + delete this.renderer; + delete this.physics; + delete this.layoutEngine; + delete this.clustering; + delete this.manipulation; + delete this.nodesHandler; + delete this.edgesHandler; + delete this.configurator; + delete this.images; + + for (var nodeId in this.body.nodes) { + delete this.body.nodes[nodeId]; + } + for (var edgeId in this.body.edges) { + delete this.body.edges[edgeId]; + } + + // remove the container and everything inside it recursively + util.recursiveDOMDelete(this.body.container); + }; + + /** + * Update the values of all object in the given array according to the current + * value range of the objects in the array. + * @param {Object} obj An object containing a set of Edges or Nodes + * The objects must have a method getValue() and + * setValueRange(min, max). + * @private + */ + Network.prototype._updateValueRange = function (obj) { + var id; + + // determine the range of the objects + var valueMin = undefined; + var valueMax = undefined; + var valueTotal = 0; + for (id in obj) { + if (obj.hasOwnProperty(id)) { + var value = obj[id].getValue(); + if (value !== undefined) { + valueMin = valueMin === undefined ? value : Math.min(value, valueMin); + valueMax = valueMax === undefined ? value : Math.max(value, valueMax); + valueTotal += value; } - }, + } + } - autoResize: true, - clickToUse: false, - end: '', - 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: '' + // adjust the range of all objects + if (valueMin !== undefined && valueMax !== undefined) { + for (id in obj) { + if (obj.hasOwnProperty(id)) { + obj[id].setValueRange(valueMin, valueMax, valueTotal); } - }, + } + } + }; - height: '', - locale: '', - max: '', - maxHeight: '', - min: '', - minHeight: '', - moveable: true, - orientation: ['both', 'bottom', 'top'], - showCurrentTime: false, - showMajorLabels: true, - showMinorLabels: true, - start: '', - width: '100%', - zoomable: true, - zoomMax: [315360000000000, 10, 315360000000000, 1], - zoomMin: [10, 10, 315360000000000, 1] + /** + * Returns true when the Network is active. + * @returns {boolean} + */ + Network.prototype.isActive = function () { + return !this.activator || this.activator.active; + }; + + Network.prototype.setSize = function () { + return this.canvas.setSize.apply(this.canvas, arguments); + }; + Network.prototype.canvasToDOM = function () { + return this.canvas.canvasToDOM.apply(this.canvas, arguments); + }; + Network.prototype.DOMtoCanvas = function () { + return this.canvas.DOMtoCanvas(this.canvas, arguments); + }; + Network.prototype.findNode = function () { + return this.clustering.findNode.apply(this.clustering, arguments); + }; + Network.prototype.isCluster = function () { + return this.clustering.isCluster.apply(this.clustering, arguments); + }; + Network.prototype.openCluster = function () { + return this.clustering.openCluster.apply(this.clustering, arguments); + }; + Network.prototype.cluster = function () { + return this.clustering.cluster.apply(this.clustering, arguments); + }; + Network.prototype.getNodesInCluster = function () { + return this.clustering.getNodesInCluster.apply(this.clustering, arguments); + }; + Network.prototype.clusterByConnection = function () { + return this.clustering.clusterByConnection.apply(this.clustering, arguments); + }; + Network.prototype.clusterByHubsize = function () { + return this.clustering.clusterByHubsize.apply(this.clustering, arguments); + }; + Network.prototype.clusterOutliers = function () { + return this.clustering.clusterOutliers.apply(this.clustering, arguments); + }; + Network.prototype.getSeed = function () { + return this.layoutEngine.getSeed.apply(this.layoutEngine, arguments); + }; + Network.prototype.enableEditMode = function () { + return this.manipulation.enableEditMode.apply(this.manipulation, arguments); + }; + Network.prototype.disableEditMode = function () { + return this.manipulation.disableEditMode.apply(this.manipulation, arguments); + }; + Network.prototype.addNodeMode = function () { + return this.manipulation.addNodeMode.apply(this.manipulation, arguments); + }; + Network.prototype.editNode = function () { + return this.manipulation.editNode.apply(this.manipulation, arguments); + }; + Network.prototype.editNodeMode = function () { + console.log('Depricated: 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); + }; + Network.prototype.editEdgeMode = function () { + return this.manipulation.editEdgeMode.apply(this.manipulation, arguments); + }; + Network.prototype.deleteSelected = function () { + return this.manipulation.deleteSelected.apply(this.manipulation, arguments); + }; + Network.prototype.getPositions = function () { + return this.nodesHandler.getPositions.apply(this.nodesHandler, arguments); + }; + Network.prototype.storePositions = function () { + return this.nodesHandler.storePositions.apply(this.nodesHandler, arguments); + }; + Network.prototype.getBoundingBox = function () { + return this.nodesHandler.getBoundingBox.apply(this.nodesHandler, arguments); + }; + Network.prototype.getConnectedNodes = function (objectId) { + if (this.body.nodes[objectId] !== undefined) { + return this.nodesHandler.getConnectedNodes.apply(this.nodesHandler, arguments); + } else { + return this.edgesHandler.getConnectedNodes.apply(this.edgesHandler, arguments); + } + }; + Network.prototype.getConnectedEdges = function () { + return this.nodesHandler.getConnectedEdges.apply(this.nodesHandler, arguments); + }; + Network.prototype.startSimulation = function () { + return this.physics.startSimulation.apply(this.physics, arguments); + }; + Network.prototype.stopSimulation = function () { + return this.physics.stopSimulation.apply(this.physics, arguments); + }; + Network.prototype.stabilize = function () { + return this.physics.stabilize.apply(this.physics, arguments); + }; + Network.prototype.getSelection = function () { + return this.selectionHandler.getSelection.apply(this.selectionHandler, arguments); + }; + Network.prototype.getSelectedNodes = function () { + return this.selectionHandler.getSelectedNodes.apply(this.selectionHandler, arguments); + }; + Network.prototype.getSelectedEdges = function () { + return this.selectionHandler.getSelectedEdges.apply(this.selectionHandler, arguments); + }; + Network.prototype.getNodeAt = function () { + var node = this.selectionHandler.getNodeAt.apply(this.selectionHandler, arguments); + if (node !== undefined && node.id !== undefined) { + return node.id; + } + return node; + }; + Network.prototype.getEdgeAt = function () { + var edge = this.selectionHandler.getEdgeAt.apply(this.selectionHandler, arguments); + if (edge !== undefined && edge.id !== undefined) { + return edge.id; } + return edge; + }; + 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.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); + }; + Network.prototype.fit = function () { + return this.view.fit.apply(this.view, arguments); + }; + Network.prototype.moveTo = function () { + return this.view.moveTo.apply(this.view, arguments); + }; + Network.prototype.focus = function () { + return this.view.focus.apply(this.view, arguments); + }; + Network.prototype.releaseNode = function () { + return this.view.releaseNode.apply(this.view, arguments); }; - exports.allOptions = allOptions; - exports.configureOptions = configureOptions; + module.exports = Network; /***/ }, -/* 62 */ +/* 61 */ /***/ function(module, exports, __webpack_require__) { "use strict"; @@ -27603,7 +27476,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = exports["default"]; /***/ }, -/* 63 */ +/* 62 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; @@ -27618,17 +27491,17 @@ return /******/ (function(modules) { // webpackBootstrap function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } - var _componentsNode = __webpack_require__(64); + var _componentsNode = __webpack_require__(63); var _componentsNode2 = _interopRequireDefault(_componentsNode); - var _componentsSharedLabel = __webpack_require__(65); + var _componentsSharedLabel = __webpack_require__(64); var _componentsSharedLabel2 = _interopRequireDefault(_componentsSharedLabel); var util = __webpack_require__(3); - var DataSet = __webpack_require__(12); - var DataView = __webpack_require__(14); + var DataSet = __webpack_require__(9); + var DataView = __webpack_require__(11); var NodesHandler = (function () { function NodesHandler(body, images, groups, layoutEngine) { @@ -28081,7 +27954,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = exports['default']; /***/ }, -/* 64 */ +/* 63 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; @@ -28096,67 +27969,67 @@ return /******/ (function(modules) { // webpackBootstrap function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } - var _sharedLabel = __webpack_require__(65); + var _sharedLabel = __webpack_require__(64); var _sharedLabel2 = _interopRequireDefault(_sharedLabel); - var _nodesShapesBox = __webpack_require__(66); + var _nodesShapesBox = __webpack_require__(65); var _nodesShapesBox2 = _interopRequireDefault(_nodesShapesBox); - var _nodesShapesCircle = __webpack_require__(68); + var _nodesShapesCircle = __webpack_require__(67); var _nodesShapesCircle2 = _interopRequireDefault(_nodesShapesCircle); - var _nodesShapesCircularImage = __webpack_require__(70); + var _nodesShapesCircularImage = __webpack_require__(69); var _nodesShapesCircularImage2 = _interopRequireDefault(_nodesShapesCircularImage); - var _nodesShapesDatabase = __webpack_require__(71); + var _nodesShapesDatabase = __webpack_require__(70); var _nodesShapesDatabase2 = _interopRequireDefault(_nodesShapesDatabase); - var _nodesShapesDiamond = __webpack_require__(72); + var _nodesShapesDiamond = __webpack_require__(71); var _nodesShapesDiamond2 = _interopRequireDefault(_nodesShapesDiamond); - var _nodesShapesDot = __webpack_require__(74); + var _nodesShapesDot = __webpack_require__(73); var _nodesShapesDot2 = _interopRequireDefault(_nodesShapesDot); - var _nodesShapesEllipse = __webpack_require__(75); + var _nodesShapesEllipse = __webpack_require__(74); var _nodesShapesEllipse2 = _interopRequireDefault(_nodesShapesEllipse); - var _nodesShapesIcon = __webpack_require__(76); + var _nodesShapesIcon = __webpack_require__(75); var _nodesShapesIcon2 = _interopRequireDefault(_nodesShapesIcon); - var _nodesShapesImage = __webpack_require__(77); + var _nodesShapesImage = __webpack_require__(76); var _nodesShapesImage2 = _interopRequireDefault(_nodesShapesImage); - var _nodesShapesSquare = __webpack_require__(78); + var _nodesShapesSquare = __webpack_require__(77); var _nodesShapesSquare2 = _interopRequireDefault(_nodesShapesSquare); - var _nodesShapesStar = __webpack_require__(79); + var _nodesShapesStar = __webpack_require__(78); var _nodesShapesStar2 = _interopRequireDefault(_nodesShapesStar); - var _nodesShapesText = __webpack_require__(80); + var _nodesShapesText = __webpack_require__(79); var _nodesShapesText2 = _interopRequireDefault(_nodesShapesText); - var _nodesShapesTriangle = __webpack_require__(81); + var _nodesShapesTriangle = __webpack_require__(80); var _nodesShapesTriangle2 = _interopRequireDefault(_nodesShapesTriangle); - var _nodesShapesTriangleDown = __webpack_require__(82); + var _nodesShapesTriangleDown = __webpack_require__(81); var _nodesShapesTriangleDown2 = _interopRequireDefault(_nodesShapesTriangleDown); - var _sharedValidator = __webpack_require__(50); + var _sharedValidator = __webpack_require__(48); var _sharedValidator2 = _interopRequireDefault(_sharedValidator); @@ -28601,7 +28474,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = exports['default']; /***/ }, -/* 65 */ +/* 64 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; @@ -28917,7 +28790,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = exports['default']; /***/ }, -/* 66 */ +/* 65 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; @@ -28936,7 +28809,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 _utilNodeBase = __webpack_require__(67); + var _utilNodeBase = __webpack_require__(66); var _utilNodeBase2 = _interopRequireDefault(_utilNodeBase); @@ -29022,7 +28895,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = exports['default']; /***/ }, -/* 67 */ +/* 66 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; @@ -29090,7 +28963,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = exports['default']; /***/ }, -/* 68 */ +/* 67 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; @@ -29109,7 +28982,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 _utilCircleImageBase = __webpack_require__(69); + var _utilCircleImageBase = __webpack_require__(68); var _utilCircleImageBase2 = _interopRequireDefault(_utilCircleImageBase); @@ -29180,7 +29053,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = exports['default']; /***/ }, -/* 69 */ +/* 68 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; @@ -29199,7 +29072,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 _utilNodeBase = __webpack_require__(67); + var _utilNodeBase = __webpack_require__(66); var _utilNodeBase2 = _interopRequireDefault(_utilNodeBase); @@ -29329,7 +29202,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = exports['default']; /***/ }, -/* 70 */ +/* 69 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; @@ -29348,7 +29221,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 _utilCircleImageBase = __webpack_require__(69); + var _utilCircleImageBase = __webpack_require__(68); var _utilCircleImageBase2 = _interopRequireDefault(_utilCircleImageBase); @@ -29434,7 +29307,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = exports['default']; /***/ }, -/* 71 */ +/* 70 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; @@ -29453,7 +29326,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 _utilNodeBase = __webpack_require__(67); + var _utilNodeBase = __webpack_require__(66); var _utilNodeBase2 = _interopRequireDefault(_utilNodeBase); @@ -29539,7 +29412,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = exports['default']; /***/ }, -/* 72 */ +/* 71 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; @@ -29558,7 +29431,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 _utilShapeBase = __webpack_require__(73); + var _utilShapeBase = __webpack_require__(72); var _utilShapeBase2 = _interopRequireDefault(_utilShapeBase); @@ -29595,7 +29468,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = exports['default']; /***/ }, -/* 73 */ +/* 72 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; @@ -29614,7 +29487,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 _utilNodeBase = __webpack_require__(67); + var _utilNodeBase = __webpack_require__(66); var _utilNodeBase2 = _interopRequireDefault(_utilNodeBase); @@ -29694,7 +29567,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = exports['default']; /***/ }, -/* 74 */ +/* 73 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; @@ -29713,7 +29586,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 _utilShapeBase = __webpack_require__(73); + var _utilShapeBase = __webpack_require__(72); var _utilShapeBase2 = _interopRequireDefault(_utilShapeBase); @@ -29750,7 +29623,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = exports['default']; /***/ }, -/* 75 */ +/* 74 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; @@ -29769,7 +29642,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 _utilNodeBase = __webpack_require__(67); + var _utilNodeBase = __webpack_require__(66); var _utilNodeBase2 = _interopRequireDefault(_utilNodeBase); @@ -29857,7 +29730,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = exports['default']; /***/ }, -/* 76 */ +/* 75 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; @@ -29876,7 +29749,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 _utilNodeBase = __webpack_require__(67); + var _utilNodeBase = __webpack_require__(66); var _utilNodeBase2 = _interopRequireDefault(_utilNodeBase); @@ -29973,7 +29846,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = exports['default']; /***/ }, -/* 77 */ +/* 76 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; @@ -29992,7 +29865,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 _utilCircleImageBase = __webpack_require__(69); + var _utilCircleImageBase = __webpack_require__(68); var _utilCircleImageBase2 = _interopRequireDefault(_utilCircleImageBase); @@ -30060,7 +29933,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = exports['default']; /***/ }, -/* 78 */ +/* 77 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; @@ -30079,7 +29952,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 _utilShapeBase = __webpack_require__(73); + var _utilShapeBase = __webpack_require__(72); var _utilShapeBase2 = _interopRequireDefault(_utilShapeBase); @@ -30117,7 +29990,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = exports['default']; /***/ }, -/* 79 */ +/* 78 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; @@ -30136,7 +30009,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 _utilShapeBase = __webpack_require__(73); + var _utilShapeBase = __webpack_require__(72); var _utilShapeBase2 = _interopRequireDefault(_utilShapeBase); @@ -30173,7 +30046,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = exports['default']; /***/ }, -/* 80 */ +/* 79 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; @@ -30192,7 +30065,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 _utilNodeBase = __webpack_require__(67); + var _utilNodeBase = __webpack_require__(66); var _utilNodeBase2 = _interopRequireDefault(_utilNodeBase); @@ -30258,7 +30131,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = exports['default']; /***/ }, -/* 81 */ +/* 80 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; @@ -30277,7 +30150,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 _utilShapeBase = __webpack_require__(73); + var _utilShapeBase = __webpack_require__(72); var _utilShapeBase2 = _interopRequireDefault(_utilShapeBase); @@ -30314,7 +30187,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = exports['default']; /***/ }, -/* 82 */ +/* 81 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; @@ -30333,7 +30206,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 _utilShapeBase = __webpack_require__(73); + var _utilShapeBase = __webpack_require__(72); var _utilShapeBase2 = _interopRequireDefault(_utilShapeBase); @@ -30370,7 +30243,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = exports['default']; /***/ }, -/* 83 */ +/* 82 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; @@ -30385,17 +30258,17 @@ return /******/ (function(modules) { // webpackBootstrap function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } - var _componentsEdge = __webpack_require__(84); + var _componentsEdge = __webpack_require__(83); var _componentsEdge2 = _interopRequireDefault(_componentsEdge); - var _componentsSharedLabel = __webpack_require__(65); + var _componentsSharedLabel = __webpack_require__(64); var _componentsSharedLabel2 = _interopRequireDefault(_componentsSharedLabel); var util = __webpack_require__(3); - var DataSet = __webpack_require__(12); - var DataView = __webpack_require__(14); + var DataSet = __webpack_require__(9); + var DataView = __webpack_require__(11); var EdgesHandler = (function () { function EdgesHandler(body, images, groups) { @@ -30807,7 +30680,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = exports['default']; /***/ }, -/* 84 */ +/* 83 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; @@ -30822,19 +30695,19 @@ return /******/ (function(modules) { // webpackBootstrap function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } - var _sharedLabel = __webpack_require__(65); + var _sharedLabel = __webpack_require__(64); var _sharedLabel2 = _interopRequireDefault(_sharedLabel); - var _edgesBezierEdgeDynamic = __webpack_require__(85); + var _edgesBezierEdgeDynamic = __webpack_require__(84); var _edgesBezierEdgeDynamic2 = _interopRequireDefault(_edgesBezierEdgeDynamic); - var _edgesBezierEdgeStatic = __webpack_require__(88); + var _edgesBezierEdgeStatic = __webpack_require__(87); var _edgesBezierEdgeStatic2 = _interopRequireDefault(_edgesBezierEdgeStatic); - var _edgesStraightEdge = __webpack_require__(89); + var _edgesStraightEdge = __webpack_require__(88); var _edgesStraightEdge2 = _interopRequireDefault(_edgesStraightEdge); @@ -31371,7 +31244,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = exports['default']; /***/ }, -/* 85 */ +/* 84 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; @@ -31390,7 +31263,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__(86); + var _utilBezierEdgeBase = __webpack_require__(85); var _utilBezierEdgeBase2 = _interopRequireDefault(_utilBezierEdgeBase); @@ -31535,7 +31408,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = exports['default']; /***/ }, -/* 86 */ +/* 85 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; @@ -31554,7 +31427,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__(87); + var _EdgeBase2 = __webpack_require__(86); var _EdgeBase3 = _interopRequireDefault(_EdgeBase2); @@ -31682,7 +31555,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = exports['default']; /***/ }, -/* 87 */ +/* 86 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; @@ -32276,7 +32149,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = exports['default']; /***/ }, -/* 88 */ +/* 87 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; @@ -32295,7 +32168,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__(86); + var _utilBezierEdgeBase = __webpack_require__(85); var _utilBezierEdgeBase2 = _interopRequireDefault(_utilBezierEdgeBase); @@ -32535,7 +32408,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = exports['default']; /***/ }, -/* 89 */ +/* 88 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; @@ -32554,7 +32427,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__(87); + var _utilEdgeBase = __webpack_require__(86); var _utilEdgeBase2 = _interopRequireDefault(_utilEdgeBase); @@ -32640,7 +32513,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = exports['default']; /***/ }, -/* 90 */ +/* 89 */ /***/ function(module, exports, __webpack_require__) { "use strict"; @@ -33134,7 +33007,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = exports["default"]; /***/ }, -/* 91 */ +/* 90 */ /***/ function(module, exports, __webpack_require__) { "use strict"; @@ -33229,7 +33102,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = exports["default"]; /***/ }, -/* 92 */ +/* 91 */ /***/ function(module, exports, __webpack_require__) { "use strict"; @@ -33320,7 +33193,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = exports["default"]; /***/ }, -/* 93 */ +/* 92 */ /***/ function(module, exports, __webpack_require__) { "use strict"; @@ -33429,6 +33302,135 @@ return /******/ (function(modules) { // webpackBootstrap exports["default"] = SpringSolver; module.exports = exports["default"]; +/***/ }, +/* 93 */ +/***/ 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; }; })(); + + function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + + var HierarchicalSpringSolver = (function () { + function HierarchicalSpringSolver(body, physicsBody, options) { + _classCallCheck(this, HierarchicalSpringSolver); + + this.body = body; + this.physicsBody = physicsBody; + this.setOptions(options); + } + + _createClass(HierarchicalSpringSolver, [{ + key: "setOptions", + value: function setOptions(options) { + this.options = options; + } + }, { + key: "solve", + + /** + * This function calculates the springforces on the nodes, accounting for the support nodes. + * + * @private + */ + value: function solve() { + var edgeLength, edge; + var dx, dy, fx, fy, springForce, distance; + var edges = this.body.edges; + var factor = 0.5; + + var edgeIndices = this.physicsBody.physicsEdgeIndices; + var nodeIndices = this.physicsBody.physicsNodeIndices; + var forces = this.physicsBody.forces; + + // initialize the spring force counters + for (var i = 0; i < nodeIndices.length; i++) { + var nodeId = nodeIndices[i]; + forces[nodeId].springFx = 0; + forces[nodeId].springFy = 0; + } + + // forces caused by the edges, modelled as springs + for (var i = 0; i < edgeIndices.length; i++) { + edge = edges[edgeIndices[i]]; + if (edge.connected === true) { + edgeLength = edge.options.length === undefined ? this.options.springLength : edge.options.length; + + dx = edge.from.x - edge.to.x; + dy = edge.from.y - edge.to.y; + distance = Math.sqrt(dx * dx + dy * dy); + distance = distance === 0 ? 0.01 : distance; + + // the 1/distance is so the fx and fy can be calculated without sine or cosine. + springForce = this.options.springConstant * (edgeLength - distance) / distance; + + fx = dx * springForce; + fy = dy * springForce; + + if (edge.to.level != edge.from.level) { + if (forces[edge.toId] !== undefined) { + forces[edge.toId].springFx -= fx; + forces[edge.toId].springFy -= fy; + } + if (forces[edge.fromId] !== undefined) { + forces[edge.fromId].springFx += fx; + forces[edge.fromId].springFy += fy; + } + } else { + if (forces[edge.toId] !== undefined) { + forces[edge.toId].x -= factor * fx; + forces[edge.toId].y -= factor * fy; + } + if (forces[edge.fromId] !== undefined) { + forces[edge.fromId].x += factor * fx; + forces[edge.fromId].y += factor * fy; + } + } + } + } + + // normalize spring forces + var springForce = 1; + var springFx, springFy; + for (var i = 0; i < nodeIndices.length; i++) { + var nodeId = nodeIndices[i]; + springFx = Math.min(springForce, Math.max(-springForce, forces[nodeId].springFx)); + springFy = Math.min(springForce, Math.max(-springForce, forces[nodeId].springFy)); + + forces[nodeId].x += springFx; + forces[nodeId].y += springFy; + } + + // retain energy balance + var totalFx = 0; + var totalFy = 0; + for (var i = 0; i < nodeIndices.length; i++) { + var nodeId = nodeIndices[i]; + totalFx += forces[nodeId].x; + totalFy += forces[nodeId].y; + } + var correctionFx = totalFx / nodeIndices.length; + var correctionFy = totalFy / nodeIndices.length; + + for (var i = 0; i < nodeIndices.length; i++) { + var nodeId = nodeIndices[i]; + forces[nodeId].x -= correctionFx; + forces[nodeId].y -= correctionFy; + } + } + }]); + + return HierarchicalSpringSolver; + })(); + + exports["default"] = HierarchicalSpringSolver; + module.exports = exports["default"]; + /***/ }, /* 94 */ /***/ function(module, exports, __webpack_require__) { @@ -33518,7 +33520,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 _BarnesHutSolver2 = __webpack_require__(90); + var _BarnesHutSolver2 = __webpack_require__(89); var _BarnesHutSolver3 = _interopRequireDefault(_BarnesHutSolver2); @@ -34371,7 +34373,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 _Node2 = __webpack_require__(64); + var _Node2 = __webpack_require__(63); var _Node3 = _interopRequireDefault(_Node2); @@ -34798,8 +34800,8 @@ return /******/ (function(modules) { // webpackBootstrap function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } - var Hammer = __webpack_require__(27); - var hammerUtil = __webpack_require__(32); + var Hammer = __webpack_require__(24); + var hammerUtil = __webpack_require__(29); var util = __webpack_require__(3); @@ -36327,9 +36329,9 @@ return /******/ (function(modules) { // webpackBootstrap function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } var util = __webpack_require__(3); - var Hammer = __webpack_require__(27); - var hammerUtil = __webpack_require__(32); - var keycharm = __webpack_require__(47); + var Hammer = __webpack_require__(24); + var hammerUtil = __webpack_require__(29); + var keycharm = __webpack_require__(44); var NavigationHandler = (function () { function NavigationHandler(body, canvas) { @@ -36769,8 +36771,8 @@ return /******/ (function(modules) { // webpackBootstrap function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - var Node = __webpack_require__(64); - var Edge = __webpack_require__(84); + var Node = __webpack_require__(63); + var Edge = __webpack_require__(83); var util = __webpack_require__(3); var SelectionHandler = (function () { @@ -38001,8 +38003,8 @@ return /******/ (function(modules) { // webpackBootstrap function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } var util = __webpack_require__(3); - var Hammer = __webpack_require__(27); - var hammerUtil = __webpack_require__(32); + var Hammer = __webpack_require__(24); + var hammerUtil = __webpack_require__(29); /** * clears the toolbar div element of children diff --git a/lib/network/modules/PhysicsEngine.js b/lib/network/modules/PhysicsEngine.js index 10c478b1..e82bdf86 100644 --- a/lib/network/modules/PhysicsEngine.js +++ b/lib/network/modules/PhysicsEngine.js @@ -21,6 +21,7 @@ class PhysicsEngine { this.previousStates = {}; this.freezeCache = {}; this.renderTimer = undefined; + this.initialStabilizationEmitted = false; this.stabilized = false; this.startedStabilization = false; @@ -237,7 +238,8 @@ class PhysicsEngine { } _emitStabilized() { - if (this.stabilizationIterations > 0) { + if (this.stabilizationIterations > 1 || this.initialStabilizationEmitted === false) { + this.initialStabilizationEmitted = true; setTimeout(() => { this.body.emitter.emit('stabilized', {iterations: this.stabilizationIterations}); this.stabilizationIterations = 0;