From 2abfcd8261087ece0e0b624f977479f2b238709b Mon Sep 17 00:00:00 2001 From: Alex de Mulder Date: Thu, 21 Aug 2014 10:40:41 +0200 Subject: [PATCH] Fixed physics stopping conditions, updated history #255 --- HISTORY.md | 7 + dist/vis.js | 47862 ++++++++++++++++++------------------- dist/vis.map | 2 +- dist/vis.min.js | 22 +- examples/network/ex.html | 128 + lib/network/Network.js | 9 +- lib/network/Node.js | 5 +- 7 files changed, 24085 insertions(+), 23950 deletions(-) create mode 100644 examples/network/ex.html diff --git a/HISTORY.md b/HISTORY.md index fdc6adfe..9ab1917a 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -13,6 +13,13 @@ http://visjs.org ### Network - A fix in reading group properties for a node. +- Fixed physics solving stopping when a support node was not moving. + +### Graph2D + +- Added 'slots' for groups when using barCharts. +- Added 'allowOverlap' option for barCharts. +- Added two examples showing the two additions above. ## 2014-08-14, version 3.2.0 diff --git a/dist/vis.js b/dist/vis.js index 49592791..35b01a96 100644 --- a/dist/vis.js +++ b/dist/vis.js @@ -5,7 +5,7 @@ * A dynamic, browser-based visualization library. * * @version 3.2.1-SNAPSHOT - * @date 2014-08-20 + * @date 2014-08-21 * * @license * Copyright (C) 2011-2014 Almende B.V, http://almende.com @@ -81,63 +81,63 @@ return /******/ (function(modules) { // webpackBootstrap // utils exports.util = __webpack_require__(1); - exports.DOMutil = __webpack_require__(6); + exports.DOMutil = __webpack_require__(2); // data - exports.DataSet = __webpack_require__(7); - exports.DataView = __webpack_require__(8); + exports.DataSet = __webpack_require__(3); + exports.DataView = __webpack_require__(4); // Graph3d - exports.Graph3d = __webpack_require__(9); + exports.Graph3d = __webpack_require__(5); exports.graph3d = { - Camera: __webpack_require__(13), - Filter: __webpack_require__(14), - Point2d: __webpack_require__(12), - Point3d: __webpack_require__(11), - Slider: __webpack_require__(15), - StepNumber: __webpack_require__(16) + Camera: __webpack_require__(6), + Filter: __webpack_require__(7), + Point2d: __webpack_require__(8), + Point3d: __webpack_require__(9), + Slider: __webpack_require__(10), + StepNumber: __webpack_require__(11) }; // Timeline - exports.Timeline = __webpack_require__(17); - exports.Graph2d = __webpack_require__(35); + exports.Timeline = __webpack_require__(12); + exports.Graph2d = __webpack_require__(13); exports.timeline = { - DataStep: __webpack_require__(37), - Range: __webpack_require__(20), - stack: __webpack_require__(30), - TimeStep: __webpack_require__(25), + DataStep: __webpack_require__(14), + Range: __webpack_require__(15), + stack: __webpack_require__(16), + TimeStep: __webpack_require__(17), components: { items: { - Item: __webpack_require__(32), - ItemBox: __webpack_require__(33), - ItemPoint: __webpack_require__(34), + Item: __webpack_require__(28), + ItemBox: __webpack_require__(29), + ItemPoint: __webpack_require__(30), ItemRange: __webpack_require__(31) }, - Component: __webpack_require__(22), - CurrentTime: __webpack_require__(26), - CustomTime: __webpack_require__(27), - DataAxis: __webpack_require__(38), - GraphGroup: __webpack_require__(39), - Group: __webpack_require__(29), - ItemSet: __webpack_require__(28), - Legend: __webpack_require__(40), - LineGraph: __webpack_require__(36), - TimeAxis: __webpack_require__(24) + Component: __webpack_require__(18), + CurrentTime: __webpack_require__(19), + CustomTime: __webpack_require__(20), + DataAxis: __webpack_require__(21), + GraphGroup: __webpack_require__(22), + Group: __webpack_require__(23), + ItemSet: __webpack_require__(24), + Legend: __webpack_require__(25), + LineGraph: __webpack_require__(26), + TimeAxis: __webpack_require__(27) } }; // Network - exports.Network = __webpack_require__(41); + exports.Network = __webpack_require__(32); exports.network = { - Edge: __webpack_require__(48), - Groups: __webpack_require__(45), - Images: __webpack_require__(46), - Node: __webpack_require__(47), - Popup: __webpack_require__(49), - dotparser: __webpack_require__(43), - gephiParser: __webpack_require__(44) + Edge: __webpack_require__(33), + Groups: __webpack_require__(34), + Images: __webpack_require__(35), + Node: __webpack_require__(36), + Popup: __webpack_require__(37), + dotparser: __webpack_require__(38), + gephiParser: __webpack_require__(39) }; // Deprecated since v3.0.0 @@ -146,8 +146,8 @@ return /******/ (function(modules) { // webpackBootstrap }; // bundled external libraries - exports.moment = __webpack_require__(2); - exports.hammer = __webpack_require__(18); + exports.moment = __webpack_require__(40); + exports.hammer = __webpack_require__(41); /***/ }, @@ -158,7 +158,7 @@ return /******/ (function(modules) { // webpackBootstrap // first check if moment.js is already loaded in the browser window, if so, // use this instance. Else, load via commonjs. - var moment = __webpack_require__(2); + var moment = __webpack_require__(40); /** * Test whether given object is a number @@ -1405,24620 +1405,24854 @@ return /******/ (function(modules) { // webpackBootstrap /* 2 */ /***/ 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. - module.exports = (typeof window !== 'undefined') && window['moment'] || __webpack_require__(3); + // DOM utility methods + /** + * this prepares the JSON container for allocating SVG elements + * @param JSONcontainer + * @private + */ + exports.prepareElements = function(JSONcontainer) { + // cleanup the redundant svgElements; + for (var elementType in JSONcontainer) { + if (JSONcontainer.hasOwnProperty(elementType)) { + JSONcontainer[elementType].redundant = JSONcontainer[elementType].used; + JSONcontainer[elementType].used = []; + } + } + }; -/***/ }, -/* 3 */ -/***/ function(module, exports, __webpack_require__) { + /** + * this cleans up all the unused SVG elements. By asking for the parentNode, we only need to supply the JSON container from + * which to remove the redundant elements. + * + * @param JSONcontainer + * @private + */ + exports.cleanupElements = function(JSONcontainer) { + // cleanup the redundant svgElements; + for (var elementType in JSONcontainer) { + if (JSONcontainer.hasOwnProperty(elementType)) { + if (JSONcontainer[elementType].redundant) { + for (var i = 0; i < JSONcontainer[elementType].redundant.length; i++) { + JSONcontainer[elementType].redundant[i].parentNode.removeChild(JSONcontainer[elementType].redundant[i]); + } + JSONcontainer[elementType].redundant = []; + } + } + } + }; - var __WEBPACK_AMD_DEFINE_RESULT__;/* WEBPACK VAR INJECTION */(function(global, module) {//! moment.js - //! version : 2.7.0 - //! authors : Tim Wood, Iskren Chernev, Moment.js contributors - //! license : MIT - //! momentjs.com + /** + * Allocate or generate an SVG element if needed. Store a reference to it in the JSON container and draw it in the svgContainer + * the JSON container and the SVG container have to be supplied so other svg containers (like the legend) can use this. + * + * @param elementType + * @param JSONcontainer + * @param svgContainer + * @returns {*} + * @private + */ + exports.getSVGElement = function (elementType, JSONcontainer, svgContainer) { + var element; + // allocate SVG element, if it doesnt yet exist, create one. + if (JSONcontainer.hasOwnProperty(elementType)) { // this element has been created before + // check if there is an redundant element + if (JSONcontainer[elementType].redundant.length > 0) { + element = JSONcontainer[elementType].redundant[0]; + JSONcontainer[elementType].redundant.shift(); + } + else { + // create a new element and add it to the SVG + element = document.createElementNS('http://www.w3.org/2000/svg', elementType); + svgContainer.appendChild(element); + } + } + else { + // create a new element and add it to the SVG, also create a new object in the svgElements to keep track of it. + element = document.createElementNS('http://www.w3.org/2000/svg', elementType); + JSONcontainer[elementType] = {used: [], redundant: []}; + svgContainer.appendChild(element); + } + JSONcontainer[elementType].used.push(element); + return element; + }; - (function (undefined) { - /************************************ - Constants - ************************************/ + /** + * Allocate or generate an SVG element if needed. Store a reference to it in the JSON container and draw it in the svgContainer + * the JSON container and the SVG container have to be supplied so other svg containers (like the legend) can use this. + * + * @param elementType + * @param JSONcontainer + * @param DOMContainer + * @returns {*} + * @private + */ + exports.getDOMElement = function (elementType, JSONcontainer, DOMContainer) { + var element; + // allocate DOM element, if it doesnt yet exist, create one. + if (JSONcontainer.hasOwnProperty(elementType)) { // this element has been created before + // check if there is an redundant element + if (JSONcontainer[elementType].redundant.length > 0) { + element = JSONcontainer[elementType].redundant[0]; + JSONcontainer[elementType].redundant.shift(); + } + else { + // create a new element and add it to the SVG + element = document.createElement(elementType); + DOMContainer.appendChild(element); + } + } + else { + // create a new element and add it to the SVG, also create a new object in the svgElements to keep track of it. + element = document.createElement(elementType); + JSONcontainer[elementType] = {used: [], redundant: []}; + DOMContainer.appendChild(element); + } + JSONcontainer[elementType].used.push(element); + return element; + }; - var moment, - VERSION = "2.7.0", - // the global-scope this is NOT the global object in Node.js - globalScope = typeof global !== 'undefined' ? global : this, - oldGlobalMoment, - round = Math.round, - i, - YEAR = 0, - MONTH = 1, - DATE = 2, - HOUR = 3, - MINUTE = 4, - SECOND = 5, - MILLISECOND = 6, - // internal storage for language config files - languages = {}, - // moment internal properties - momentProperties = { - _isAMomentObject: null, - _i : null, - _f : null, - _l : null, - _strict : null, - _tzm : null, - _isUTC : null, - _offset : null, // optional. Combine with _isUTC - _pf : null, - _lang : null // optional - }, + /** + * draw a point object. this is a seperate function because it can also be called by the legend. + * The reason the JSONcontainer and the target SVG svgContainer have to be supplied is so the legend can use these functions + * as well. + * + * @param x + * @param y + * @param group + * @param JSONcontainer + * @param svgContainer + * @returns {*} + */ + exports.drawPoint = function(x, y, group, JSONcontainer, svgContainer) { + var point; + if (group.options.drawPoints.style == 'circle') { + point = exports.getSVGElement('circle',JSONcontainer,svgContainer); + point.setAttributeNS(null, "cx", x); + point.setAttributeNS(null, "cy", y); + point.setAttributeNS(null, "r", 0.5 * group.options.drawPoints.size); + point.setAttributeNS(null, "class", group.className + " point"); + } + else { + point = exports.getSVGElement('rect',JSONcontainer,svgContainer); + point.setAttributeNS(null, "x", x - 0.5*group.options.drawPoints.size); + point.setAttributeNS(null, "y", y - 0.5*group.options.drawPoints.size); + point.setAttributeNS(null, "width", group.options.drawPoints.size); + point.setAttributeNS(null, "height", group.options.drawPoints.size); + point.setAttributeNS(null, "class", group.className + " point"); + } + return point; + }; - // check for nodeJS - hasModule = (typeof module !== 'undefined' && module.exports), + /** + * draw a bar SVG element centered on the X coordinate + * + * @param x + * @param y + * @param className + */ + exports.drawBar = function (x, y, width, height, className, JSONcontainer, svgContainer) { + // if (height != 0) { + var rect = exports.getSVGElement('rect',JSONcontainer, svgContainer); + rect.setAttributeNS(null, "x", x - 0.5 * width); + rect.setAttributeNS(null, "y", y); + rect.setAttributeNS(null, "width", width); + rect.setAttributeNS(null, "height", height); + rect.setAttributeNS(null, "class", className); + // } + }; - // ASP.NET json date format regex - aspNetJsonRegex = /^\/?Date\((\-?\d+)/i, - aspNetTimeSpanJsonRegex = /(\-)?(?:(\d*)\.)?(\d+)\:(\d+)(?:\:(\d+)\.?(\d{3})?)?/, +/***/ }, +/* 3 */ +/***/ function(module, exports, __webpack_require__) { - // from http://docs.closure-library.googlecode.com/git/closure_goog_date_date.js.source.html - // somewhat more in line with 4.4.3.2 2004 spec, but allows decimal anywhere - isoDurationRegex = /^(-)?P(?:(?:([0-9,.]*)Y)?(?:([0-9,.]*)M)?(?:([0-9,.]*)D)?(?:T(?:([0-9,.]*)H)?(?:([0-9,.]*)M)?(?:([0-9,.]*)S)?)?|([0-9,.]*)W)$/, + var util = __webpack_require__(1); - // format tokens - formattingTokens = /(\[[^\[]*\])|(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Q|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|mm?|ss?|S{1,4}|X|zz?|ZZ?|.)/g, - localFormattingTokens = /(\[[^\[]*\])|(\\)?(LT|LL?L?L?|l{1,4})/g, + /** + * DataSet + * + * Usage: + * var dataSet = new DataSet({ + * fieldId: '_id', + * type: { + * // ... + * } + * }); + * + * dataSet.add(item); + * dataSet.add(data); + * dataSet.update(item); + * dataSet.update(data); + * dataSet.remove(id); + * dataSet.remove(ids); + * var data = dataSet.get(); + * var data = dataSet.get(id); + * var data = dataSet.get(ids); + * var data = dataSet.get(ids, options, data); + * dataSet.clear(); + * + * A data set can: + * - add/remove/update data + * - gives triggers upon changes in the data + * - can import/export data in various data formats + * + * @param {Array | DataTable} [data] Optional array with initial data + * @param {Object} [options] Available options: + * {String} fieldId Field name of the id in the + * items, 'id' by default. + * {Object. ["10", "00"] or "-1530" > ["-15", "30"] - parseTimezoneChunker = /([\+\-]|\d\d)/gi, + subscribers.push({ + callback: callback + }); + }; - // getter and setter names - proxyGettersAndSetters = 'Date|Hours|Minutes|Seconds|Milliseconds'.split('|'), - unitMillisecondFactors = { - 'Milliseconds' : 1, - 'Seconds' : 1e3, - 'Minutes' : 6e4, - 'Hours' : 36e5, - 'Days' : 864e5, - 'Months' : 2592e6, - 'Years' : 31536e6 - }, + // TODO: make this function deprecated (replaced with `on` since version 0.5) + DataSet.prototype.subscribe = DataSet.prototype.on; - unitAliases = { - ms : 'millisecond', - s : 'second', - m : 'minute', - h : 'hour', - d : 'day', - D : 'date', - w : 'week', - W : 'isoWeek', - M : 'month', - Q : 'quarter', - y : 'year', - DDD : 'dayOfYear', - e : 'weekday', - E : 'isoWeekday', - gg: 'weekYear', - GG: 'isoWeekYear' - }, + /** + * Unsubscribe from an event, remove an event listener + * @param {String} event + * @param {function} callback + */ + DataSet.prototype.off = function(event, callback) { + var subscribers = this._subscribers[event]; + if (subscribers) { + this._subscribers[event] = subscribers.filter(function (listener) { + return (listener.callback != callback); + }); + } + }; - camelFunctions = { - dayofyear : 'dayOfYear', - isoweekday : 'isoWeekday', - isoweek : 'isoWeek', - weekyear : 'weekYear', - isoweekyear : 'isoWeekYear' - }, + // TODO: make this function deprecated (replaced with `on` since version 0.5) + DataSet.prototype.unsubscribe = DataSet.prototype.off; - // format function strings - formatFunctions = {}, + /** + * Trigger an event + * @param {String} event + * @param {Object | null} params + * @param {String} [senderId] Optional id of the sender. + * @private + */ + DataSet.prototype._trigger = function (event, params, senderId) { + if (event == '*') { + throw new Error('Cannot trigger event *'); + } - // default relative time thresholds - relativeTimeThresholds = { - s: 45, //seconds to minutes - m: 45, //minutes to hours - h: 22, //hours to days - dd: 25, //days to month (month == 1) - dm: 45, //days to months (months > 1) - dy: 345 //days to year - }, + var subscribers = []; + if (event in this._subscribers) { + subscribers = subscribers.concat(this._subscribers[event]); + } + if ('*' in this._subscribers) { + subscribers = subscribers.concat(this._subscribers['*']); + } - // tokens to ordinalize and pad - ordinalizeTokens = 'DDD w W M D d'.split(' '), - paddedTokens = 'M D H h m s w W'.split(' '), + for (var i = 0; i < subscribers.length; i++) { + var subscriber = subscribers[i]; + if (subscriber.callback) { + subscriber.callback(event, params, senderId || null); + } + } + }; - formatTokenFunctions = { - M : function () { - return this.month() + 1; - }, - MMM : function (format) { - return this.lang().monthsShort(this, format); - }, - MMMM : function (format) { - return this.lang().months(this, format); - }, - D : function () { - return this.date(); - }, - DDD : function () { - return this.dayOfYear(); - }, - d : function () { - return this.day(); - }, - dd : function (format) { - return this.lang().weekdaysMin(this, format); - }, - ddd : function (format) { - return this.lang().weekdaysShort(this, format); - }, - dddd : function (format) { - return this.lang().weekdays(this, format); - }, - w : function () { - return this.week(); - }, - W : function () { - return this.isoWeek(); - }, - YY : function () { - return leftZeroFill(this.year() % 100, 2); - }, - YYYY : function () { - return leftZeroFill(this.year(), 4); - }, - YYYYY : function () { - return leftZeroFill(this.year(), 5); - }, - YYYYYY : function () { - var y = this.year(), sign = y >= 0 ? '+' : '-'; - return sign + leftZeroFill(Math.abs(y), 6); - }, - gg : function () { - return leftZeroFill(this.weekYear() % 100, 2); - }, - gggg : function () { - return leftZeroFill(this.weekYear(), 4); - }, - ggggg : function () { - return leftZeroFill(this.weekYear(), 5); - }, - GG : function () { - return leftZeroFill(this.isoWeekYear() % 100, 2); - }, - GGGG : function () { - return leftZeroFill(this.isoWeekYear(), 4); - }, - GGGGG : function () { - return leftZeroFill(this.isoWeekYear(), 5); - }, - e : function () { - return this.weekday(); - }, - E : function () { - return this.isoWeekday(); - }, - a : function () { - return this.lang().meridiem(this.hours(), this.minutes(), true); - }, - A : function () { - return this.lang().meridiem(this.hours(), this.minutes(), false); - }, - H : function () { - return this.hours(); - }, - h : function () { - return this.hours() % 12 || 12; - }, - m : function () { - return this.minutes(); - }, - s : function () { - return this.seconds(); - }, - S : function () { - return toInt(this.milliseconds() / 100); - }, - SS : function () { - return leftZeroFill(toInt(this.milliseconds() / 10), 2); - }, - SSS : function () { - return leftZeroFill(this.milliseconds(), 3); - }, - SSSS : function () { - return leftZeroFill(this.milliseconds(), 3); - }, - Z : function () { - var a = -this.zone(), - b = "+"; - if (a < 0) { - a = -a; - b = "-"; - } - return b + leftZeroFill(toInt(a / 60), 2) + ":" + leftZeroFill(toInt(a) % 60, 2); - }, - ZZ : function () { - var a = -this.zone(), - b = "+"; - if (a < 0) { - a = -a; - b = "-"; - } - return b + leftZeroFill(toInt(a / 60), 2) + leftZeroFill(toInt(a) % 60, 2); - }, - z : function () { - return this.zoneAbbr(); - }, - zz : function () { - return this.zoneName(); - }, - X : function () { - return this.unix(); - }, - Q : function () { - return this.quarter(); - } - }, - - lists = ['months', 'monthsShort', 'weekdays', 'weekdaysShort', 'weekdaysMin']; - - // Pick the first defined of two or three arguments. dfl comes from - // default. - function dfl(a, b, c) { - switch (arguments.length) { - case 2: return a != null ? a : b; - case 3: return a != null ? a : b != null ? b : c; - default: throw new Error("Implement me"); - } - } - - function defaultParsingFlags() { - // We need to deep clone this object, and es5 standard is not very - // helpful. - return { - empty : false, - unusedTokens : [], - unusedInput : [], - overflow : -2, - charsLeftOver : 0, - nullInput : false, - invalidMonth : null, - invalidFormat : false, - userInvalidated : false, - iso: false - }; - } - - function deprecate(msg, fn) { - var firstTime = true; - function printMsg() { - if (moment.suppressDeprecationWarnings === false && - typeof console !== 'undefined' && console.warn) { - console.warn("Deprecation warning: " + msg); - } - } - return extend(function () { - if (firstTime) { - printMsg(); - firstTime = false; - } - return fn.apply(this, arguments); - }, fn); - } + /** + * Add data. + * Adding an item will fail when there already is an item with the same id. + * @param {Object | Array | DataTable} data + * @param {String} [senderId] Optional sender id + * @return {Array} addedIds Array with the ids of the added items + */ + DataSet.prototype.add = function (data, senderId) { + var addedIds = [], + id, + me = this; - function padToken(func, count) { - return function (a) { - return leftZeroFill(func.call(this, a), count); - }; - } - function ordinalizeToken(func, period) { - return function (a) { - return this.lang().ordinal(func.call(this, a), period); - }; + if (Array.isArray(data)) { + // Array + for (var i = 0, len = data.length; i < len; i++) { + id = me._addItem(data[i]); + addedIds.push(id); } + } + else if (util.isDataTable(data)) { + // Google DataTable + var columns = this._getColumnNames(data); + for (var row = 0, rows = data.getNumberOfRows(); row < rows; row++) { + var item = {}; + for (var col = 0, cols = columns.length; col < cols; col++) { + var field = columns[col]; + item[field] = data.getValue(row, col); + } - while (ordinalizeTokens.length) { - i = ordinalizeTokens.pop(); - formatTokenFunctions[i + 'o'] = ordinalizeToken(formatTokenFunctions[i], i); - } - while (paddedTokens.length) { - i = paddedTokens.pop(); - formatTokenFunctions[i + i] = padToken(formatTokenFunctions[i], 2); + id = me._addItem(item); + addedIds.push(id); } - formatTokenFunctions.DDDD = padToken(formatTokenFunctions.DDD, 3); + } + else if (data instanceof Object) { + // Single item + id = me._addItem(data); + addedIds.push(id); + } + else { + throw new Error('Unknown dataType'); + } + if (addedIds.length) { + this._trigger('add', {items: addedIds}, senderId); + } - /************************************ - Constructors - ************************************/ + return addedIds; + }; - function Language() { + /** + * Update existing items. When an item does not exist, it will be created + * @param {Object | Array | DataTable} data + * @param {String} [senderId] Optional sender id + * @return {Array} updatedIds The ids of the added or updated items + */ + DataSet.prototype.update = function (data, senderId) { + var addedIds = [], + updatedIds = [], + me = this, + fieldId = me._fieldId; + var addOrUpdate = function (item) { + var id = item[fieldId]; + if (me._data[id]) { + // update item + id = me._updateItem(item); + updatedIds.push(id); } - - // Moment prototype object - function Moment(config) { - checkOverflow(config); - extend(this, config); + else { + // add new item + id = me._addItem(item); + addedIds.push(id); } + }; - // Duration Constructor - function Duration(duration) { - var normalizedInput = normalizeObjectUnits(duration), - years = normalizedInput.year || 0, - quarters = normalizedInput.quarter || 0, - months = normalizedInput.month || 0, - weeks = normalizedInput.week || 0, - days = normalizedInput.day || 0, - hours = normalizedInput.hour || 0, - minutes = normalizedInput.minute || 0, - seconds = normalizedInput.second || 0, - milliseconds = normalizedInput.millisecond || 0; - - // representation for dateAddRemove - this._milliseconds = +milliseconds + - seconds * 1e3 + // 1000 - minutes * 6e4 + // 1000 * 60 - hours * 36e5; // 1000 * 60 * 60 - // Because of dateAddRemove treats 24 hours as different from a - // day when working around DST, we need to store them separately - this._days = +days + - weeks * 7; - // It is impossible translate months into days without knowing - // which months you are are talking about, so we have to store - // it separately. - this._months = +months + - quarters * 3 + - years * 12; - - this._data = {}; + if (Array.isArray(data)) { + // Array + for (var i = 0, len = data.length; i < len; i++) { + addOrUpdate(data[i]); + } + } + else if (util.isDataTable(data)) { + // Google DataTable + var columns = this._getColumnNames(data); + for (var row = 0, rows = data.getNumberOfRows(); row < rows; row++) { + var item = {}; + for (var col = 0, cols = columns.length; col < cols; col++) { + var field = columns[col]; + item[field] = data.getValue(row, col); + } - this._bubble(); + addOrUpdate(item); } + } + else if (data instanceof Object) { + // Single item + addOrUpdate(data); + } + else { + throw new Error('Unknown dataType'); + } - /************************************ - Helpers - ************************************/ + if (addedIds.length) { + this._trigger('add', {items: addedIds}, senderId); + } + if (updatedIds.length) { + this._trigger('update', {items: updatedIds}, senderId); + } + return addedIds.concat(updatedIds); + }; - function extend(a, b) { - for (var i in b) { - if (b.hasOwnProperty(i)) { - a[i] = b[i]; - } - } + /** + * Get a data item or multiple items. + * + * Usage: + * + * get() + * get(options: Object) + * get(options: Object, data: Array | DataTable) + * + * get(id: Number | String) + * get(id: Number | String, options: Object) + * get(id: Number | String, options: Object, data: Array | DataTable) + * + * get(ids: Number[] | String[]) + * get(ids: Number[] | String[], options: Object) + * get(ids: Number[] | String[], options: Object, data: Array | DataTable) + * + * Where: + * + * {Number | String} id The id of an item + * {Number[] | String{}} ids An array with ids of items + * {Object} options An Object with options. Available options: + * {String} [returnType] Type of data to be + * returned. Can be 'DataTable' or 'Array' (default) + * {Object.} [type] + * {String[]} [fields] field names to be returned + * {function} [filter] filter items + * {String | function} [order] Order the items by + * a field name or custom sort function. + * {Array | DataTable} [data] If provided, items will be appended to this + * array or table. Required in case of Google + * DataTable. + * + * @throws Error + */ + DataSet.prototype.get = function (args) { + var me = this; - if (b.hasOwnProperty("toString")) { - a.toString = b.toString; - } + // parse the arguments + var id, ids, options, data; + var firstType = util.getType(arguments[0]); + if (firstType == 'String' || firstType == 'Number') { + // get(id [, options] [, data]) + id = arguments[0]; + options = arguments[1]; + data = arguments[2]; + } + else if (firstType == 'Array') { + // get(ids [, options] [, data]) + ids = arguments[0]; + options = arguments[1]; + data = arguments[2]; + } + else { + // get([, options] [, data]) + options = arguments[0]; + data = arguments[1]; + } - if (b.hasOwnProperty("valueOf")) { - a.valueOf = b.valueOf; - } + // determine the return type + var returnType; + if (options && options.returnType) { + var allowedValues = ["DataTable", "Array", "Object"]; + returnType = allowedValues.indexOf(options.returnType) == -1 ? "Array" : options.returnType; - return a; + if (data && (returnType != util.getType(data))) { + throw new Error('Type of parameter "data" (' + util.getType(data) + ') ' + + 'does not correspond with specified options.type (' + options.type + ')'); + } + if (returnType == 'DataTable' && !util.isDataTable(data)) { + throw new Error('Parameter "data" must be a DataTable ' + + 'when options.type is "DataTable"'); } + } + else if (data) { + returnType = (util.getType(data) == 'DataTable') ? 'DataTable' : 'Array'; + } + else { + returnType = 'Array'; + } - function cloneMoment(m) { - var result = {}, i; - for (i in m) { - if (m.hasOwnProperty(i) && momentProperties.hasOwnProperty(i)) { - result[i] = m[i]; - } - } + // build options + var type = options && options.type || this._options.type; + var filter = options && options.filter; + var items = [], item, itemId, i, len; - return result; + // convert items + if (id != undefined) { + // return a single item + item = me._getItem(id, type); + if (filter && !filter(item)) { + item = null; } - - function absRound(number) { - if (number < 0) { - return Math.ceil(number); - } else { - return Math.floor(number); - } + } + else if (ids != undefined) { + // return a subset of items + for (i = 0, len = ids.length; i < len; i++) { + item = me._getItem(ids[i], type); + if (!filter || filter(item)) { + items.push(item); + } } - - // left zero fill a number - // see http://jsperf.com/left-zero-filling for performance comparison - function leftZeroFill(number, targetLength, forceSign) { - var output = '' + Math.abs(number), - sign = number >= 0; - - while (output.length < targetLength) { - output = '0' + output; + } + else { + // return all items + for (itemId in this._data) { + if (this._data.hasOwnProperty(itemId)) { + item = me._getItem(itemId, type); + if (!filter || filter(item)) { + items.push(item); } - return (sign ? (forceSign ? '+' : '') : '-') + output; + } } + } - // helper function for _.addTime and _.subtractTime - function addOrSubtractDurationFromMoment(mom, duration, isAdding, updateOffset) { - var milliseconds = duration._milliseconds, - days = duration._days, - months = duration._months; - updateOffset = updateOffset == null ? true : updateOffset; + // order the results + if (options && options.order && id == undefined) { + this._sort(items, options.order); + } - if (milliseconds) { - mom._d.setTime(+mom._d + milliseconds * isAdding); - } - if (days) { - rawSetter(mom, 'Date', rawGetter(mom, 'Date') + days * isAdding); - } - if (months) { - rawMonthSetter(mom, rawGetter(mom, 'Month') + months * isAdding); - } - if (updateOffset) { - moment.updateOffset(mom, days || months); - } + // filter fields of the items + if (options && options.fields) { + var fields = options.fields; + if (id != undefined) { + item = this._filterFields(item, fields); } - - // check if is an array - function isArray(input) { - return Object.prototype.toString.call(input) === '[object Array]'; + else { + for (i = 0, len = items.length; i < len; i++) { + items[i] = this._filterFields(items[i], fields); + } } + } - function isDate(input) { - return Object.prototype.toString.call(input) === '[object Date]' || - input instanceof Date; + // return the results + if (returnType == 'DataTable') { + var columns = this._getColumnNames(data); + if (id != undefined) { + // append a single item to the data table + me._appendRow(data, columns, item); } - - // compare two arrays, return the number of differences - function compareArrays(array1, array2, dontConvert) { - var len = Math.min(array1.length, array2.length), - lengthDiff = Math.abs(array1.length - array2.length), - diffs = 0, - i; - for (i = 0; i < len; i++) { - if ((dontConvert && array1[i] !== array2[i]) || - (!dontConvert && toInt(array1[i]) !== toInt(array2[i]))) { - diffs++; - } - } - return diffs + lengthDiff; + else { + // copy the items to the provided data table + for (i = 0; i < items.length; i++) { + me._appendRow(data, columns, items[i]); + } } - - function normalizeUnits(units) { - if (units) { - var lowered = units.toLowerCase().replace(/(.)s$/, '$1'); - units = unitAliases[units] || camelFunctions[lowered] || lowered; - } - return units; + return data; + } + else if (returnType == "Object") { + var result = {}; + for (i = 0; i < items.length; i++) { + result[items[i].id] = items[i]; } - - function normalizeObjectUnits(inputObject) { - var normalizedInput = {}, - normalizedProp, - prop; - - for (prop in inputObject) { - if (inputObject.hasOwnProperty(prop)) { - normalizedProp = normalizeUnits(prop); - if (normalizedProp) { - normalizedInput[normalizedProp] = inputObject[prop]; - } - } + return result; + } + else { + // return an array + if (id != undefined) { + // a single item + return item; + } + else { + // multiple items + if (data) { + // copy the items to the provided array + for (i = 0, len = items.length; i < len; i++) { + data.push(items[i]); } - - return normalizedInput; + return data; + } + else { + // just return our array + return items; + } } + } + }; - function makeList(field) { - var count, setter; - - if (field.indexOf('week') === 0) { - count = 7; - setter = 'day'; - } - else if (field.indexOf('month') === 0) { - count = 12; - setter = 'month'; - } - else { - return; - } - - moment[field] = function (format, index) { - var i, getter, - method = moment.fn._lang[field], - results = []; + /** + * Get ids of all items or from a filtered set of items. + * @param {Object} [options] An Object with options. Available options: + * {function} [filter] filter items + * {String | function} [order] Order the items by + * a field name or custom sort function. + * @return {Array} ids + */ + DataSet.prototype.getIds = function (options) { + var data = this._data, + filter = options && options.filter, + order = options && options.order, + type = options && options.type || this._options.type, + i, + len, + id, + item, + items, + ids = []; - if (typeof format === 'number') { - index = format; - format = undefined; - } + if (filter) { + // get filtered items + if (order) { + // create ordered list + items = []; + for (id in data) { + if (data.hasOwnProperty(id)) { + item = this._getItem(id, type); + if (filter(item)) { + items.push(item); + } + } + } - getter = function (i) { - var m = moment().utc().set(setter, i); - return method.call(moment.fn._lang, m, format || ''); - }; + this._sort(items, order); - if (index != null) { - return getter(index); - } - else { - for (i = 0; i < count; i++) { - results.push(getter(i)); - } - return results; - } - }; + for (i = 0, len = items.length; i < len; i++) { + ids[i] = items[i][this._fieldId]; + } } - - function toInt(argumentForCoercion) { - var coercedNumber = +argumentForCoercion, - value = 0; - - if (coercedNumber !== 0 && isFinite(coercedNumber)) { - if (coercedNumber >= 0) { - value = Math.floor(coercedNumber); - } else { - value = Math.ceil(coercedNumber); - } + else { + // create unordered list + for (id in data) { + if (data.hasOwnProperty(id)) { + item = this._getItem(id, type); + if (filter(item)) { + ids.push(item[this._fieldId]); + } } - - return value; - } - - function daysInMonth(year, month) { - return new Date(Date.UTC(year, month + 1, 0)).getUTCDate(); + } } + } + else { + // get all items + if (order) { + // create an ordered list + items = []; + for (id in data) { + if (data.hasOwnProperty(id)) { + items.push(data[id]); + } + } - function weeksInYear(year, dow, doy) { - return weekOfYear(moment([year, 11, 31 + dow - doy]), dow, doy).week; - } + this._sort(items, order); - function daysInYear(year) { - return isLeapYear(year) ? 366 : 365; + for (i = 0, len = items.length; i < len; i++) { + ids[i] = items[i][this._fieldId]; + } } - - function isLeapYear(year) { - return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0; + else { + // create unordered list + for (id in data) { + if (data.hasOwnProperty(id)) { + item = data[id]; + ids.push(item[this._fieldId]); + } + } } + } - function checkOverflow(m) { - var overflow; - if (m._a && m._pf.overflow === -2) { - overflow = - m._a[MONTH] < 0 || m._a[MONTH] > 11 ? MONTH : - m._a[DATE] < 1 || m._a[DATE] > daysInMonth(m._a[YEAR], m._a[MONTH]) ? DATE : - m._a[HOUR] < 0 || m._a[HOUR] > 23 ? HOUR : - m._a[MINUTE] < 0 || m._a[MINUTE] > 59 ? MINUTE : - m._a[SECOND] < 0 || m._a[SECOND] > 59 ? SECOND : - m._a[MILLISECOND] < 0 || m._a[MILLISECOND] > 999 ? MILLISECOND : - -1; + return ids; + }; - if (m._pf._overflowDayOfYear && (overflow < YEAR || overflow > DATE)) { - overflow = DATE; - } + /** + * Returns the DataSet itself. Is overwritten for example by the DataView, + * which returns the DataSet it is connected to instead. + */ + DataSet.prototype.getDataSet = function () { + return this; + }; - m._pf.overflow = overflow; - } - } + /** + * Execute a callback function for every item in the dataset. + * @param {function} callback + * @param {Object} [options] Available options: + * {Object.} [type] + * {String[]} [fields] filter fields + * {function} [filter] filter items + * {String | function} [order] Order the items by + * a field name or custom sort function. + */ + DataSet.prototype.forEach = function (callback, options) { + var filter = options && options.filter, + type = options && options.type || this._options.type, + data = this._data, + item, + id; - function isValid(m) { - if (m._isValid == null) { - m._isValid = !isNaN(m._d.getTime()) && - m._pf.overflow < 0 && - !m._pf.empty && - !m._pf.invalidMonth && - !m._pf.nullInput && - !m._pf.invalidFormat && - !m._pf.userInvalidated; + if (options && options.order) { + // execute forEach on ordered list + var items = this.get(options); - if (m._strict) { - m._isValid = m._isValid && - m._pf.charsLeftOver === 0 && - m._pf.unusedTokens.length === 0; - } + for (var i = 0, len = items.length; i < len; i++) { + item = items[i]; + id = item[this._fieldId]; + callback(item, id); + } + } + else { + // unordered + for (id in data) { + if (data.hasOwnProperty(id)) { + item = this._getItem(id, type); + if (!filter || filter(item)) { + callback(item, id); } - return m._isValid; + } } + } + }; - function normalizeLanguage(key) { - return key ? key.toLowerCase().replace('_', '-') : key; - } + /** + * Map every item in the dataset. + * @param {function} callback + * @param {Object} [options] Available options: + * {Object.} [type] + * {String[]} [fields] filter fields + * {function} [filter] filter items + * {String | function} [order] Order the items by + * a field name or custom sort function. + * @return {Object[]} mappedItems + */ + DataSet.prototype.map = function (callback, options) { + var filter = options && options.filter, + type = options && options.type || this._options.type, + mappedItems = [], + data = this._data, + item; - // Return a moment from input, that is local/utc/zone equivalent to model. - function makeAs(input, model) { - return model._isUTC ? moment(input).zone(model._offset || 0) : - moment(input).local(); + // convert and filter items + for (var id in data) { + if (data.hasOwnProperty(id)) { + item = this._getItem(id, type); + if (!filter || filter(item)) { + mappedItems.push(callback(item, id)); + } } + } - /************************************ - Languages - ************************************/ + // order items + if (options && options.order) { + this._sort(mappedItems, options.order); + } + return mappedItems; + }; - extend(Language.prototype, { + /** + * Filter the fields of an item + * @param {Object} item + * @param {String[]} fields Field names + * @return {Object} filteredItem + * @private + */ + DataSet.prototype._filterFields = function (item, fields) { + var filteredItem = {}; - set : function (config) { - var prop, i; - for (i in config) { - prop = config[i]; - if (typeof prop === 'function') { - this[i] = prop; - } else { - this['_' + i] = prop; - } - } - }, + for (var field in item) { + if (item.hasOwnProperty(field) && (fields.indexOf(field) != -1)) { + filteredItem[field] = item[field]; + } + } - _months : "January_February_March_April_May_June_July_August_September_October_November_December".split("_"), - months : function (m) { - return this._months[m.month()]; - }, + return filteredItem; + }; - _monthsShort : "Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"), - monthsShort : function (m) { - return this._monthsShort[m.month()]; - }, + /** + * Sort the provided array with items + * @param {Object[]} items + * @param {String | function} order A field name or custom sort function. + * @private + */ + DataSet.prototype._sort = function (items, order) { + if (util.isString(order)) { + // order by provided field name + var name = order; // field name + items.sort(function (a, b) { + var av = a[name]; + var bv = b[name]; + return (av > bv) ? 1 : ((av < bv) ? -1 : 0); + }); + } + else if (typeof order === 'function') { + // order by sort function + items.sort(order); + } + // TODO: extend order by an Object {field:String, direction:String} + // where direction can be 'asc' or 'desc' + else { + throw new TypeError('Order must be a function or a string'); + } + }; - monthsParse : function (monthName) { - var i, mom, regex; + /** + * Remove an object by pointer or by id + * @param {String | Number | Object | Array} id Object or id, or an array with + * objects or ids to be removed + * @param {String} [senderId] Optional sender id + * @return {Array} removedIds + */ + DataSet.prototype.remove = function (id, senderId) { + var removedIds = [], + i, len, removedId; - if (!this._monthsParse) { - this._monthsParse = []; - } + if (Array.isArray(id)) { + for (i = 0, len = id.length; i < len; i++) { + removedId = this._remove(id[i]); + if (removedId != null) { + removedIds.push(removedId); + } + } + } + else { + removedId = this._remove(id); + if (removedId != null) { + removedIds.push(removedId); + } + } - for (i = 0; i < 12; i++) { - // make the regex if we don't have it already - if (!this._monthsParse[i]) { - mom = moment.utc([2000, i]); - regex = '^' + this.months(mom, '') + '|^' + this.monthsShort(mom, ''); - this._monthsParse[i] = new RegExp(regex.replace('.', ''), 'i'); - } - // test the regex - if (this._monthsParse[i].test(monthName)) { - return i; - } - } - }, + if (removedIds.length) { + this._trigger('remove', {items: removedIds}, senderId); + } - _weekdays : "Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"), - weekdays : function (m) { - return this._weekdays[m.day()]; - }, + return removedIds; + }; - _weekdaysShort : "Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"), - weekdaysShort : function (m) { - return this._weekdaysShort[m.day()]; - }, + /** + * Remove an item by its id + * @param {Number | String | Object} id id or item + * @returns {Number | String | null} id + * @private + */ + DataSet.prototype._remove = function (id) { + if (util.isNumber(id) || util.isString(id)) { + if (this._data[id]) { + delete this._data[id]; + return id; + } + } + else if (id instanceof Object) { + var itemId = id[this._fieldId]; + if (itemId && this._data[itemId]) { + delete this._data[itemId]; + return itemId; + } + } + return null; + }; - _weekdaysMin : "Su_Mo_Tu_We_Th_Fr_Sa".split("_"), - weekdaysMin : function (m) { - return this._weekdaysMin[m.day()]; - }, + /** + * Clear the data + * @param {String} [senderId] Optional sender id + * @return {Array} removedIds The ids of all removed items + */ + DataSet.prototype.clear = function (senderId) { + var ids = Object.keys(this._data); - weekdaysParse : function (weekdayName) { - var i, mom, regex; + this._data = {}; - if (!this._weekdaysParse) { - this._weekdaysParse = []; - } + this._trigger('remove', {items: ids}, senderId); - for (i = 0; i < 7; i++) { - // make the regex if we don't have it already - if (!this._weekdaysParse[i]) { - mom = moment([2000, 1]).day(i); - regex = '^' + this.weekdays(mom, '') + '|^' + this.weekdaysShort(mom, '') + '|^' + this.weekdaysMin(mom, ''); - this._weekdaysParse[i] = new RegExp(regex.replace('.', ''), 'i'); - } - // test the regex - if (this._weekdaysParse[i].test(weekdayName)) { - return i; - } - } - }, + return ids; + }; - _longDateFormat : { - LT : "h:mm A", - L : "MM/DD/YYYY", - LL : "MMMM D YYYY", - LLL : "MMMM D YYYY LT", - LLLL : "dddd, MMMM D YYYY LT" - }, - longDateFormat : function (key) { - var output = this._longDateFormat[key]; - if (!output && this._longDateFormat[key.toUpperCase()]) { - output = this._longDateFormat[key.toUpperCase()].replace(/MMMM|MM|DD|dddd/g, function (val) { - return val.slice(1); - }); - this._longDateFormat[key] = output; - } - return output; - }, + /** + * Find the item with maximum value of a specified field + * @param {String} field + * @return {Object | null} item Item containing max value, or null if no items + */ + DataSet.prototype.max = function (field) { + var data = this._data, + max = null, + maxField = null; - isPM : function (input) { - // IE8 Quirks Mode & IE7 Standards Mode do not allow accessing strings like arrays - // Using charAt should be more compatible. - return ((input + '').toLowerCase().charAt(0) === 'p'); - }, + for (var id in data) { + if (data.hasOwnProperty(id)) { + var item = data[id]; + var itemField = item[field]; + if (itemField != null && (!max || itemField > maxField)) { + max = item; + maxField = itemField; + } + } + } - _meridiemParse : /[ap]\.?m?\.?/i, - meridiem : function (hours, minutes, isLower) { - if (hours > 11) { - return isLower ? 'pm' : 'PM'; - } else { - return isLower ? 'am' : 'AM'; - } - }, + return max; + }; - _calendar : { - sameDay : '[Today at] LT', - nextDay : '[Tomorrow at] LT', - nextWeek : 'dddd [at] LT', - lastDay : '[Yesterday at] LT', - lastWeek : '[Last] dddd [at] LT', - sameElse : 'L' - }, - calendar : function (key, mom) { - var output = this._calendar[key]; - return typeof output === 'function' ? output.apply(mom) : output; - }, + /** + * Find the item with minimum value of a specified field + * @param {String} field + * @return {Object | null} item Item containing max value, or null if no items + */ + DataSet.prototype.min = function (field) { + var data = this._data, + min = null, + minField = null; - _relativeTime : { - future : "in %s", - past : "%s ago", - s : "a few seconds", - m : "a minute", - mm : "%d minutes", - h : "an hour", - hh : "%d hours", - d : "a day", - dd : "%d days", - M : "a month", - MM : "%d months", - y : "a year", - yy : "%d years" - }, - relativeTime : function (number, withoutSuffix, string, isFuture) { - var output = this._relativeTime[string]; - return (typeof output === 'function') ? - output(number, withoutSuffix, string, isFuture) : - output.replace(/%d/i, number); - }, - pastFuture : function (diff, output) { - var format = this._relativeTime[diff > 0 ? 'future' : 'past']; - return typeof format === 'function' ? format(output) : format.replace(/%s/i, output); - }, - - ordinal : function (number) { - return this._ordinal.replace("%d", number); - }, - _ordinal : "%d", - - preparse : function (string) { - return string; - }, - - postformat : function (string) { - return string; - }, - - week : function (mom) { - return weekOfYear(mom, this._week.dow, this._week.doy).week; - }, + for (var id in data) { + if (data.hasOwnProperty(id)) { + var item = data[id]; + var itemField = item[field]; + if (itemField != null && (!min || itemField < minField)) { + min = item; + minField = itemField; + } + } + } - _week : { - dow : 0, // Sunday is the first day of the week. - doy : 6 // The week that contains Jan 1st is the first week of the year. - }, + return min; + }; - _invalidDate: 'Invalid date', - invalidDate: function () { - return this._invalidDate; - } - }); + /** + * Find all distinct values of a specified field + * @param {String} field + * @return {Array} values Array containing all distinct values. If data items + * do not contain the specified field are ignored. + * The returned array is unordered. + */ + DataSet.prototype.distinct = function (field) { + var data = this._data; + var values = []; + var fieldType = this._options.type && this._options.type[field] || null; + var count = 0; + var i; - // Loads a language definition into the `languages` cache. The function - // takes a key and optionally values. If not in the browser and no values - // are provided, it will load the language file module. As a convenience, - // this function also returns the language values. - function loadLang(key, values) { - values.abbr = key; - if (!languages[key]) { - languages[key] = new Language(); + for (var prop in data) { + if (data.hasOwnProperty(prop)) { + var item = data[prop]; + var value = item[field]; + var exists = false; + for (i = 0; i < count; i++) { + if (values[i] == value) { + exists = true; + break; } - languages[key].set(values); - return languages[key]; + } + if (!exists && (value !== undefined)) { + values[count] = value; + count++; + } } + } - // Remove a language from the `languages` cache. Mostly useful in tests. - function unloadLang(key) { - delete languages[key]; + if (fieldType) { + for (i = 0; i < values.length; i++) { + values[i] = util.convert(values[i], fieldType); } + } - // Determines which language definition to use and returns it. - // - // With no parameters, it will return the global language. If you - // pass in a language key, such as 'en', it will return the - // definition for 'en', so long as 'en' has already been loaded using - // moment.lang. - function getLangDefinition(key) { - var i = 0, j, lang, next, split, - get = function (k) { - if (!languages[k] && hasModule) { - try { - __webpack_require__(4)("./" + k); - } catch (e) { } - } - return languages[k]; - }; + return values; + }; - if (!key) { - return moment.fn._lang; - } + /** + * Add a single item. Will fail when an item with the same id already exists. + * @param {Object} item + * @return {String} id + * @private + */ + DataSet.prototype._addItem = function (item) { + var id = item[this._fieldId]; - if (!isArray(key)) { - //short-circuit everything else - lang = get(key); - if (lang) { - return lang; - } - key = [key]; - } + if (id != undefined) { + // check whether this id is already taken + if (this._data[id]) { + // item already exists + throw new Error('Cannot add item: item with id ' + id + ' already exists'); + } + } + else { + // generate an id + id = util.randomUUID(); + item[this._fieldId] = id; + } - //pick the language from the array - //try ['en-au', 'en-gb'] as 'en-au', 'en-gb', 'en', as in move through the list trying each - //substring from most specific to least, but move to the next array item if it's a more specific variant than the current root - while (i < key.length) { - split = normalizeLanguage(key[i]).split('-'); - j = split.length; - next = normalizeLanguage(key[i + 1]); - next = next ? next.split('-') : null; - while (j > 0) { - lang = get(split.slice(0, j).join('-')); - if (lang) { - return lang; - } - if (next && next.length >= j && compareArrays(split, next, true) >= j - 1) { - //the next array item is better than a shallower substring of this one - break; - } - j--; - } - i++; - } - return moment.fn._lang; + var d = {}; + for (var field in item) { + if (item.hasOwnProperty(field)) { + var fieldType = this._type[field]; // type may be undefined + d[field] = util.convert(item[field], fieldType); } + } + this._data[id] = d; - /************************************ - Formatting - ************************************/ + return id; + }; + /** + * Get an item. Fields can be converted to a specific type + * @param {String} id + * @param {Object.} [types] field types to convert + * @return {Object | null} item + * @private + */ + DataSet.prototype._getItem = function (id, types) { + var field, value; - function removeFormattingTokens(input) { - if (input.match(/\[[\s\S]/)) { - return input.replace(/^\[|\]$/g, ""); - } - return input.replace(/\\/g, ""); - } + // get the item from the dataset + var raw = this._data[id]; + if (!raw) { + return null; + } - function makeFormatFunction(format) { - var array = format.match(formattingTokens), i, length; + // convert the items field types + var converted = {}; + if (types) { + for (field in raw) { + if (raw.hasOwnProperty(field)) { + value = raw[field]; + converted[field] = util.convert(value, types[field]); + } + } + } + else { + // no field types specified, no converting needed + for (field in raw) { + if (raw.hasOwnProperty(field)) { + value = raw[field]; + converted[field] = value; + } + } + } + return converted; + }; - for (i = 0, length = array.length; i < length; i++) { - if (formatTokenFunctions[array[i]]) { - array[i] = formatTokenFunctions[array[i]]; - } else { - array[i] = removeFormattingTokens(array[i]); - } - } + /** + * Update a single item: merge with existing item. + * Will fail when the item has no id, or when there does not exist an item + * with the same id. + * @param {Object} item + * @return {String} id + * @private + */ + DataSet.prototype._updateItem = function (item) { + var id = item[this._fieldId]; + if (id == undefined) { + throw new Error('Cannot update item: item has no id (item: ' + JSON.stringify(item) + ')'); + } + var d = this._data[id]; + if (!d) { + // item doesn't exist + throw new Error('Cannot update item: no item with id ' + id + ' found'); + } - return function (mom) { - var output = ""; - for (i = 0; i < length; i++) { - output += array[i] instanceof Function ? array[i].call(mom, format) : array[i]; - } - return output; - }; + // merge with current item + for (var field in item) { + if (item.hasOwnProperty(field)) { + var fieldType = this._type[field]; // type may be undefined + d[field] = util.convert(item[field], fieldType); } + } - // format date using native date object - function formatMoment(m, format) { - - if (!m.isValid()) { - return m.lang().invalidDate(); - } + return id; + }; - format = expandFormat(format, m.lang()); + /** + * Get an array with the column names of a Google DataTable + * @param {DataTable} dataTable + * @return {String[]} columnNames + * @private + */ + DataSet.prototype._getColumnNames = function (dataTable) { + var columns = []; + for (var col = 0, cols = dataTable.getNumberOfColumns(); col < cols; col++) { + columns[col] = dataTable.getColumnId(col) || dataTable.getColumnLabel(col); + } + return columns; + }; - if (!formatFunctions[format]) { - formatFunctions[format] = makeFormatFunction(format); - } + /** + * Append an item as a row to the dataTable + * @param dataTable + * @param columns + * @param item + * @private + */ + DataSet.prototype._appendRow = function (dataTable, columns, item) { + var row = dataTable.addRow(); - return formatFunctions[format](m); - } + for (var col = 0, cols = columns.length; col < cols; col++) { + var field = columns[col]; + dataTable.setValue(row, col, item[field]); + } + }; - function expandFormat(format, lang) { - var i = 5; + module.exports = DataSet; - function replaceLongDateFormatTokens(input) { - return lang.longDateFormat(input) || input; - } - localFormattingTokens.lastIndex = 0; - while (i >= 0 && localFormattingTokens.test(format)) { - format = format.replace(localFormattingTokens, replaceLongDateFormatTokens); - localFormattingTokens.lastIndex = 0; - i -= 1; - } +/***/ }, +/* 4 */ +/***/ function(module, exports, __webpack_require__) { - return format; - } + var util = __webpack_require__(1); + var DataSet = __webpack_require__(3); + /** + * DataView + * + * a dataview offers a filtered view on a dataset or an other dataview. + * + * @param {DataSet | DataView} data + * @param {Object} [options] Available options: see method get + * + * @constructor DataView + */ + function DataView (data, options) { + this._data = null; + this._ids = {}; // ids of the items currently in memory (just contains a boolean true) + this._options = options || {}; + this._fieldId = 'id'; // name of the field containing id + this._subscribers = {}; // event subscribers - /************************************ - Parsing - ************************************/ + var me = this; + this.listener = function () { + me._onEvent.apply(me, arguments); + }; + this.setData(data); + } - // get the regex to find the next token - function getParseRegexForToken(token, config) { - var a, strict = config._strict; - switch (token) { - case 'Q': - return parseTokenOneDigit; - case 'DDDD': - return parseTokenThreeDigits; - case 'YYYY': - case 'GGGG': - case 'gggg': - return strict ? parseTokenFourDigits : parseTokenOneToFourDigits; - case 'Y': - case 'G': - case 'g': - return parseTokenSignedNumber; - case 'YYYYYY': - case 'YYYYY': - case 'GGGGG': - case 'ggggg': - return strict ? parseTokenSixDigits : parseTokenOneToSixDigits; - case 'S': - if (strict) { return parseTokenOneDigit; } - /* falls through */ - case 'SS': - if (strict) { return parseTokenTwoDigits; } - /* falls through */ - case 'SSS': - if (strict) { return parseTokenThreeDigits; } - /* falls through */ - case 'DDD': - return parseTokenOneToThreeDigits; - case 'MMM': - case 'MMMM': - case 'dd': - case 'ddd': - case 'dddd': - return parseTokenWord; - case 'a': - case 'A': - return getLangDefinition(config._l)._meridiemParse; - case 'X': - return parseTokenTimestampMs; - case 'Z': - case 'ZZ': - return parseTokenTimezone; - case 'T': - return parseTokenT; - case 'SSSS': - return parseTokenDigits; - case 'MM': - case 'DD': - case 'YY': - case 'GG': - case 'gg': - case 'HH': - case 'hh': - case 'mm': - case 'ss': - case 'ww': - case 'WW': - return strict ? parseTokenTwoDigits : parseTokenOneOrTwoDigits; - case 'M': - case 'D': - case 'd': - case 'H': - case 'h': - case 'm': - case 's': - case 'w': - case 'W': - case 'e': - case 'E': - return parseTokenOneOrTwoDigits; - case 'Do': - return parseTokenOrdinal; - default : - a = new RegExp(regexpEscape(unescapeFormat(token.replace('\\', '')), "i")); - return a; - } - } + // TODO: implement a function .config() to dynamically update things like configured filter + // and trigger changes accordingly - function timezoneMinutesFromString(string) { - string = string || ""; - var possibleTzMatches = (string.match(parseTokenTimezone) || []), - tzChunk = possibleTzMatches[possibleTzMatches.length - 1] || [], - parts = (tzChunk + '').match(parseTimezoneChunker) || ['-', 0, 0], - minutes = +(parts[1] * 60) + toInt(parts[2]); + /** + * Set a data source for the view + * @param {DataSet | DataView} data + */ + DataView.prototype.setData = function (data) { + var ids, i, len; - return parts[0] === '+' ? -minutes : minutes; + if (this._data) { + // unsubscribe from current dataset + if (this._data.unsubscribe) { + this._data.unsubscribe('*', this.listener); } - // function to convert string input to date - function addTimeToArrayFromToken(token, input, config) { - var a, datePartArray = config._a; + // trigger a remove of all items in memory + ids = []; + for (var id in this._ids) { + if (this._ids.hasOwnProperty(id)) { + ids.push(id); + } + } + this._ids = {}; + this._trigger('remove', {items: ids}); + } - switch (token) { - // QUARTER - case 'Q': - if (input != null) { - datePartArray[MONTH] = (toInt(input) - 1) * 3; - } - break; - // MONTH - case 'M' : // fall through to MM - case 'MM' : - if (input != null) { - datePartArray[MONTH] = toInt(input) - 1; - } - break; - case 'MMM' : // fall through to MMMM - case 'MMMM' : - a = getLangDefinition(config._l).monthsParse(input); - // if we didn't find a month name, mark the date as invalid. - if (a != null) { - datePartArray[MONTH] = a; - } else { - config._pf.invalidMonth = input; - } - break; - // DAY OF MONTH - case 'D' : // fall through to DD - case 'DD' : - if (input != null) { - datePartArray[DATE] = toInt(input); - } - break; - case 'Do' : - if (input != null) { - datePartArray[DATE] = toInt(parseInt(input, 10)); - } - break; - // DAY OF YEAR - case 'DDD' : // fall through to DDDD - case 'DDDD' : - if (input != null) { - config._dayOfYear = toInt(input); - } + this._data = data; - break; - // YEAR - case 'YY' : - datePartArray[YEAR] = moment.parseTwoDigitYear(input); - break; - case 'YYYY' : - case 'YYYYY' : - case 'YYYYYY' : - datePartArray[YEAR] = toInt(input); - break; - // AM / PM - case 'a' : // fall through to A - case 'A' : - config._isPm = getLangDefinition(config._l).isPM(input); - break; - // 24 HOUR - case 'H' : // fall through to hh - case 'HH' : // fall through to hh - case 'h' : // fall through to hh - case 'hh' : - datePartArray[HOUR] = toInt(input); - break; - // MINUTE - case 'm' : // fall through to mm - case 'mm' : - datePartArray[MINUTE] = toInt(input); - break; - // SECOND - case 's' : // fall through to ss - case 'ss' : - datePartArray[SECOND] = toInt(input); - break; - // MILLISECOND - case 'S' : - case 'SS' : - case 'SSS' : - case 'SSSS' : - datePartArray[MILLISECOND] = toInt(('0.' + input) * 1000); - break; - // UNIX TIMESTAMP WITH MS - case 'X': - config._d = new Date(parseFloat(input) * 1000); - break; - // TIMEZONE - case 'Z' : // fall through to ZZ - case 'ZZ' : - config._useUTC = true; - config._tzm = timezoneMinutesFromString(input); - break; - // WEEKDAY - human - case 'dd': - case 'ddd': - case 'dddd': - a = getLangDefinition(config._l).weekdaysParse(input); - // if we didn't get a weekday name, mark the date as invalid - if (a != null) { - config._w = config._w || {}; - config._w['d'] = a; - } else { - config._pf.invalidWeekday = input; - } - break; - // WEEK, WEEK DAY - numeric - case 'w': - case 'ww': - case 'W': - case 'WW': - case 'd': - case 'e': - case 'E': - token = token.substr(0, 1); - /* falls through */ - case 'gggg': - case 'GGGG': - case 'GGGGG': - token = token.substr(0, 2); - if (input) { - config._w = config._w || {}; - config._w[token] = toInt(input); - } - break; - case 'gg': - case 'GG': - config._w = config._w || {}; - config._w[token] = moment.parseTwoDigitYear(input); - } - } + if (this._data) { + // update fieldId + this._fieldId = this._options.fieldId || + (this._data && this._data.options && this._data.options.fieldId) || + 'id'; - function dayOfYearFromWeekInfo(config) { - var w, weekYear, week, weekday, dow, doy, temp, lang; + // trigger an add of all added items + ids = this._data.getIds({filter: this._options && this._options.filter}); + for (i = 0, len = ids.length; i < len; i++) { + id = ids[i]; + this._ids[id] = true; + } + this._trigger('add', {items: ids}); - w = config._w; - if (w.GG != null || w.W != null || w.E != null) { - dow = 1; - doy = 4; + // subscribe to new dataset + if (this._data.on) { + this._data.on('*', this.listener); + } + } + }; - // TODO: We need to take the current isoWeekYear, but that depends on - // how we interpret now (local, utc, fixed offset). So create - // a now version of current config (take local/utc/offset flags, and - // create now). - weekYear = dfl(w.GG, config._a[YEAR], weekOfYear(moment(), 1, 4).year); - week = dfl(w.W, 1); - weekday = dfl(w.E, 1); - } else { - lang = getLangDefinition(config._l); - dow = lang._week.dow; - doy = lang._week.doy; + /** + * Get data from the data view + * + * Usage: + * + * get() + * get(options: Object) + * get(options: Object, data: Array | DataTable) + * + * get(id: Number) + * get(id: Number, options: Object) + * get(id: Number, options: Object, data: Array | DataTable) + * + * get(ids: Number[]) + * get(ids: Number[], options: Object) + * get(ids: Number[], options: Object, data: Array | DataTable) + * + * Where: + * + * {Number | String} id The id of an item + * {Number[] | String{}} ids An array with ids of items + * {Object} options An Object with options. Available options: + * {String} [type] Type of data to be returned. Can + * be 'DataTable' or 'Array' (default) + * {Object.} [convert] + * {String[]} [fields] field names to be returned + * {function} [filter] filter items + * {String | function} [order] Order the items by + * a field name or custom sort function. + * {Array | DataTable} [data] If provided, items will be appended to this + * array or table. Required in case of Google + * DataTable. + * @param args + */ + DataView.prototype.get = function (args) { + var me = this; - weekYear = dfl(w.gg, config._a[YEAR], weekOfYear(moment(), dow, doy).year); - week = dfl(w.w, 1); + // parse the arguments + var ids, options, data; + var firstType = util.getType(arguments[0]); + if (firstType == 'String' || firstType == 'Number' || firstType == 'Array') { + // get(id(s) [, options] [, data]) + ids = arguments[0]; // can be a single id or an array with ids + options = arguments[1]; + data = arguments[2]; + } + else { + // get([, options] [, data]) + options = arguments[0]; + data = arguments[1]; + } - if (w.d != null) { - // weekday -- low day numbers are considered next week - weekday = w.d; - if (weekday < dow) { - ++week; - } - } else if (w.e != null) { - // local weekday -- counting starts from begining of week - weekday = w.e + dow; - } else { - // default to begining of week - weekday = dow; - } - } - temp = dayOfYearFromWeeks(weekYear, week, weekday, doy, dow); + // extend the options with the default options and provided options + var viewOptions = util.extend({}, this._options, options); - config._a[YEAR] = temp.year; - config._dayOfYear = temp.dayOfYear; + // create a combined filter method when needed + if (this._options.filter && options && options.filter) { + viewOptions.filter = function (item) { + return me._options.filter(item) && options.filter(item); } + } - // convert an array to a date. - // the array should mirror the parameters below - // note: all values past the year are optional and will default to the lowest possible value. - // [year, month, day , hour, minute, second, millisecond] - function dateFromConfig(config) { - var i, date, input = [], currentDate, yearToUse; - - if (config._d) { - return; - } - - currentDate = currentDateArray(config); + // build up the call to the linked data set + var getArguments = []; + if (ids != undefined) { + getArguments.push(ids); + } + getArguments.push(viewOptions); + getArguments.push(data); - //compute day of the year from weeks and weekdays - if (config._w && config._a[DATE] == null && config._a[MONTH] == null) { - dayOfYearFromWeekInfo(config); - } + return this._data && this._data.get.apply(this._data, getArguments); + }; - //if the day of the year is set, figure out what it is - if (config._dayOfYear) { - yearToUse = dfl(config._a[YEAR], currentDate[YEAR]); + /** + * Get ids of all items or from a filtered set of items. + * @param {Object} [options] An Object with options. Available options: + * {function} [filter] filter items + * {String | function} [order] Order the items by + * a field name or custom sort function. + * @return {Array} ids + */ + DataView.prototype.getIds = function (options) { + var ids; - if (config._dayOfYear > daysInYear(yearToUse)) { - config._pf._overflowDayOfYear = true; - } + if (this._data) { + var defaultFilter = this._options.filter; + var filter; - date = makeUTCDate(yearToUse, 0, config._dayOfYear); - config._a[MONTH] = date.getUTCMonth(); - config._a[DATE] = date.getUTCDate(); + if (options && options.filter) { + if (defaultFilter) { + filter = function (item) { + return defaultFilter(item) && options.filter(item); } + } + else { + filter = options.filter; + } + } + else { + filter = defaultFilter; + } - // Default to current date. - // * if no year, month, day of month are given, default to today - // * if day of month is given, default month and year - // * if month is given, default only year - // * if year is given, don't default anything - for (i = 0; i < 3 && config._a[i] == null; ++i) { - config._a[i] = input[i] = currentDate[i]; - } + ids = this._data.getIds({ + filter: filter, + order: options && options.order + }); + } + else { + ids = []; + } - // Zero out whatever was not defaulted, including time - for (; i < 7; i++) { - config._a[i] = input[i] = (config._a[i] == null) ? (i === 2 ? 1 : 0) : config._a[i]; - } + return ids; + }; - config._d = (config._useUTC ? makeUTCDate : makeDate).apply(null, input); - // Apply timezone offset from input. The actual zone can be changed - // with parseZone. - if (config._tzm != null) { - config._d.setUTCMinutes(config._d.getUTCMinutes() + config._tzm); - } - } - - function dateFromObject(config) { - var normalizedInput; - - if (config._d) { - return; - } - - normalizedInput = normalizeObjectUnits(config._i); - config._a = [ - normalizedInput.year, - normalizedInput.month, - normalizedInput.day, - normalizedInput.hour, - normalizedInput.minute, - normalizedInput.second, - normalizedInput.millisecond - ]; - - dateFromConfig(config); - } - - function currentDateArray(config) { - var now = new Date(); - if (config._useUTC) { - return [ - now.getUTCFullYear(), - now.getUTCMonth(), - now.getUTCDate() - ]; - } else { - return [now.getFullYear(), now.getMonth(), now.getDate()]; - } - } + /** + * Get the DataSet to which this DataView is connected. In case there is a chain + * of multiple DataViews, the root DataSet of this chain is returned. + * @return {DataSet} dataSet + */ + DataView.prototype.getDataSet = function () { + var dataSet = this; + while (dataSet instanceof DataView) { + dataSet = dataSet._data; + } + return dataSet || null; + }; - // date from string and format string - function makeDateFromStringAndFormat(config) { + /** + * Event listener. Will propagate all events from the connected data set to + * the subscribers of the DataView, but will filter the items and only trigger + * when there are changes in the filtered data set. + * @param {String} event + * @param {Object | null} params + * @param {String} senderId + * @private + */ + DataView.prototype._onEvent = function (event, params, senderId) { + var i, len, id, item, + ids = params && params.items, + data = this._data, + added = [], + updated = [], + removed = []; - if (config._f === moment.ISO_8601) { - parseISO(config); - return; + if (ids && data) { + switch (event) { + case 'add': + // filter the ids of the added items + for (i = 0, len = ids.length; i < len; i++) { + id = ids[i]; + item = this.get(id); + if (item) { + this._ids[id] = true; + added.push(id); + } } - config._a = []; - config._pf.empty = true; - - // This array is used to make a Date, either with `new Date` or `Date.UTC` - var lang = getLangDefinition(config._l), - string = '' + config._i, - i, parsedInput, tokens, token, skipped, - stringLength = string.length, - totalParsedInputLength = 0; + break; - tokens = expandFormat(config._f, lang).match(formattingTokens) || []; + case 'update': + // determine the event from the views viewpoint: an updated + // item can be added, updated, or removed from this view. + for (i = 0, len = ids.length; i < len; i++) { + id = ids[i]; + item = this.get(id); - for (i = 0; i < tokens.length; i++) { - token = tokens[i]; - parsedInput = (string.match(getParseRegexForToken(token, config)) || [])[0]; - if (parsedInput) { - skipped = string.substr(0, string.indexOf(parsedInput)); - if (skipped.length > 0) { - config._pf.unusedInput.push(skipped); - } - string = string.slice(string.indexOf(parsedInput) + parsedInput.length); - totalParsedInputLength += parsedInput.length; + if (item) { + if (this._ids[id]) { + updated.push(id); } - // don't parse if it's not a known token - if (formatTokenFunctions[token]) { - if (parsedInput) { - config._pf.empty = false; - } - else { - config._pf.unusedTokens.push(token); - } - addTimeToArrayFromToken(token, parsedInput, config); + else { + this._ids[id] = true; + added.push(id); } - else if (config._strict && !parsedInput) { - config._pf.unusedTokens.push(token); + } + else { + if (this._ids[id]) { + delete this._ids[id]; + removed.push(id); + } + else { + // nothing interesting for me :-( } + } } - // add remaining unparsed input length to the string - config._pf.charsLeftOver = stringLength - totalParsedInputLength; - if (string.length > 0) { - config._pf.unusedInput.push(string); - } + break; - // handle am pm - if (config._isPm && config._a[HOUR] < 12) { - config._a[HOUR] += 12; - } - // if is 12 am, change hours to 0 - if (config._isPm === false && config._a[HOUR] === 12) { - config._a[HOUR] = 0; + case 'remove': + // filter the ids of the removed items + for (i = 0, len = ids.length; i < len; i++) { + id = ids[i]; + if (this._ids[id]) { + delete this._ids[id]; + removed.push(id); + } } - dateFromConfig(config); - checkOverflow(config); + break; } - function unescapeFormat(s) { - return s.replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g, function (matched, p1, p2, p3, p4) { - return p1 || p2 || p3 || p4; - }); + if (added.length) { + this._trigger('add', {items: added}, senderId); } - - // Code from http://stackoverflow.com/questions/3561493/is-there-a-regexp-escape-function-in-javascript - function regexpEscape(s) { - return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'); + if (updated.length) { + this._trigger('update', {items: updated}, senderId); + } + if (removed.length) { + this._trigger('remove', {items: removed}, senderId); } + } + }; - // date from string and array of format strings - function makeDateFromStringAndArray(config) { - var tempConfig, - bestMoment, + // copy subscription functionality from DataSet + DataView.prototype.on = DataSet.prototype.on; + DataView.prototype.off = DataSet.prototype.off; + DataView.prototype._trigger = DataSet.prototype._trigger; - scoreToBeat, - i, - currentScore; + // TODO: make these functions deprecated (replaced with `on` and `off` since version 0.5) + DataView.prototype.subscribe = DataView.prototype.on; + DataView.prototype.unsubscribe = DataView.prototype.off; - if (config._f.length === 0) { - config._pf.invalidFormat = true; - config._d = new Date(NaN); - return; - } + module.exports = DataView; - for (i = 0; i < config._f.length; i++) { - currentScore = 0; - tempConfig = extend({}, config); - tempConfig._pf = defaultParsingFlags(); - tempConfig._f = config._f[i]; - makeDateFromStringAndFormat(tempConfig); +/***/ }, +/* 5 */ +/***/ function(module, exports, __webpack_require__) { - if (!isValid(tempConfig)) { - continue; - } + var Emitter = __webpack_require__(46); + var DataSet = __webpack_require__(3); + var DataView = __webpack_require__(4); + var util = __webpack_require__(1); + var Point3d = __webpack_require__(9); + var Point2d = __webpack_require__(8); + var Camera = __webpack_require__(6); + var Filter = __webpack_require__(7); + var Slider = __webpack_require__(10); + var StepNumber = __webpack_require__(11); - // if there is any input that was not parsed add a penalty for that format - currentScore += tempConfig._pf.charsLeftOver; + /** + * @constructor Graph3d + * Graph3d displays data in 3d. + * + * Graph3d is developed in javascript as a Google Visualization Chart. + * + * @param {Element} container The DOM element in which the Graph3d will + * be created. Normally a div element. + * @param {DataSet | DataView | Array} [data] + * @param {Object} [options] + */ + function Graph3d(container, data, options) { + if (!(this instanceof Graph3d)) { + throw new SyntaxError('Constructor must be called with the new operator'); + } - //or tokens - currentScore += tempConfig._pf.unusedTokens.length * 10; + // create variables and set default values + this.containerElement = container; + this.width = '400px'; + this.height = '400px'; + this.margin = 10; // px + this.defaultXCenter = '55%'; + this.defaultYCenter = '50%'; - tempConfig._pf.score = currentScore; + this.xLabel = 'x'; + this.yLabel = 'y'; + this.zLabel = 'z'; + this.filterLabel = 'time'; + this.legendLabel = 'value'; - if (scoreToBeat == null || currentScore < scoreToBeat) { - scoreToBeat = currentScore; - bestMoment = tempConfig; - } - } + this.style = Graph3d.STYLE.DOT; + this.showPerspective = true; + this.showGrid = true; + this.keepAspectRatio = true; + this.showShadow = false; + this.showGrayBottom = false; // TODO: this does not work correctly + this.showTooltip = false; + this.verticalRatio = 0.5; // 0.1 to 1.0, where 1.0 results in a 'cube' - extend(config, bestMoment || tempConfig); - } - - // date from iso format - function parseISO(config) { - var i, l, - string = config._i, - match = isoRegex.exec(string); + this.animationInterval = 1000; // milliseconds + this.animationPreload = false; - if (match) { - config._pf.iso = true; - for (i = 0, l = isoDates.length; i < l; i++) { - if (isoDates[i][1].exec(string)) { - // match[5] should be "T" or undefined - config._f = isoDates[i][0] + (match[6] || " "); - break; - } - } - for (i = 0, l = isoTimes.length; i < l; i++) { - if (isoTimes[i][1].exec(string)) { - config._f += isoTimes[i][0]; - break; - } - } - if (string.match(parseTokenTimezone)) { - config._f += "Z"; - } - makeDateFromStringAndFormat(config); - } else { - config._isValid = false; - } - } + this.camera = new Camera(); + this.eye = new Point3d(0, 0, -1); // TODO: set eye.z about 3/4 of the width of the window? - // date from iso format or fallback - function makeDateFromString(config) { - parseISO(config); - if (config._isValid === false) { - delete config._isValid; - moment.createFromInputFallback(config); - } - } + this.dataTable = null; // The original data table + this.dataPoints = null; // The table with point objects - function makeDateFromInput(config) { - var input = config._i, - matched = aspNetJsonRegex.exec(input); + // the column indexes + this.colX = undefined; + this.colY = undefined; + this.colZ = undefined; + this.colValue = undefined; + this.colFilter = undefined; - if (input === undefined) { - config._d = new Date(); - } else if (matched) { - config._d = new Date(+matched[1]); - } else if (typeof input === 'string') { - makeDateFromString(config); - } else if (isArray(input)) { - config._a = input.slice(0); - dateFromConfig(config); - } else if (isDate(input)) { - config._d = new Date(+input); - } else if (typeof(input) === 'object') { - dateFromObject(config); - } else if (typeof(input) === 'number') { - // from milliseconds - config._d = new Date(input); - } else { - moment.createFromInputFallback(config); - } - } + this.xMin = 0; + this.xStep = undefined; // auto by default + this.xMax = 1; + this.yMin = 0; + this.yStep = undefined; // auto by default + this.yMax = 1; + this.zMin = 0; + this.zStep = undefined; // auto by default + this.zMax = 1; + this.valueMin = 0; + this.valueMax = 1; + this.xBarWidth = 1; + this.yBarWidth = 1; + // TODO: customize axis range - function makeDate(y, m, d, h, M, s, ms) { - //can't just apply() to create a date: - //http://stackoverflow.com/questions/181348/instantiating-a-javascript-object-by-calling-prototype-constructor-apply - var date = new Date(y, m, d, h, M, s, ms); + // constants + this.colorAxis = '#4D4D4D'; + this.colorGrid = '#D3D3D3'; + this.colorDot = '#7DC1FF'; + this.colorDotBorder = '#3267D2'; - //the date constructor doesn't accept years < 1970 - if (y < 1970) { - date.setFullYear(y); - } - return date; - } + // create a frame and canvas + this.create(); - function makeUTCDate(y) { - var date = new Date(Date.UTC.apply(null, arguments)); - if (y < 1970) { - date.setUTCFullYear(y); - } - return date; - } + // apply options (also when undefined) + this.setOptions(options); - function parseWeekday(input, language) { - if (typeof input === 'string') { - if (!isNaN(input)) { - input = parseInt(input, 10); - } - else { - input = language.weekdaysParse(input); - if (typeof input !== 'number') { - return null; - } - } - } - return input; - } + // apply data + if (data) { + this.setData(data); + } + } - /************************************ - Relative Time - ************************************/ + // Extend Graph3d with an Emitter mixin + Emitter(Graph3d.prototype); + /** + * Calculate the scaling values, dependent on the range in x, y, and z direction + */ + Graph3d.prototype._setScale = function() { + this.scale = new Point3d(1 / (this.xMax - this.xMin), + 1 / (this.yMax - this.yMin), + 1 / (this.zMax - this.zMin)); - // helper function for moment.fn.from, moment.fn.fromNow, and moment.duration.fn.humanize - function substituteTimeAgo(string, number, withoutSuffix, isFuture, lang) { - return lang.relativeTime(number || 1, !!withoutSuffix, string, isFuture); + // keep aspect ration between x and y scale if desired + if (this.keepAspectRatio) { + if (this.scale.x < this.scale.y) { + //noinspection JSSuspiciousNameCombination + this.scale.y = this.scale.x; } - - function relativeTime(milliseconds, withoutSuffix, lang) { - var seconds = round(Math.abs(milliseconds) / 1000), - minutes = round(seconds / 60), - hours = round(minutes / 60), - days = round(hours / 24), - years = round(days / 365), - args = seconds < relativeTimeThresholds.s && ['s', seconds] || - minutes === 1 && ['m'] || - minutes < relativeTimeThresholds.m && ['mm', minutes] || - hours === 1 && ['h'] || - hours < relativeTimeThresholds.h && ['hh', hours] || - days === 1 && ['d'] || - days <= relativeTimeThresholds.dd && ['dd', days] || - days <= relativeTimeThresholds.dm && ['M'] || - days < relativeTimeThresholds.dy && ['MM', round(days / 30)] || - years === 1 && ['y'] || ['yy', years]; - args[2] = withoutSuffix; - args[3] = milliseconds > 0; - args[4] = lang; - return substituteTimeAgo.apply({}, args); + else { + //noinspection JSSuspiciousNameCombination + this.scale.x = this.scale.y; } + } + // scale the vertical axis + this.scale.z *= this.verticalRatio; + // TODO: can this be automated? verticalRatio? - /************************************ - Week of Year - ************************************/ + // determine scale for (optional) value + this.scale.value = 1 / (this.valueMax - this.valueMin); + // position the camera arm + var xCenter = (this.xMax + this.xMin) / 2 * this.scale.x; + var yCenter = (this.yMax + this.yMin) / 2 * this.scale.y; + var zCenter = (this.zMax + this.zMin) / 2 * this.scale.z; + this.camera.setArmLocation(xCenter, yCenter, zCenter); + }; - // firstDayOfWeek 0 = sun, 6 = sat - // the day of the week that starts the week - // (usually sunday or monday) - // firstDayOfWeekOfYear 0 = sun, 6 = sat - // the first week is the week that contains the first - // of this day of the week - // (eg. ISO weeks use thursday (4)) - function weekOfYear(mom, firstDayOfWeek, firstDayOfWeekOfYear) { - var end = firstDayOfWeekOfYear - firstDayOfWeek, - daysToDayOfWeek = firstDayOfWeekOfYear - mom.day(), - adjustedMoment; + /** + * Convert a 3D location to a 2D location on screen + * http://en.wikipedia.org/wiki/3D_projection + * @param {Point3d} point3d A 3D point with parameters x, y, z + * @return {Point2d} point2d A 2D point with parameters x, y + */ + Graph3d.prototype._convert3Dto2D = function(point3d) { + var translation = this._convertPointToTranslation(point3d); + return this._convertTranslationToScreen(translation); + }; - if (daysToDayOfWeek > end) { - daysToDayOfWeek -= 7; - } + /** + * Convert a 3D location its translation seen from the camera + * http://en.wikipedia.org/wiki/3D_projection + * @param {Point3d} point3d A 3D point with parameters x, y, z + * @return {Point3d} translation A 3D point with parameters x, y, z This is + * the translation of the point, seen from the + * camera + */ + Graph3d.prototype._convertPointToTranslation = function(point3d) { + var ax = point3d.x * this.scale.x, + ay = point3d.y * this.scale.y, + az = point3d.z * this.scale.z, - if (daysToDayOfWeek < end - 7) { - daysToDayOfWeek += 7; - } + cx = this.camera.getCameraLocation().x, + cy = this.camera.getCameraLocation().y, + cz = this.camera.getCameraLocation().z, - adjustedMoment = moment(mom).add('d', daysToDayOfWeek); - return { - week: Math.ceil(adjustedMoment.dayOfYear() / 7), - year: adjustedMoment.year() - }; - } + // calculate angles + sinTx = Math.sin(this.camera.getCameraRotation().x), + cosTx = Math.cos(this.camera.getCameraRotation().x), + sinTy = Math.sin(this.camera.getCameraRotation().y), + cosTy = Math.cos(this.camera.getCameraRotation().y), + sinTz = Math.sin(this.camera.getCameraRotation().z), + cosTz = Math.cos(this.camera.getCameraRotation().z), - //http://en.wikipedia.org/wiki/ISO_week_date#Calculating_a_date_given_the_year.2C_week_number_and_weekday - function dayOfYearFromWeeks(year, week, weekday, firstDayOfWeekOfYear, firstDayOfWeek) { - var d = makeUTCDate(year, 0, 1).getUTCDay(), daysToAdd, dayOfYear; + // calculate translation + dx = cosTy * (sinTz * (ay - cy) + cosTz * (ax - cx)) - sinTy * (az - cz), + dy = sinTx * (cosTy * (az - cz) + sinTy * (sinTz * (ay - cy) + cosTz * (ax - cx))) + cosTx * (cosTz * (ay - cy) - sinTz * (ax-cx)), + dz = cosTx * (cosTy * (az - cz) + sinTy * (sinTz * (ay - cy) + cosTz * (ax - cx))) - sinTx * (cosTz * (ay - cy) - sinTz * (ax-cx)); - d = d === 0 ? 7 : d; - weekday = weekday != null ? weekday : firstDayOfWeek; - daysToAdd = firstDayOfWeek - d + (d > firstDayOfWeekOfYear ? 7 : 0) - (d < firstDayOfWeek ? 7 : 0); - dayOfYear = 7 * (week - 1) + (weekday - firstDayOfWeek) + daysToAdd + 1; - - return { - year: dayOfYear > 0 ? year : year - 1, - dayOfYear: dayOfYear > 0 ? dayOfYear : daysInYear(year - 1) + dayOfYear - }; - } + return new Point3d(dx, dy, dz); + }; - /************************************ - Top Level Functions - ************************************/ + /** + * Convert a translation point to a point on the screen + * @param {Point3d} translation A 3D point with parameters x, y, z This is + * the translation of the point, seen from the + * camera + * @return {Point2d} point2d A 2D point with parameters x, y + */ + Graph3d.prototype._convertTranslationToScreen = function(translation) { + var ex = this.eye.x, + ey = this.eye.y, + ez = this.eye.z, + dx = translation.x, + dy = translation.y, + dz = translation.z; - function makeMoment(config) { - var input = config._i, - format = config._f; + // calculate position on screen from translation + var bx; + var by; + if (this.showPerspective) { + bx = (dx - ex) * (ez / dz); + by = (dy - ey) * (ez / dz); + } + else { + bx = dx * -(ez / this.camera.getArmLength()); + by = dy * -(ez / this.camera.getArmLength()); + } - if (input === null || (format === undefined && input === '')) { - return moment.invalid({nullInput: true}); - } + // shift and scale the point to the center of the screen + // use the width of the graph to scale both horizontally and vertically. + return new Point2d( + this.xcenter + bx * this.frame.canvas.clientWidth, + this.ycenter - by * this.frame.canvas.clientWidth); + }; - if (typeof input === 'string') { - config._i = input = getLangDefinition().preparse(input); - } + /** + * Set the background styling for the graph + * @param {string | {fill: string, stroke: string, strokeWidth: string}} backgroundColor + */ + Graph3d.prototype._setBackgroundColor = function(backgroundColor) { + var fill = 'white'; + var stroke = 'gray'; + var strokeWidth = 1; - if (moment.isMoment(input)) { - config = cloneMoment(input); + if (typeof(backgroundColor) === 'string') { + fill = backgroundColor; + stroke = 'none'; + strokeWidth = 0; + } + else if (typeof(backgroundColor) === 'object') { + if (backgroundColor.fill !== undefined) fill = backgroundColor.fill; + if (backgroundColor.stroke !== undefined) stroke = backgroundColor.stroke; + if (backgroundColor.strokeWidth !== undefined) strokeWidth = backgroundColor.strokeWidth; + } + else if (backgroundColor === undefined) { + // use use defaults + } + else { + throw 'Unsupported type of backgroundColor'; + } - config._d = new Date(+input._d); - } else if (format) { - if (isArray(format)) { - makeDateFromStringAndArray(config); - } else { - makeDateFromStringAndFormat(config); - } - } else { - makeDateFromInput(config); - } + this.frame.style.backgroundColor = fill; + this.frame.style.borderColor = stroke; + this.frame.style.borderWidth = strokeWidth + 'px'; + this.frame.style.borderStyle = 'solid'; + }; - return new Moment(config); - } - moment = function (input, format, lang, strict) { - var c; + /// enumerate the available styles + Graph3d.STYLE = { + BAR: 0, + BARCOLOR: 1, + BARSIZE: 2, + DOT : 3, + DOTLINE : 4, + DOTCOLOR: 5, + DOTSIZE: 6, + GRID : 7, + LINE: 8, + SURFACE : 9 + }; - if (typeof(lang) === "boolean") { - strict = lang; - lang = undefined; - } - // object construction must be done this way. - // https://github.com/moment/moment/issues/1423 - c = {}; - c._isAMomentObject = true; - c._i = input; - c._f = format; - c._l = lang; - c._strict = strict; - c._isUTC = false; - c._pf = defaultParsingFlags(); + /** + * Retrieve the style index from given styleName + * @param {string} styleName Style name such as 'dot', 'grid', 'dot-line' + * @return {Number} styleNumber Enumeration value representing the style, or -1 + * when not found + */ + Graph3d.prototype._getStyleNumber = function(styleName) { + switch (styleName) { + case 'dot': return Graph3d.STYLE.DOT; + case 'dot-line': return Graph3d.STYLE.DOTLINE; + case 'dot-color': return Graph3d.STYLE.DOTCOLOR; + case 'dot-size': return Graph3d.STYLE.DOTSIZE; + case 'line': return Graph3d.STYLE.LINE; + case 'grid': return Graph3d.STYLE.GRID; + case 'surface': return Graph3d.STYLE.SURFACE; + case 'bar': return Graph3d.STYLE.BAR; + case 'bar-color': return Graph3d.STYLE.BARCOLOR; + case 'bar-size': return Graph3d.STYLE.BARSIZE; + } - return makeMoment(c); - }; + return -1; + }; - moment.suppressDeprecationWarnings = false; + /** + * Determine the indexes of the data columns, based on the given style and data + * @param {DataSet} data + * @param {Number} style + */ + Graph3d.prototype._determineColumnIndexes = function(data, style) { + if (this.style === Graph3d.STYLE.DOT || + this.style === Graph3d.STYLE.DOTLINE || + this.style === Graph3d.STYLE.LINE || + this.style === Graph3d.STYLE.GRID || + this.style === Graph3d.STYLE.SURFACE || + this.style === Graph3d.STYLE.BAR) { + // 3 columns expected, and optionally a 4th with filter values + this.colX = 0; + this.colY = 1; + this.colZ = 2; + this.colValue = undefined; - moment.createFromInputFallback = deprecate( - "moment construction falls back to js Date. This is " + - "discouraged and will be removed in upcoming major " + - "release. Please refer to " + - "https://github.com/moment/moment/issues/1407 for more info.", - function (config) { - config._d = new Date(config._i); - }); + if (data.getNumberOfColumns() > 3) { + this.colFilter = 3; + } + } + else if (this.style === Graph3d.STYLE.DOTCOLOR || + this.style === Graph3d.STYLE.DOTSIZE || + this.style === Graph3d.STYLE.BARCOLOR || + this.style === Graph3d.STYLE.BARSIZE) { + // 4 columns expected, and optionally a 5th with filter values + this.colX = 0; + this.colY = 1; + this.colZ = 2; + this.colValue = 3; - // Pick a moment m from moments so that m[fn](other) is true for all - // other. This relies on the function fn to be transitive. - // - // moments should either be an array of moment objects or an array, whose - // first element is an array of moment objects. - function pickBy(fn, moments) { - var res, i; - if (moments.length === 1 && isArray(moments[0])) { - moments = moments[0]; - } - if (!moments.length) { - return moment(); - } - res = moments[0]; - for (i = 1; i < moments.length; ++i) { - if (moments[i][fn](res)) { - res = moments[i]; - } - } - return res; + if (data.getNumberOfColumns() > 4) { + this.colFilter = 4; } + } + else { + throw 'Unknown style "' + this.style + '"'; + } + }; - moment.min = function () { - var args = [].slice.call(arguments, 0); + Graph3d.prototype.getNumberOfRows = function(data) { + return data.length; + } - return pickBy('isBefore', args); - }; - moment.max = function () { - var args = [].slice.call(arguments, 0); + Graph3d.prototype.getNumberOfColumns = function(data) { + var counter = 0; + for (var column in data[0]) { + if (data[0].hasOwnProperty(column)) { + counter++; + } + } + return counter; + } - return pickBy('isAfter', args); - }; - // creating with utc - moment.utc = function (input, format, lang, strict) { - var c; + Graph3d.prototype.getDistinctValues = function(data, column) { + var distinctValues = []; + for (var i = 0; i < data.length; i++) { + if (distinctValues.indexOf(data[i][column]) == -1) { + distinctValues.push(data[i][column]); + } + } + return distinctValues; + } - if (typeof(lang) === "boolean") { - strict = lang; - lang = undefined; - } - // object construction must be done this way. - // https://github.com/moment/moment/issues/1423 - c = {}; - c._isAMomentObject = true; - c._useUTC = true; - c._isUTC = true; - c._l = lang; - c._i = input; - c._f = format; - c._strict = strict; - c._pf = defaultParsingFlags(); - return makeMoment(c).utc(); - }; + Graph3d.prototype.getColumnRange = function(data,column) { + var minMax = {min:data[0][column],max:data[0][column]}; + for (var i = 0; i < data.length; i++) { + if (minMax.min > data[i][column]) { minMax.min = data[i][column]; } + if (minMax.max < data[i][column]) { minMax.max = data[i][column]; } + } + return minMax; + }; - // creating with unix timestamp (in seconds) - moment.unix = function (input) { - return moment(input * 1000); - }; + /** + * Initialize the data from the data table. Calculate minimum and maximum values + * and column index values + * @param {Array | DataSet | DataView} rawData The data containing the items for the Graph. + * @param {Number} style Style Number + */ + Graph3d.prototype._dataInitialize = function (rawData, style) { + var me = this; - // duration - moment.duration = function (input, key) { - var duration = input, - // matching against regexp is expensive, do it on demand - match = null, - sign, - ret, - parseIso; + // unsubscribe from the dataTable + if (this.dataSet) { + this.dataSet.off('*', this._onChange); + } - if (moment.isDuration(input)) { - duration = { - ms: input._milliseconds, - d: input._days, - M: input._months - }; - } else if (typeof input === 'number') { - duration = {}; - if (key) { - duration[key] = input; - } else { - duration.milliseconds = input; - } - } else if (!!(match = aspNetTimeSpanJsonRegex.exec(input))) { - sign = (match[1] === "-") ? -1 : 1; - duration = { - y: 0, - d: toInt(match[DATE]) * sign, - h: toInt(match[HOUR]) * sign, - m: toInt(match[MINUTE]) * sign, - s: toInt(match[SECOND]) * sign, - ms: toInt(match[MILLISECOND]) * sign - }; - } else if (!!(match = isoDurationRegex.exec(input))) { - sign = (match[1] === "-") ? -1 : 1; - parseIso = function (inp) { - // We'd normally use ~~inp for this, but unfortunately it also - // converts floats to ints. - // inp may be undefined, so careful calling replace on it. - var res = inp && parseFloat(inp.replace(',', '.')); - // apply sign while we're at it - return (isNaN(res) ? 0 : res) * sign; - }; - duration = { - y: parseIso(match[2]), - M: parseIso(match[3]), - d: parseIso(match[4]), - h: parseIso(match[5]), - m: parseIso(match[6]), - s: parseIso(match[7]), - w: parseIso(match[8]) - }; - } + if (rawData === undefined) + return; - ret = new Duration(duration); + if (Array.isArray(rawData)) { + rawData = new DataSet(rawData); + } - if (moment.isDuration(input) && input.hasOwnProperty('_lang')) { - ret._lang = input._lang; - } + var data; + if (rawData instanceof DataSet || rawData instanceof DataView) { + data = rawData.get(); + } + else { + throw new Error('Array, DataSet, or DataView expected'); + } - return ret; - }; + if (data.length == 0) + return; - // version number - moment.version = VERSION; + this.dataSet = rawData; + this.dataTable = data; - // default format - moment.defaultFormat = isoFormat; + // subscribe to changes in the dataset + this._onChange = function () { + me.setData(me.dataSet); + }; + this.dataSet.on('*', this._onChange); - // constant that refers to the ISO standard - moment.ISO_8601 = function () {}; + // _determineColumnIndexes + // getNumberOfRows (points) + // getNumberOfColumns (x,y,z,v,t,t1,t2...) + // getDistinctValues (unique values?) + // getColumnRange - // Plugins that add properties should also add the key here (null value), - // so we can properly clone ourselves. - moment.momentProperties = momentProperties; + // determine the location of x,y,z,value,filter columns + this.colX = 'x'; + this.colY = 'y'; + this.colZ = 'z'; + this.colValue = 'style'; + this.colFilter = 'filter'; - // This function will be called whenever a moment is mutated. - // It is intended to keep the offset in sync with the timezone. - moment.updateOffset = function () {}; - // This function allows you to set a threshold for relative time strings - moment.relativeTimeThreshold = function(threshold, limit) { - if (relativeTimeThresholds[threshold] === undefined) { - return false; - } - relativeTimeThresholds[threshold] = limit; - return true; - }; - // This function will load languages and then set the global language. If - // no arguments are passed in, it will simply return the current global - // language key. - moment.lang = function (key, values) { - var r; - if (!key) { - return moment.fn._lang._abbr; - } - if (values) { - loadLang(normalizeLanguage(key), values); - } else if (values === null) { - unloadLang(key); - key = 'en'; - } else if (!languages[key]) { - getLangDefinition(key); - } - r = moment.duration.fn._lang = moment.fn._lang = getLangDefinition(key); - return r._abbr; - }; + // check if a filter column is provided + if (data[0].hasOwnProperty('filter')) { + if (this.dataFilter === undefined) { + this.dataFilter = new Filter(rawData, this.colFilter, this); + this.dataFilter.setOnLoadCallback(function() {me.redraw();}); + } + } - // returns language data - moment.langData = function (key) { - if (key && key._lang && key._lang._abbr) { - key = key._lang._abbr; - } - return getLangDefinition(key); - }; - // compare moment object - moment.isMoment = function (obj) { - return obj instanceof Moment || - (obj != null && obj.hasOwnProperty('_isAMomentObject')); - }; + var withBars = this.style == Graph3d.STYLE.BAR || + this.style == Graph3d.STYLE.BARCOLOR || + this.style == Graph3d.STYLE.BARSIZE; - // for typechecking Duration objects - moment.isDuration = function (obj) { - return obj instanceof Duration; - }; + // determine barWidth from data + if (withBars) { + if (this.defaultXBarWidth !== undefined) { + this.xBarWidth = this.defaultXBarWidth; + } + else { + var dataX = this.getDistinctValues(data,this.colX); + this.xBarWidth = (dataX[1] - dataX[0]) || 1; + } - for (i = lists.length - 1; i >= 0; --i) { - makeList(lists[i]); + if (this.defaultYBarWidth !== undefined) { + this.yBarWidth = this.defaultYBarWidth; + } + else { + var dataY = this.getDistinctValues(data,this.colY); + this.yBarWidth = (dataY[1] - dataY[0]) || 1; } + } - moment.normalizeUnits = function (units) { - return normalizeUnits(units); - }; + // calculate minimums and maximums + var xRange = this.getColumnRange(data,this.colX); + if (withBars) { + xRange.min -= this.xBarWidth / 2; + xRange.max += this.xBarWidth / 2; + } + this.xMin = (this.defaultXMin !== undefined) ? this.defaultXMin : xRange.min; + this.xMax = (this.defaultXMax !== undefined) ? this.defaultXMax : xRange.max; + if (this.xMax <= this.xMin) this.xMax = this.xMin + 1; + this.xStep = (this.defaultXStep !== undefined) ? this.defaultXStep : (this.xMax-this.xMin)/5; - moment.invalid = function (flags) { - var m = moment.utc(NaN); - if (flags != null) { - extend(m._pf, flags); - } - else { - m._pf.userInvalidated = true; - } + var yRange = this.getColumnRange(data,this.colY); + if (withBars) { + yRange.min -= this.yBarWidth / 2; + yRange.max += this.yBarWidth / 2; + } + this.yMin = (this.defaultYMin !== undefined) ? this.defaultYMin : yRange.min; + this.yMax = (this.defaultYMax !== undefined) ? this.defaultYMax : yRange.max; + if (this.yMax <= this.yMin) this.yMax = this.yMin + 1; + this.yStep = (this.defaultYStep !== undefined) ? this.defaultYStep : (this.yMax-this.yMin)/5; - return m; - }; + var zRange = this.getColumnRange(data,this.colZ); + this.zMin = (this.defaultZMin !== undefined) ? this.defaultZMin : zRange.min; + this.zMax = (this.defaultZMax !== undefined) ? this.defaultZMax : zRange.max; + if (this.zMax <= this.zMin) this.zMax = this.zMin + 1; + this.zStep = (this.defaultZStep !== undefined) ? this.defaultZStep : (this.zMax-this.zMin)/5; - moment.parseZone = function () { - return moment.apply(null, arguments).parseZone(); - }; + if (this.colValue !== undefined) { + var valueRange = this.getColumnRange(data,this.colValue); + this.valueMin = (this.defaultValueMin !== undefined) ? this.defaultValueMin : valueRange.min; + this.valueMax = (this.defaultValueMax !== undefined) ? this.defaultValueMax : valueRange.max; + if (this.valueMax <= this.valueMin) this.valueMax = this.valueMin + 1; + } - moment.parseTwoDigitYear = function (input) { - return toInt(input) + (toInt(input) > 68 ? 1900 : 2000); - }; + // set the scale dependent on the ranges. + this._setScale(); + }; - /************************************ - Moment Prototype - ************************************/ - extend(moment.fn = Moment.prototype, { + /** + * Filter the data based on the current filter + * @param {Array} data + * @return {Array} dataPoints Array with point objects which can be drawn on screen + */ + Graph3d.prototype._getDataPoints = function (data) { + // TODO: store the created matrix dataPoints in the filters instead of reloading each time + var x, y, i, z, obj, point; - clone : function () { - return moment(this); - }, + var dataPoints = []; - valueOf : function () { - return +this._d + ((this._offset || 0) * 60000); - }, + if (this.style === Graph3d.STYLE.GRID || + this.style === Graph3d.STYLE.SURFACE) { + // copy all values from the google data table to a matrix + // the provided values are supposed to form a grid of (x,y) positions - unix : function () { - return Math.floor(+this / 1000); - }, + // create two lists with all present x and y values + var dataX = []; + var dataY = []; + for (i = 0; i < this.getNumberOfRows(data); i++) { + x = data[i][this.colX] || 0; + y = data[i][this.colY] || 0; - toString : function () { - return this.clone().lang('en').format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ"); - }, + if (dataX.indexOf(x) === -1) { + dataX.push(x); + } + if (dataY.indexOf(y) === -1) { + dataY.push(y); + } + } - toDate : function () { - return this._offset ? new Date(+this) : this._d; - }, + function sortNumber(a, b) { + return a - b; + } + dataX.sort(sortNumber); + dataY.sort(sortNumber); - toISOString : function () { - var m = moment(this).utc(); - if (0 < m.year() && m.year() <= 9999) { - return formatMoment(m, 'YYYY-MM-DD[T]HH:mm:ss.SSS[Z]'); - } else { - return formatMoment(m, 'YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]'); - } - }, + // create a grid, a 2d matrix, with all values. + var dataMatrix = []; // temporary data matrix + for (i = 0; i < data.length; i++) { + x = data[i][this.colX] || 0; + y = data[i][this.colY] || 0; + z = data[i][this.colZ] || 0; - toArray : function () { - var m = this; - return [ - m.year(), - m.month(), - m.date(), - m.hours(), - m.minutes(), - m.seconds(), - m.milliseconds() - ]; - }, + var xIndex = dataX.indexOf(x); // TODO: implement Array().indexOf() for Internet Explorer + var yIndex = dataY.indexOf(y); - isValid : function () { - return isValid(this); - }, + if (dataMatrix[xIndex] === undefined) { + dataMatrix[xIndex] = []; + } - isDSTShifted : function () { + var point3d = new Point3d(); + point3d.x = x; + point3d.y = y; + point3d.z = z; - if (this._a) { - return this.isValid() && compareArrays(this._a, (this._isUTC ? moment.utc(this._a) : moment(this._a)).toArray()) > 0; - } + obj = {}; + obj.point = point3d; + obj.trans = undefined; + obj.screen = undefined; + obj.bottom = new Point3d(x, y, this.zMin); - return false; - }, + dataMatrix[xIndex][yIndex] = obj; - parsingFlags : function () { - return extend({}, this._pf); - }, + dataPoints.push(obj); + } - invalidAt: function () { - return this._pf.overflow; - }, + // fill in the pointers to the neighbors. + for (x = 0; x < dataMatrix.length; x++) { + for (y = 0; y < dataMatrix[x].length; y++) { + if (dataMatrix[x][y]) { + dataMatrix[x][y].pointRight = (x < dataMatrix.length-1) ? dataMatrix[x+1][y] : undefined; + dataMatrix[x][y].pointTop = (y < dataMatrix[x].length-1) ? dataMatrix[x][y+1] : undefined; + dataMatrix[x][y].pointCross = + (x < dataMatrix.length-1 && y < dataMatrix[x].length-1) ? + dataMatrix[x+1][y+1] : + undefined; + } + } + } + } + else { // 'dot', 'dot-line', etc. + // copy all values from the google data table to a list with Point3d objects + for (i = 0; i < data.length; i++) { + point = new Point3d(); + point.x = data[i][this.colX] || 0; + point.y = data[i][this.colY] || 0; + point.z = data[i][this.colZ] || 0; - utc : function () { - return this.zone(0); - }, + if (this.colValue !== undefined) { + point.value = data[i][this.colValue] || 0; + } - local : function () { - this.zone(0); - this._isUTC = false; - return this; - }, + obj = {}; + obj.point = point; + obj.bottom = new Point3d(point.x, point.y, this.zMin); + obj.trans = undefined; + obj.screen = undefined; - format : function (inputString) { - var output = formatMoment(this, inputString || moment.defaultFormat); - return this.lang().postformat(output); - }, + dataPoints.push(obj); + } + } - add : function (input, val) { - var dur; - // switch args to support add('s', 1) and add(1, 's') - if (typeof input === 'string' && typeof val === 'string') { - dur = moment.duration(isNaN(+val) ? +input : +val, isNaN(+val) ? val : input); - } else if (typeof input === 'string') { - dur = moment.duration(+val, input); - } else { - dur = moment.duration(input, val); - } - addOrSubtractDurationFromMoment(this, dur, 1); - return this; - }, + return dataPoints; + }; - subtract : function (input, val) { - var dur; - // switch args to support subtract('s', 1) and subtract(1, 's') - if (typeof input === 'string' && typeof val === 'string') { - dur = moment.duration(isNaN(+val) ? +input : +val, isNaN(+val) ? val : input); - } else if (typeof input === 'string') { - dur = moment.duration(+val, input); - } else { - dur = moment.duration(input, val); - } - addOrSubtractDurationFromMoment(this, dur, -1); - return this; - }, + /** + * Create the main frame for the Graph3d. + * This function is executed once when a Graph3d object is created. The frame + * contains a canvas, and this canvas contains all objects like the axis and + * nodes. + */ + Graph3d.prototype.create = function () { + // remove all elements from the container element. + while (this.containerElement.hasChildNodes()) { + this.containerElement.removeChild(this.containerElement.firstChild); + } - diff : function (input, units, asFloat) { - var that = makeAs(input, this), - zoneDiff = (this.zone() - that.zone()) * 6e4, - diff, output; + this.frame = document.createElement('div'); + this.frame.style.position = 'relative'; + this.frame.style.overflow = 'hidden'; - units = normalizeUnits(units); + // create the graph canvas (HTML canvas element) + this.frame.canvas = document.createElement( 'canvas' ); + this.frame.canvas.style.position = 'relative'; + this.frame.appendChild(this.frame.canvas); + //if (!this.frame.canvas.getContext) { + { + var noCanvas = document.createElement( 'DIV' ); + noCanvas.style.color = 'red'; + noCanvas.style.fontWeight = 'bold' ; + noCanvas.style.padding = '10px'; + noCanvas.innerHTML = 'Error: your browser does not support HTML canvas'; + this.frame.canvas.appendChild(noCanvas); + } - if (units === 'year' || units === 'month') { - // average number of days in the months in the given dates - diff = (this.daysInMonth() + that.daysInMonth()) * 432e5; // 24 * 60 * 60 * 1000 / 2 - // difference in months - output = ((this.year() - that.year()) * 12) + (this.month() - that.month()); - // adjust by taking difference in days, average number of days - // and dst in the given months. - output += ((this - moment(this).startOf('month')) - - (that - moment(that).startOf('month'))) / diff; - // same as above but with zones, to negate all dst - output -= ((this.zone() - moment(this).startOf('month').zone()) - - (that.zone() - moment(that).startOf('month').zone())) * 6e4 / diff; - if (units === 'year') { - output = output / 12; - } - } else { - diff = (this - that); - output = units === 'second' ? diff / 1e3 : // 1000 - units === 'minute' ? diff / 6e4 : // 1000 * 60 - units === 'hour' ? diff / 36e5 : // 1000 * 60 * 60 - units === 'day' ? (diff - zoneDiff) / 864e5 : // 1000 * 60 * 60 * 24, negate dst - units === 'week' ? (diff - zoneDiff) / 6048e5 : // 1000 * 60 * 60 * 24 * 7, negate dst - diff; - } - return asFloat ? output : absRound(output); - }, + this.frame.filter = document.createElement( 'div' ); + this.frame.filter.style.position = 'absolute'; + this.frame.filter.style.bottom = '0px'; + this.frame.filter.style.left = '0px'; + this.frame.filter.style.width = '100%'; + this.frame.appendChild(this.frame.filter); - from : function (time, withoutSuffix) { - return moment.duration(this.diff(time)).lang(this.lang()._abbr).humanize(!withoutSuffix); - }, + // add event listeners to handle moving and zooming the contents + var me = this; + var onmousedown = function (event) {me._onMouseDown(event);}; + var ontouchstart = function (event) {me._onTouchStart(event);}; + var onmousewheel = function (event) {me._onWheel(event);}; + var ontooltip = function (event) {me._onTooltip(event);}; + // TODO: these events are never cleaned up... can give a 'memory leakage' - fromNow : function (withoutSuffix) { - return this.from(moment(), withoutSuffix); - }, + util.addEventListener(this.frame.canvas, 'keydown', onkeydown); + util.addEventListener(this.frame.canvas, 'mousedown', onmousedown); + util.addEventListener(this.frame.canvas, 'touchstart', ontouchstart); + util.addEventListener(this.frame.canvas, 'mousewheel', onmousewheel); + util.addEventListener(this.frame.canvas, 'mousemove', ontooltip); - calendar : function (time) { - // We want to compare the start of today, vs this. - // Getting start-of-today depends on whether we're zone'd or not. - var now = time || moment(), - sod = makeAs(now, this).startOf('day'), - diff = this.diff(sod, 'days', true), - format = diff < -6 ? 'sameElse' : - diff < -1 ? 'lastWeek' : - diff < 0 ? 'lastDay' : - diff < 1 ? 'sameDay' : - diff < 2 ? 'nextDay' : - diff < 7 ? 'nextWeek' : 'sameElse'; - return this.format(this.lang().calendar(format, this)); - }, + // add the new graph to the container element + this.containerElement.appendChild(this.frame); + }; - isLeapYear : function () { - return isLeapYear(this.year()); - }, - isDST : function () { - return (this.zone() < this.clone().month(0).zone() || - this.zone() < this.clone().month(5).zone()); - }, + /** + * Set a new size for the graph + * @param {string} width Width in pixels or percentage (for example '800px' + * or '50%') + * @param {string} height Height in pixels or percentage (for example '400px' + * or '30%') + */ + Graph3d.prototype.setSize = function(width, height) { + this.frame.style.width = width; + this.frame.style.height = height; - day : function (input) { - var day = this._isUTC ? this._d.getUTCDay() : this._d.getDay(); - if (input != null) { - input = parseWeekday(input, this.lang()); - return this.add({ d : input - day }); - } else { - return day; - } - }, + this._resizeCanvas(); + }; - month : makeAccessor('Month', true), + /** + * Resize the canvas to the current size of the frame + */ + Graph3d.prototype._resizeCanvas = function() { + this.frame.canvas.style.width = '100%'; + this.frame.canvas.style.height = '100%'; - startOf: function (units) { - units = normalizeUnits(units); - // the following switch intentionally omits break keywords - // to utilize falling through the cases. - switch (units) { - case 'year': - this.month(0); - /* falls through */ - case 'quarter': - case 'month': - this.date(1); - /* falls through */ - case 'week': - case 'isoWeek': - case 'day': - this.hours(0); - /* falls through */ - case 'hour': - this.minutes(0); - /* falls through */ - case 'minute': - this.seconds(0); - /* falls through */ - case 'second': - this.milliseconds(0); - /* falls through */ - } + this.frame.canvas.width = this.frame.canvas.clientWidth; + this.frame.canvas.height = this.frame.canvas.clientHeight; - // weeks are a special case - if (units === 'week') { - this.weekday(0); - } else if (units === 'isoWeek') { - this.isoWeekday(1); - } + // adjust with for margin + this.frame.filter.style.width = (this.frame.canvas.clientWidth - 2 * 10) + 'px'; + }; - // quarters are also special - if (units === 'quarter') { - this.month(Math.floor(this.month() / 3) * 3); - } + /** + * Start animation + */ + Graph3d.prototype.animationStart = function() { + if (!this.frame.filter || !this.frame.filter.slider) + throw 'No animation available'; - return this; - }, + this.frame.filter.slider.play(); + }; - endOf: function (units) { - units = normalizeUnits(units); - return this.startOf(units).add((units === 'isoWeek' ? 'week' : units), 1).subtract('ms', 1); - }, - isAfter: function (input, units) { - units = typeof units !== 'undefined' ? units : 'millisecond'; - return +this.clone().startOf(units) > +moment(input).startOf(units); - }, + /** + * Stop animation + */ + Graph3d.prototype.animationStop = function() { + if (!this.frame.filter || !this.frame.filter.slider) return; - isBefore: function (input, units) { - units = typeof units !== 'undefined' ? units : 'millisecond'; - return +this.clone().startOf(units) < +moment(input).startOf(units); - }, + this.frame.filter.slider.stop(); + }; - isSame: function (input, units) { - units = units || 'ms'; - return +this.clone().startOf(units) === +makeAs(input, this).startOf(units); - }, - min: deprecate( - "moment().min is deprecated, use moment.min instead. https://github.com/moment/moment/issues/1548", - function (other) { - other = moment.apply(null, arguments); - return other < this ? this : other; - } - ), + /** + * Resize the center position based on the current values in this.defaultXCenter + * and this.defaultYCenter (which are strings with a percentage or a value + * in pixels). The center positions are the variables this.xCenter + * and this.yCenter + */ + Graph3d.prototype._resizeCenter = function() { + // calculate the horizontal center position + if (this.defaultXCenter.charAt(this.defaultXCenter.length-1) === '%') { + this.xcenter = + parseFloat(this.defaultXCenter) / 100 * + this.frame.canvas.clientWidth; + } + else { + this.xcenter = parseFloat(this.defaultXCenter); // supposed to be in px + } - max: deprecate( - "moment().max is deprecated, use moment.max instead. https://github.com/moment/moment/issues/1548", - function (other) { - other = moment.apply(null, arguments); - return other > this ? this : other; - } - ), + // calculate the vertical center position + if (this.defaultYCenter.charAt(this.defaultYCenter.length-1) === '%') { + this.ycenter = + parseFloat(this.defaultYCenter) / 100 * + (this.frame.canvas.clientHeight - this.frame.filter.clientHeight); + } + else { + this.ycenter = parseFloat(this.defaultYCenter); // supposed to be in px + } + }; - // keepTime = true means only change the timezone, without affecting - // the local hour. So 5:31:26 +0300 --[zone(2, true)]--> 5:31:26 +0200 - // It is possible that 5:31:26 doesn't exist int zone +0200, so we - // adjust the time as needed, to be valid. - // - // Keeping the time actually adds/subtracts (one hour) - // from the actual represented time. That is why we call updateOffset - // a second time. In case it wants us to change the offset again - // _changeInProgress == true case, then we have to adjust, because - // there is no such time in the given timezone. - zone : function (input, keepTime) { - var offset = this._offset || 0; - if (input != null) { - if (typeof input === "string") { - input = timezoneMinutesFromString(input); - } - if (Math.abs(input) < 16) { - input = input * 60; - } - this._offset = input; - this._isUTC = true; - if (offset !== input) { - if (!keepTime || this._changeInProgress) { - addOrSubtractDurationFromMoment(this, - moment.duration(offset - input, 'm'), 1, false); - } else if (!this._changeInProgress) { - this._changeInProgress = true; - moment.updateOffset(this, true); - this._changeInProgress = null; - } - } - } else { - return this._isUTC ? offset : this._d.getTimezoneOffset(); - } - return this; - }, + /** + * Set the rotation and distance of the camera + * @param {Object} pos An object with the camera position. The object + * contains three parameters: + * - horizontal {Number} + * The horizontal rotation, between 0 and 2*PI. + * Optional, can be left undefined. + * - vertical {Number} + * The vertical rotation, between 0 and 0.5*PI + * if vertical=0.5*PI, the graph is shown from the + * top. Optional, can be left undefined. + * - distance {Number} + * The (normalized) distance of the camera to the + * center of the graph, a value between 0.71 and 5.0. + * Optional, can be left undefined. + */ + Graph3d.prototype.setCameraPosition = function(pos) { + if (pos === undefined) { + return; + } - zoneAbbr : function () { - return this._isUTC ? "UTC" : ""; - }, + if (pos.horizontal !== undefined && pos.vertical !== undefined) { + this.camera.setArmRotation(pos.horizontal, pos.vertical); + } - zoneName : function () { - return this._isUTC ? "Coordinated Universal Time" : ""; - }, + if (pos.distance !== undefined) { + this.camera.setArmLength(pos.distance); + } - parseZone : function () { - if (this._tzm) { - this.zone(this._tzm); - } else if (typeof this._i === 'string') { - this.zone(this._i); - } - return this; - }, + this.redraw(); + }; - hasAlignedHourOffset : function (input) { - if (!input) { - input = 0; - } - else { - input = moment(input).zone(); - } - - return (this.zone() - input) % 60 === 0; - }, - - daysInMonth : function () { - return daysInMonth(this.year(), this.month()); - }, - dayOfYear : function (input) { - var dayOfYear = round((moment(this).startOf('day') - moment(this).startOf('year')) / 864e5) + 1; - return input == null ? dayOfYear : this.add("d", (input - dayOfYear)); - }, + /** + * Retrieve the current camera rotation + * @return {object} An object with parameters horizontal, vertical, and + * distance + */ + Graph3d.prototype.getCameraPosition = function() { + var pos = this.camera.getArmRotation(); + pos.distance = this.camera.getArmLength(); + return pos; + }; - quarter : function (input) { - return input == null ? Math.ceil((this.month() + 1) / 3) : this.month((input - 1) * 3 + this.month() % 3); - }, + /** + * Load data into the 3D Graph + */ + Graph3d.prototype._readData = function(data) { + // read the data + this._dataInitialize(data, this.style); - weekYear : function (input) { - var year = weekOfYear(this, this.lang()._week.dow, this.lang()._week.doy).year; - return input == null ? year : this.add("y", (input - year)); - }, - isoWeekYear : function (input) { - var year = weekOfYear(this, 1, 4).year; - return input == null ? year : this.add("y", (input - year)); - }, + if (this.dataFilter) { + // apply filtering + this.dataPoints = this.dataFilter._getDataPoints(); + } + else { + // no filtering. load all data + this.dataPoints = this._getDataPoints(this.dataTable); + } - week : function (input) { - var week = this.lang().week(this); - return input == null ? week : this.add("d", (input - week) * 7); - }, + // draw the filter + this._redrawFilter(); + }; - isoWeek : function (input) { - var week = weekOfYear(this, 1, 4).week; - return input == null ? week : this.add("d", (input - week) * 7); - }, + /** + * Replace the dataset of the Graph3d + * @param {Array | DataSet | DataView} data + */ + Graph3d.prototype.setData = function (data) { + this._readData(data); + this.redraw(); - weekday : function (input) { - var weekday = (this.day() + 7 - this.lang()._week.dow) % 7; - return input == null ? weekday : this.add("d", input - weekday); - }, + // start animation when option is true + if (this.animationAutoStart && this.dataFilter) { + this.animationStart(); + } + }; - isoWeekday : function (input) { - // behaves the same as moment#day except - // as a getter, returns 7 instead of 0 (1-7 range instead of 0-6) - // as a setter, sunday should belong to the previous week. - return input == null ? this.day() || 7 : this.day(this.day() % 7 ? input : input - 7); - }, + /** + * Update the options. Options will be merged with current options + * @param {Object} options + */ + Graph3d.prototype.setOptions = function (options) { + var cameraPosition = undefined; - isoWeeksInYear : function () { - return weeksInYear(this.year(), 1, 4); - }, + this.animationStop(); - weeksInYear : function () { - var weekInfo = this._lang._week; - return weeksInYear(this.year(), weekInfo.dow, weekInfo.doy); - }, + if (options !== undefined) { + // retrieve parameter values + if (options.width !== undefined) this.width = options.width; + if (options.height !== undefined) this.height = options.height; - get : function (units) { - units = normalizeUnits(units); - return this[units](); - }, + if (options.xCenter !== undefined) this.defaultXCenter = options.xCenter; + if (options.yCenter !== undefined) this.defaultYCenter = options.yCenter; - set : function (units, value) { - units = normalizeUnits(units); - if (typeof this[units] === 'function') { - this[units](value); - } - return this; - }, + if (options.filterLabel !== undefined) this.filterLabel = options.filterLabel; + if (options.legendLabel !== undefined) this.legendLabel = options.legendLabel; + if (options.xLabel !== undefined) this.xLabel = options.xLabel; + if (options.yLabel !== undefined) this.yLabel = options.yLabel; + if (options.zLabel !== undefined) this.zLabel = options.zLabel; - // If passed a language key, it will set the language for this - // instance. Otherwise, it will return the language configuration - // variables for this instance. - lang : function (key) { - if (key === undefined) { - return this._lang; - } else { - this._lang = getLangDefinition(key); - return this; - } - } - }); + if (options.style !== undefined) { + var styleNumber = this._getStyleNumber(options.style); + if (styleNumber !== -1) { + this.style = styleNumber; + } + } + if (options.showGrid !== undefined) this.showGrid = options.showGrid; + if (options.showPerspective !== undefined) this.showPerspective = options.showPerspective; + if (options.showShadow !== undefined) this.showShadow = options.showShadow; + if (options.tooltip !== undefined) this.showTooltip = options.tooltip; + if (options.showAnimationControls !== undefined) this.showAnimationControls = options.showAnimationControls; + if (options.keepAspectRatio !== undefined) this.keepAspectRatio = options.keepAspectRatio; + if (options.verticalRatio !== undefined) this.verticalRatio = options.verticalRatio; - function rawMonthSetter(mom, value) { - var dayOfMonth; + if (options.animationInterval !== undefined) this.animationInterval = options.animationInterval; + if (options.animationPreload !== undefined) this.animationPreload = options.animationPreload; + if (options.animationAutoStart !== undefined)this.animationAutoStart = options.animationAutoStart; - // TODO: Move this out of here! - if (typeof value === 'string') { - value = mom.lang().monthsParse(value); - // TODO: Another silent failure? - if (typeof value !== 'number') { - return mom; - } - } + if (options.xBarWidth !== undefined) this.defaultXBarWidth = options.xBarWidth; + if (options.yBarWidth !== undefined) this.defaultYBarWidth = options.yBarWidth; - dayOfMonth = Math.min(mom.date(), - daysInMonth(mom.year(), value)); - mom._d['set' + (mom._isUTC ? 'UTC' : '') + 'Month'](value, dayOfMonth); - return mom; - } + if (options.xMin !== undefined) this.defaultXMin = options.xMin; + if (options.xStep !== undefined) this.defaultXStep = options.xStep; + if (options.xMax !== undefined) this.defaultXMax = options.xMax; + if (options.yMin !== undefined) this.defaultYMin = options.yMin; + if (options.yStep !== undefined) this.defaultYStep = options.yStep; + if (options.yMax !== undefined) this.defaultYMax = options.yMax; + if (options.zMin !== undefined) this.defaultZMin = options.zMin; + if (options.zStep !== undefined) this.defaultZStep = options.zStep; + if (options.zMax !== undefined) this.defaultZMax = options.zMax; + if (options.valueMin !== undefined) this.defaultValueMin = options.valueMin; + if (options.valueMax !== undefined) this.defaultValueMax = options.valueMax; - function rawGetter(mom, unit) { - return mom._d['get' + (mom._isUTC ? 'UTC' : '') + unit](); - } + if (options.cameraPosition !== undefined) cameraPosition = options.cameraPosition; - function rawSetter(mom, unit, value) { - if (unit === 'Month') { - return rawMonthSetter(mom, value); - } else { - return mom._d['set' + (mom._isUTC ? 'UTC' : '') + unit](value); - } + if (cameraPosition !== undefined) { + this.camera.setArmRotation(cameraPosition.horizontal, cameraPosition.vertical); + this.camera.setArmLength(cameraPosition.distance); } - - function makeAccessor(unit, keepTime) { - return function (value) { - if (value != null) { - rawSetter(this, unit, value); - moment.updateOffset(this, keepTime); - return this; - } else { - return rawGetter(this, unit); - } - }; + else { + this.camera.setArmRotation(1.0, 0.5); + this.camera.setArmLength(1.7); } + } - moment.fn.millisecond = moment.fn.milliseconds = makeAccessor('Milliseconds', false); - moment.fn.second = moment.fn.seconds = makeAccessor('Seconds', false); - moment.fn.minute = moment.fn.minutes = makeAccessor('Minutes', false); - // Setting the hour should keep the time, because the user explicitly - // specified which hour he wants. So trying to maintain the same hour (in - // a new timezone) makes sense. Adding/subtracting hours does not follow - // this rule. - moment.fn.hour = moment.fn.hours = makeAccessor('Hours', true); - // moment.fn.month is defined separately - moment.fn.date = makeAccessor('Date', true); - moment.fn.dates = deprecate("dates accessor is deprecated. Use date instead.", makeAccessor('Date', true)); - moment.fn.year = makeAccessor('FullYear', true); - moment.fn.years = deprecate("years accessor is deprecated. Use year instead.", makeAccessor('FullYear', true)); - - // add plural methods - moment.fn.days = moment.fn.day; - moment.fn.months = moment.fn.month; - moment.fn.weeks = moment.fn.week; - moment.fn.isoWeeks = moment.fn.isoWeek; - moment.fn.quarters = moment.fn.quarter; + this._setBackgroundColor(options && options.backgroundColor); - // add aliased format methods - moment.fn.toJSON = moment.fn.toISOString; + this.setSize(this.width, this.height); - /************************************ - Duration Prototype - ************************************/ + // re-load the data + if (this.dataTable) { + this.setData(this.dataTable); + } + // start animation when option is true + if (this.animationAutoStart && this.dataFilter) { + this.animationStart(); + } + }; - extend(moment.duration.fn = Duration.prototype, { + /** + * Redraw the Graph. + */ + Graph3d.prototype.redraw = function() { + if (this.dataPoints === undefined) { + throw 'Error: graph data not initialized'; + } - _bubble : function () { - var milliseconds = this._milliseconds, - days = this._days, - months = this._months, - data = this._data, - seconds, minutes, hours, years; + this._resizeCanvas(); + this._resizeCenter(); + this._redrawSlider(); + this._redrawClear(); + this._redrawAxis(); - // The following code bubbles up values, see the tests for - // examples of what that means. - data.milliseconds = milliseconds % 1000; - - seconds = absRound(milliseconds / 1000); - data.seconds = seconds % 60; - - minutes = absRound(seconds / 60); - data.minutes = minutes % 60; + if (this.style === Graph3d.STYLE.GRID || + this.style === Graph3d.STYLE.SURFACE) { + this._redrawDataGrid(); + } + else if (this.style === Graph3d.STYLE.LINE) { + this._redrawDataLine(); + } + else if (this.style === Graph3d.STYLE.BAR || + this.style === Graph3d.STYLE.BARCOLOR || + this.style === Graph3d.STYLE.BARSIZE) { + this._redrawDataBar(); + } + else { + // style is DOT, DOTLINE, DOTCOLOR, DOTSIZE + this._redrawDataDot(); + } - hours = absRound(minutes / 60); - data.hours = hours % 24; + this._redrawInfo(); + this._redrawLegend(); + }; - days += absRound(hours / 24); - data.days = days % 30; + /** + * Clear the canvas before redrawing + */ + Graph3d.prototype._redrawClear = function() { + var canvas = this.frame.canvas; + var ctx = canvas.getContext('2d'); - months += absRound(days / 30); - data.months = months % 12; + ctx.clearRect(0, 0, canvas.width, canvas.height); + }; - years = absRound(months / 12); - data.years = years; - }, - weeks : function () { - return absRound(this.days() / 7); - }, + /** + * Redraw the legend showing the colors + */ + Graph3d.prototype._redrawLegend = function() { + var y; - valueOf : function () { - return this._milliseconds + - this._days * 864e5 + - (this._months % 12) * 2592e6 + - toInt(this._months / 12) * 31536e6; - }, + if (this.style === Graph3d.STYLE.DOTCOLOR || + this.style === Graph3d.STYLE.DOTSIZE) { - humanize : function (withSuffix) { - var difference = +this, - output = relativeTime(difference, !withSuffix, this.lang()); + var dotSize = this.frame.clientWidth * 0.02; - if (withSuffix) { - output = this.lang().pastFuture(difference, output); - } + var widthMin, widthMax; + if (this.style === Graph3d.STYLE.DOTSIZE) { + widthMin = dotSize / 2; // px + widthMax = dotSize / 2 + dotSize * 2; // Todo: put this in one function + } + else { + widthMin = 20; // px + widthMax = 20; // px + } - return this.lang().postformat(output); - }, + var height = Math.max(this.frame.clientHeight * 0.25, 100); + var top = this.margin; + var right = this.frame.clientWidth - this.margin; + var left = right - widthMax; + var bottom = top + height; + } - add : function (input, val) { - // supports only 2.0-style add(1, 's') or add(moment) - var dur = moment.duration(input, val); + var canvas = this.frame.canvas; + var ctx = canvas.getContext('2d'); + ctx.lineWidth = 1; + ctx.font = '14px arial'; // TODO: put in options - this._milliseconds += dur._milliseconds; - this._days += dur._days; - this._months += dur._months; + if (this.style === Graph3d.STYLE.DOTCOLOR) { + // draw the color bar + var ymin = 0; + var ymax = height; // Todo: make height customizable + for (y = ymin; y < ymax; y++) { + var f = (y - ymin) / (ymax - ymin); - this._bubble(); + //var width = (dotSize / 2 + (1-f) * dotSize * 2); // Todo: put this in one function + var hue = f * 240; + var color = this._hsv2rgb(hue, 1, 1); - return this; - }, + ctx.strokeStyle = color; + ctx.beginPath(); + ctx.moveTo(left, top + y); + ctx.lineTo(right, top + y); + ctx.stroke(); + } - subtract : function (input, val) { - var dur = moment.duration(input, val); + ctx.strokeStyle = this.colorAxis; + ctx.strokeRect(left, top, widthMax, height); + } - this._milliseconds -= dur._milliseconds; - this._days -= dur._days; - this._months -= dur._months; + if (this.style === Graph3d.STYLE.DOTSIZE) { + // draw border around color bar + ctx.strokeStyle = this.colorAxis; + ctx.fillStyle = this.colorDot; + ctx.beginPath(); + ctx.moveTo(left, top); + ctx.lineTo(right, top); + ctx.lineTo(right - widthMax + widthMin, bottom); + ctx.lineTo(left, bottom); + ctx.closePath(); + ctx.fill(); + ctx.stroke(); + } - this._bubble(); + if (this.style === Graph3d.STYLE.DOTCOLOR || + this.style === Graph3d.STYLE.DOTSIZE) { + // print values along the color bar + var gridLineLen = 5; // px + var step = new StepNumber(this.valueMin, this.valueMax, (this.valueMax-this.valueMin)/5, true); + step.start(); + if (step.getCurrent() < this.valueMin) { + step.next(); + } + while (!step.end()) { + y = bottom - (step.getCurrent() - this.valueMin) / (this.valueMax - this.valueMin) * height; - return this; - }, + ctx.beginPath(); + ctx.moveTo(left - gridLineLen, y); + ctx.lineTo(left, y); + ctx.stroke(); - get : function (units) { - units = normalizeUnits(units); - return this[units.toLowerCase() + 's'](); - }, + ctx.textAlign = 'right'; + ctx.textBaseline = 'middle'; + ctx.fillStyle = this.colorAxis; + ctx.fillText(step.getCurrent(), left - 2 * gridLineLen, y); - as : function (units) { - units = normalizeUnits(units); - return this['as' + units.charAt(0).toUpperCase() + units.slice(1) + 's'](); - }, + step.next(); + } - lang : moment.fn.lang, + ctx.textAlign = 'right'; + ctx.textBaseline = 'top'; + var label = this.legendLabel; + ctx.fillText(label, right, bottom + this.margin); + } + }; - toIsoString : function () { - // inspired by https://github.com/dordille/moment-isoduration/blob/master/moment.isoduration.js - var years = Math.abs(this.years()), - months = Math.abs(this.months()), - days = Math.abs(this.days()), - hours = Math.abs(this.hours()), - minutes = Math.abs(this.minutes()), - seconds = Math.abs(this.seconds() + this.milliseconds() / 1000); + /** + * Redraw the filter + */ + Graph3d.prototype._redrawFilter = function() { + this.frame.filter.innerHTML = ''; - if (!this.asSeconds()) { - // this is the same as C#'s (Noda) and python (isodate)... - // but not other JS (goog.date) - return 'P0D'; - } + if (this.dataFilter) { + var options = { + 'visible': this.showAnimationControls + }; + var slider = new Slider(this.frame.filter, options); + this.frame.filter.slider = slider; - return (this.asSeconds() < 0 ? '-' : '') + - 'P' + - (years ? years + 'Y' : '') + - (months ? months + 'M' : '') + - (days ? days + 'D' : '') + - ((hours || minutes || seconds) ? 'T' : '') + - (hours ? hours + 'H' : '') + - (minutes ? minutes + 'M' : '') + - (seconds ? seconds + 'S' : ''); - } - }); + // TODO: css here is not nice here... + this.frame.filter.style.padding = '10px'; + //this.frame.filter.style.backgroundColor = '#EFEFEF'; - function makeDurationGetter(name) { - moment.duration.fn[name] = function () { - return this._data[name]; - }; - } + slider.setValues(this.dataFilter.values); + slider.setPlayInterval(this.animationInterval); - function makeDurationAsGetter(name, factor) { - moment.duration.fn['as' + name] = function () { - return +this / factor; - }; - } + // create an event handler + var me = this; + var onchange = function () { + var index = slider.getIndex(); - for (i in unitMillisecondFactors) { - if (unitMillisecondFactors.hasOwnProperty(i)) { - makeDurationAsGetter(i, unitMillisecondFactors[i]); - makeDurationGetter(i.toLowerCase()); - } - } + me.dataFilter.selectValue(index); + me.dataPoints = me.dataFilter._getDataPoints(); - makeDurationAsGetter('Weeks', 6048e5); - moment.duration.fn.asMonths = function () { - return (+this - this.years() * 31536e6) / 2592e6 + this.years() * 12; + me.redraw(); }; + slider.setOnChangeCallback(onchange); + } + else { + this.frame.filter.slider = undefined; + } + }; - - /************************************ - Default Lang - ************************************/ + /** + * Redraw the slider + */ + Graph3d.prototype._redrawSlider = function() { + if ( this.frame.filter.slider !== undefined) { + this.frame.filter.slider.redraw(); + } + }; - // Set default language, other languages will inherit from English. - moment.lang('en', { - ordinal : function (number) { - var b = number % 10, - output = (toInt(number % 100 / 10) === 1) ? 'th' : - (b === 1) ? 'st' : - (b === 2) ? 'nd' : - (b === 3) ? 'rd' : 'th'; - return number + output; - } - }); - - /* EMBED_LANGUAGES */ - - /************************************ - Exposing Moment - ************************************/ - - function makeGlobal(shouldDeprecate) { - /*global ender:false */ - if (typeof ender !== 'undefined') { - return; - } - oldGlobalMoment = globalScope.moment; - if (shouldDeprecate) { - globalScope.moment = deprecate( - "Accessing Moment through the global scope is " + - "deprecated, and will be removed in an upcoming " + - "release.", - moment); - } else { - globalScope.moment = moment; - } - } - - // CommonJS module is defined - if (hasModule) { - module.exports = moment; - } else if (true) { - !(__WEBPACK_AMD_DEFINE_RESULT__ = (function (require, exports, module) { - if (module.config && module.config() && module.config().noGlobal === true) { - // release the global variable - globalScope.moment = oldGlobalMoment; - } - - return moment; - }.call(exports, __webpack_require__, exports, module)), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); - makeGlobal(true); - } else { - makeGlobal(); - } - }).call(this); - - /* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }()), __webpack_require__(5)(module))) + /** + * Redraw common information + */ + Graph3d.prototype._redrawInfo = function() { + if (this.dataFilter) { + var canvas = this.frame.canvas; + var ctx = canvas.getContext('2d'); -/***/ }, -/* 4 */ -/***/ function(module, exports, __webpack_require__) { + ctx.font = '14px arial'; // TODO: put in options + ctx.lineStyle = 'gray'; + ctx.fillStyle = 'gray'; + ctx.textAlign = 'left'; + ctx.textBaseline = 'top'; - var map = {}; - function webpackContext(req) { - return __webpack_require__(webpackContextResolve(req)); - }; - function webpackContextResolve(req) { - return map[req] || (function() { throw new Error("Cannot find module '" + req + "'.") }()); - }; - webpackContext.keys = function webpackContextKeys() { - return Object.keys(map); + var x = this.margin; + var y = this.margin; + ctx.fillText(this.dataFilter.getLabel() + ': ' + this.dataFilter.getSelectedValue(), x, y); + } }; - webpackContext.resolve = webpackContextResolve; - module.exports = webpackContext; - -/***/ }, -/* 5 */ -/***/ function(module, exports, __webpack_require__) { - module.exports = function(module) { - if(!module.webpackPolyfill) { - module.deprecate = function() {}; - module.paths = []; - // module.parent = undefined by default - module.children = []; - module.webpackPolyfill = 1; - } - return module; - } + /** + * Redraw the axis + */ + Graph3d.prototype._redrawAxis = function() { + var canvas = this.frame.canvas, + ctx = canvas.getContext('2d'), + from, to, step, prettyStep, + text, xText, yText, zText, + offset, xOffset, yOffset, + xMin2d, xMax2d; + // TODO: get the actual rendered style of the containerElement + //ctx.font = this.containerElement.style.font; + ctx.font = 24 / this.camera.getArmLength() + 'px arial'; -/***/ }, -/* 6 */ -/***/ function(module, exports, __webpack_require__) { + // calculate the length for the short grid lines + var gridLenX = 0.025 / this.scale.x; + var gridLenY = 0.025 / this.scale.y; + var textMargin = 5 / this.camera.getArmLength(); // px + var armAngle = this.camera.getArmRotation().horizontal; - // DOM utility methods + // draw x-grid lines + ctx.lineWidth = 1; + prettyStep = (this.defaultXStep === undefined); + step = new StepNumber(this.xMin, this.xMax, this.xStep, prettyStep); + step.start(); + if (step.getCurrent() < this.xMin) { + step.next(); + } + while (!step.end()) { + var x = step.getCurrent(); - /** - * this prepares the JSON container for allocating SVG elements - * @param JSONcontainer - * @private - */ - exports.prepareElements = function(JSONcontainer) { - // cleanup the redundant svgElements; - for (var elementType in JSONcontainer) { - if (JSONcontainer.hasOwnProperty(elementType)) { - JSONcontainer[elementType].redundant = JSONcontainer[elementType].used; - JSONcontainer[elementType].used = []; + if (this.showGrid) { + from = this._convert3Dto2D(new Point3d(x, this.yMin, this.zMin)); + to = this._convert3Dto2D(new Point3d(x, this.yMax, this.zMin)); + ctx.strokeStyle = this.colorGrid; + ctx.beginPath(); + ctx.moveTo(from.x, from.y); + ctx.lineTo(to.x, to.y); + ctx.stroke(); } - } - }; + else { + from = this._convert3Dto2D(new Point3d(x, this.yMin, this.zMin)); + to = this._convert3Dto2D(new Point3d(x, this.yMin+gridLenX, this.zMin)); + ctx.strokeStyle = this.colorAxis; + ctx.beginPath(); + ctx.moveTo(from.x, from.y); + ctx.lineTo(to.x, to.y); + ctx.stroke(); - /** - * this cleans up all the unused SVG elements. By asking for the parentNode, we only need to supply the JSON container from - * which to remove the redundant elements. - * - * @param JSONcontainer - * @private - */ - exports.cleanupElements = function(JSONcontainer) { - // cleanup the redundant svgElements; - for (var elementType in JSONcontainer) { - if (JSONcontainer.hasOwnProperty(elementType)) { - if (JSONcontainer[elementType].redundant) { - for (var i = 0; i < JSONcontainer[elementType].redundant.length; i++) { - JSONcontainer[elementType].redundant[i].parentNode.removeChild(JSONcontainer[elementType].redundant[i]); - } - JSONcontainer[elementType].redundant = []; - } + from = this._convert3Dto2D(new Point3d(x, this.yMax, this.zMin)); + to = this._convert3Dto2D(new Point3d(x, this.yMax-gridLenX, this.zMin)); + ctx.strokeStyle = this.colorAxis; + ctx.beginPath(); + ctx.moveTo(from.x, from.y); + ctx.lineTo(to.x, to.y); + ctx.stroke(); } - } - }; - /** - * Allocate or generate an SVG element if needed. Store a reference to it in the JSON container and draw it in the svgContainer - * the JSON container and the SVG container have to be supplied so other svg containers (like the legend) can use this. - * - * @param elementType - * @param JSONcontainer - * @param svgContainer - * @returns {*} - * @private - */ - exports.getSVGElement = function (elementType, JSONcontainer, svgContainer) { - var element; - // allocate SVG element, if it doesnt yet exist, create one. - if (JSONcontainer.hasOwnProperty(elementType)) { // this element has been created before - // check if there is an redundant element - if (JSONcontainer[elementType].redundant.length > 0) { - element = JSONcontainer[elementType].redundant[0]; - JSONcontainer[elementType].redundant.shift(); + yText = (Math.cos(armAngle) > 0) ? this.yMin : this.yMax; + text = this._convert3Dto2D(new Point3d(x, yText, this.zMin)); + if (Math.cos(armAngle * 2) > 0) { + ctx.textAlign = 'center'; + ctx.textBaseline = 'top'; + text.y += textMargin; + } + else if (Math.sin(armAngle * 2) < 0){ + ctx.textAlign = 'right'; + ctx.textBaseline = 'middle'; } else { - // create a new element and add it to the SVG - element = document.createElementNS('http://www.w3.org/2000/svg', elementType); - svgContainer.appendChild(element); + ctx.textAlign = 'left'; + ctx.textBaseline = 'middle'; } + ctx.fillStyle = this.colorAxis; + ctx.fillText(' ' + step.getCurrent() + ' ', text.x, text.y); + + step.next(); } - else { - // create a new element and add it to the SVG, also create a new object in the svgElements to keep track of it. - element = document.createElementNS('http://www.w3.org/2000/svg', elementType); - JSONcontainer[elementType] = {used: [], redundant: []}; - svgContainer.appendChild(element); - } - JSONcontainer[elementType].used.push(element); - return element; - }; + // draw y-grid lines + ctx.lineWidth = 1; + prettyStep = (this.defaultYStep === undefined); + step = new StepNumber(this.yMin, this.yMax, this.yStep, prettyStep); + step.start(); + if (step.getCurrent() < this.yMin) { + step.next(); + } + while (!step.end()) { + if (this.showGrid) { + from = this._convert3Dto2D(new Point3d(this.xMin, step.getCurrent(), this.zMin)); + to = this._convert3Dto2D(new Point3d(this.xMax, step.getCurrent(), this.zMin)); + ctx.strokeStyle = this.colorGrid; + ctx.beginPath(); + ctx.moveTo(from.x, from.y); + ctx.lineTo(to.x, to.y); + ctx.stroke(); + } + else { + from = this._convert3Dto2D(new Point3d(this.xMin, step.getCurrent(), this.zMin)); + to = this._convert3Dto2D(new Point3d(this.xMin+gridLenY, step.getCurrent(), this.zMin)); + ctx.strokeStyle = this.colorAxis; + ctx.beginPath(); + ctx.moveTo(from.x, from.y); + ctx.lineTo(to.x, to.y); + ctx.stroke(); - /** - * Allocate or generate an SVG element if needed. Store a reference to it in the JSON container and draw it in the svgContainer - * the JSON container and the SVG container have to be supplied so other svg containers (like the legend) can use this. - * - * @param elementType - * @param JSONcontainer - * @param DOMContainer - * @returns {*} - * @private - */ - exports.getDOMElement = function (elementType, JSONcontainer, DOMContainer) { - var element; - // allocate DOM element, if it doesnt yet exist, create one. - if (JSONcontainer.hasOwnProperty(elementType)) { // this element has been created before - // check if there is an redundant element - if (JSONcontainer[elementType].redundant.length > 0) { - element = JSONcontainer[elementType].redundant[0]; - JSONcontainer[elementType].redundant.shift(); + from = this._convert3Dto2D(new Point3d(this.xMax, step.getCurrent(), this.zMin)); + to = this._convert3Dto2D(new Point3d(this.xMax-gridLenY, step.getCurrent(), this.zMin)); + ctx.strokeStyle = this.colorAxis; + ctx.beginPath(); + ctx.moveTo(from.x, from.y); + ctx.lineTo(to.x, to.y); + ctx.stroke(); + } + + xText = (Math.sin(armAngle ) > 0) ? this.xMin : this.xMax; + text = this._convert3Dto2D(new Point3d(xText, step.getCurrent(), this.zMin)); + if (Math.cos(armAngle * 2) < 0) { + ctx.textAlign = 'center'; + ctx.textBaseline = 'top'; + text.y += textMargin; + } + else if (Math.sin(armAngle * 2) > 0){ + ctx.textAlign = 'right'; + ctx.textBaseline = 'middle'; } else { - // create a new element and add it to the SVG - element = document.createElement(elementType); - DOMContainer.appendChild(element); + ctx.textAlign = 'left'; + ctx.textBaseline = 'middle'; } + ctx.fillStyle = this.colorAxis; + ctx.fillText(' ' + step.getCurrent() + ' ', text.x, text.y); + + step.next(); } - else { - // create a new element and add it to the SVG, also create a new object in the svgElements to keep track of it. - element = document.createElement(elementType); - JSONcontainer[elementType] = {used: [], redundant: []}; - DOMContainer.appendChild(element); + + // draw z-grid lines and axis + ctx.lineWidth = 1; + prettyStep = (this.defaultZStep === undefined); + step = new StepNumber(this.zMin, this.zMax, this.zStep, prettyStep); + step.start(); + if (step.getCurrent() < this.zMin) { + step.next(); } - JSONcontainer[elementType].used.push(element); - return element; - }; + xText = (Math.cos(armAngle ) > 0) ? this.xMin : this.xMax; + yText = (Math.sin(armAngle ) < 0) ? this.yMin : this.yMax; + while (!step.end()) { + // TODO: make z-grid lines really 3d? + from = this._convert3Dto2D(new Point3d(xText, yText, step.getCurrent())); + ctx.strokeStyle = this.colorAxis; + ctx.beginPath(); + ctx.moveTo(from.x, from.y); + ctx.lineTo(from.x - textMargin, from.y); + ctx.stroke(); + ctx.textAlign = 'right'; + ctx.textBaseline = 'middle'; + ctx.fillStyle = this.colorAxis; + ctx.fillText(step.getCurrent() + ' ', from.x - 5, from.y); + step.next(); + } + ctx.lineWidth = 1; + from = this._convert3Dto2D(new Point3d(xText, yText, this.zMin)); + to = this._convert3Dto2D(new Point3d(xText, yText, this.zMax)); + ctx.strokeStyle = this.colorAxis; + ctx.beginPath(); + ctx.moveTo(from.x, from.y); + ctx.lineTo(to.x, to.y); + ctx.stroke(); + // draw x-axis + ctx.lineWidth = 1; + // line at yMin + xMin2d = this._convert3Dto2D(new Point3d(this.xMin, this.yMin, this.zMin)); + xMax2d = this._convert3Dto2D(new Point3d(this.xMax, this.yMin, this.zMin)); + ctx.strokeStyle = this.colorAxis; + ctx.beginPath(); + ctx.moveTo(xMin2d.x, xMin2d.y); + ctx.lineTo(xMax2d.x, xMax2d.y); + ctx.stroke(); + // line at ymax + xMin2d = this._convert3Dto2D(new Point3d(this.xMin, this.yMax, this.zMin)); + xMax2d = this._convert3Dto2D(new Point3d(this.xMax, this.yMax, this.zMin)); + ctx.strokeStyle = this.colorAxis; + ctx.beginPath(); + ctx.moveTo(xMin2d.x, xMin2d.y); + ctx.lineTo(xMax2d.x, xMax2d.y); + ctx.stroke(); - /** - * draw a point object. this is a seperate function because it can also be called by the legend. - * The reason the JSONcontainer and the target SVG svgContainer have to be supplied is so the legend can use these functions - * as well. - * - * @param x - * @param y - * @param group - * @param JSONcontainer - * @param svgContainer - * @returns {*} - */ - exports.drawPoint = function(x, y, group, JSONcontainer, svgContainer) { - var point; - if (group.options.drawPoints.style == 'circle') { - point = exports.getSVGElement('circle',JSONcontainer,svgContainer); - point.setAttributeNS(null, "cx", x); - point.setAttributeNS(null, "cy", y); - point.setAttributeNS(null, "r", 0.5 * group.options.drawPoints.size); - point.setAttributeNS(null, "class", group.className + " point"); + // draw y-axis + ctx.lineWidth = 1; + // line at xMin + from = this._convert3Dto2D(new Point3d(this.xMin, this.yMin, this.zMin)); + to = this._convert3Dto2D(new Point3d(this.xMin, this.yMax, this.zMin)); + ctx.strokeStyle = this.colorAxis; + ctx.beginPath(); + ctx.moveTo(from.x, from.y); + ctx.lineTo(to.x, to.y); + ctx.stroke(); + // line at xMax + from = this._convert3Dto2D(new Point3d(this.xMax, this.yMin, this.zMin)); + to = this._convert3Dto2D(new Point3d(this.xMax, this.yMax, this.zMin)); + ctx.strokeStyle = this.colorAxis; + ctx.beginPath(); + ctx.moveTo(from.x, from.y); + ctx.lineTo(to.x, to.y); + ctx.stroke(); + + // draw x-label + var xLabel = this.xLabel; + if (xLabel.length > 0) { + yOffset = 0.1 / this.scale.y; + xText = (this.xMin + this.xMax) / 2; + yText = (Math.cos(armAngle) > 0) ? this.yMin - yOffset: this.yMax + yOffset; + text = this._convert3Dto2D(new Point3d(xText, yText, this.zMin)); + if (Math.cos(armAngle * 2) > 0) { + ctx.textAlign = 'center'; + ctx.textBaseline = 'top'; + } + else if (Math.sin(armAngle * 2) < 0){ + ctx.textAlign = 'right'; + ctx.textBaseline = 'middle'; + } + else { + ctx.textAlign = 'left'; + ctx.textBaseline = 'middle'; + } + ctx.fillStyle = this.colorAxis; + ctx.fillText(xLabel, text.x, text.y); } - else { - point = exports.getSVGElement('rect',JSONcontainer,svgContainer); - point.setAttributeNS(null, "x", x - 0.5*group.options.drawPoints.size); - point.setAttributeNS(null, "y", y - 0.5*group.options.drawPoints.size); - point.setAttributeNS(null, "width", group.options.drawPoints.size); - point.setAttributeNS(null, "height", group.options.drawPoints.size); - point.setAttributeNS(null, "class", group.className + " point"); + + // draw y-label + var yLabel = this.yLabel; + if (yLabel.length > 0) { + xOffset = 0.1 / this.scale.x; + xText = (Math.sin(armAngle ) > 0) ? this.xMin - xOffset : this.xMax + xOffset; + yText = (this.yMin + this.yMax) / 2; + text = this._convert3Dto2D(new Point3d(xText, yText, this.zMin)); + if (Math.cos(armAngle * 2) < 0) { + ctx.textAlign = 'center'; + ctx.textBaseline = 'top'; + } + else if (Math.sin(armAngle * 2) > 0){ + ctx.textAlign = 'right'; + ctx.textBaseline = 'middle'; + } + else { + ctx.textAlign = 'left'; + ctx.textBaseline = 'middle'; + } + ctx.fillStyle = this.colorAxis; + ctx.fillText(yLabel, text.x, text.y); + } + + // draw z-label + var zLabel = this.zLabel; + if (zLabel.length > 0) { + offset = 30; // pixels. // TODO: relate to the max width of the values on the z axis? + xText = (Math.cos(armAngle ) > 0) ? this.xMin : this.xMax; + yText = (Math.sin(armAngle ) < 0) ? this.yMin : this.yMax; + zText = (this.zMin + this.zMax) / 2; + text = this._convert3Dto2D(new Point3d(xText, yText, zText)); + ctx.textAlign = 'right'; + ctx.textBaseline = 'middle'; + ctx.fillStyle = this.colorAxis; + ctx.fillText(zLabel, text.x - offset, text.y); } - return point; }; /** - * draw a bar SVG element centered on the X coordinate - * - * @param x - * @param y - * @param className + * Calculate the color based on the given value. + * @param {Number} H Hue, a value be between 0 and 360 + * @param {Number} S Saturation, a value between 0 and 1 + * @param {Number} V Value, a value between 0 and 1 */ - exports.drawBar = function (x, y, width, height, className, JSONcontainer, svgContainer) { - // if (height != 0) { - var rect = exports.getSVGElement('rect',JSONcontainer, svgContainer); - rect.setAttributeNS(null, "x", x - 0.5 * width); - rect.setAttributeNS(null, "y", y); - rect.setAttributeNS(null, "width", width); - rect.setAttributeNS(null, "height", height); - rect.setAttributeNS(null, "class", className); - // } - }; + Graph3d.prototype._hsv2rgb = function(H, S, V) { + var R, G, B, C, Hi, X; -/***/ }, -/* 7 */ -/***/ function(module, exports, __webpack_require__) { + C = V * S; + Hi = Math.floor(H/60); // hi = 0,1,2,3,4,5 + X = C * (1 - Math.abs(((H/60) % 2) - 1)); + + switch (Hi) { + case 0: R = C; G = X; B = 0; break; + case 1: R = X; G = C; B = 0; break; + case 2: R = 0; G = C; B = X; break; + case 3: R = 0; G = X; B = C; break; + case 4: R = X; G = 0; B = C; break; + case 5: R = C; G = 0; B = X; break; + + default: R = 0; G = 0; B = 0; break; + } + + return 'RGB(' + parseInt(R*255) + ',' + parseInt(G*255) + ',' + parseInt(B*255) + ')'; + }; - var util = __webpack_require__(1); /** - * DataSet - * - * Usage: - * var dataSet = new DataSet({ - * fieldId: '_id', - * type: { - * // ... - * } - * }); - * - * dataSet.add(item); - * dataSet.add(data); - * dataSet.update(item); - * dataSet.update(data); - * dataSet.remove(id); - * dataSet.remove(ids); - * var data = dataSet.get(); - * var data = dataSet.get(id); - * var data = dataSet.get(ids); - * var data = dataSet.get(ids, options, data); - * dataSet.clear(); - * - * A data set can: - * - add/remove/update data - * - gives triggers upon changes in the data - * - can import/export data in various data formats - * - * @param {Array | DataTable} [data] Optional array with initial data - * @param {Object} [options] Available options: - * {String} fieldId Field name of the id in the - * items, 'id' by default. - * {Object. 0); } else { - this._type[field] = value; + topSideVisible = true; + } + + if (topSideVisible) { + // calculate Hue from the current value. At zMin the hue is 240, at zMax the hue is 0 + zAvg = (point.point.z + right.point.z + top.point.z + cross.point.z) / 4; + h = (1 - (zAvg - this.zMin) * this.scale.z / this.verticalRatio) * 240; + s = 1; // saturation + + if (this.showShadow) { + v = Math.min(1 + (crossproduct.x / len) / 2, 1); // value. TODO: scale + fillStyle = this._hsv2rgb(h, s, v); + strokeStyle = fillStyle; + } + else { + v = 1; + fillStyle = this._hsv2rgb(h, s, v); + strokeStyle = this.colorAxis; + } + } + else { + fillStyle = 'gray'; + strokeStyle = this.colorAxis; } + lineWidth = 0.5; + + ctx.lineWidth = lineWidth; + ctx.fillStyle = fillStyle; + ctx.strokeStyle = strokeStyle; + ctx.beginPath(); + ctx.moveTo(point.screen.x, point.screen.y); + ctx.lineTo(right.screen.x, right.screen.y); + ctx.lineTo(cross.screen.x, cross.screen.y); + ctx.lineTo(top.screen.x, top.screen.y); + ctx.closePath(); + ctx.fill(); + ctx.stroke(); } } } + else { // grid style + for (i = 0; i < this.dataPoints.length; i++) { + point = this.dataPoints[i]; + right = this.dataPoints[i].pointRight; + top = this.dataPoints[i].pointTop; - // TODO: deprecated since version 1.1.1 (or 2.0.0?) - if (this._options.convert) { - throw new Error('Option "convert" is deprecated. Use "type" instead.'); - } + if (point !== undefined) { + if (this.showPerspective) { + lineWidth = 2 / -point.trans.z; + } + else { + lineWidth = 2 * -(this.eye.z / this.camera.getArmLength()); + } + } - this._subscribers = {}; // event subscribers + if (point !== undefined && right !== undefined) { + // calculate Hue from the current value. At zMin the hue is 240, at zMax the hue is 0 + zAvg = (point.point.z + right.point.z) / 2; + h = (1 - (zAvg - this.zMin) * this.scale.z / this.verticalRatio) * 240; - // add initial data when provided - if (data) { - this.add(data); - } - } + ctx.lineWidth = lineWidth; + ctx.strokeStyle = this._hsv2rgb(h, 1, 1); + ctx.beginPath(); + ctx.moveTo(point.screen.x, point.screen.y); + ctx.lineTo(right.screen.x, right.screen.y); + ctx.stroke(); + } - /** - * Subscribe to an event, add an event listener - * @param {String} event Event name. Available events: 'put', 'update', - * 'remove' - * @param {function} callback Callback method. Called with three parameters: - * {String} event - * {Object | null} params - * {String | Number} senderId - */ - DataSet.prototype.on = function(event, callback) { - var subscribers = this._subscribers[event]; - if (!subscribers) { - subscribers = []; - this._subscribers[event] = subscribers; - } + if (point !== undefined && top !== undefined) { + // calculate Hue from the current value. At zMin the hue is 240, at zMax the hue is 0 + zAvg = (point.point.z + top.point.z) / 2; + h = (1 - (zAvg - this.zMin) * this.scale.z / this.verticalRatio) * 240; - subscribers.push({ - callback: callback - }); + ctx.lineWidth = lineWidth; + ctx.strokeStyle = this._hsv2rgb(h, 1, 1); + ctx.beginPath(); + ctx.moveTo(point.screen.x, point.screen.y); + ctx.lineTo(top.screen.x, top.screen.y); + ctx.stroke(); + } + } + } }; - // TODO: make this function deprecated (replaced with `on` since version 0.5) - DataSet.prototype.subscribe = DataSet.prototype.on; /** - * Unsubscribe from an event, remove an event listener - * @param {String} event - * @param {function} callback + * Draw all datapoints as dots. + * This function can be used when the style is 'dot' or 'dot-line' */ - DataSet.prototype.off = function(event, callback) { - var subscribers = this._subscribers[event]; - if (subscribers) { - this._subscribers[event] = subscribers.filter(function (listener) { - return (listener.callback != callback); - }); - } - }; + Graph3d.prototype._redrawDataDot = function() { + var canvas = this.frame.canvas; + var ctx = canvas.getContext('2d'); + var i; - // TODO: make this function deprecated (replaced with `on` since version 0.5) - DataSet.prototype.unsubscribe = DataSet.prototype.off; + if (this.dataPoints === undefined || this.dataPoints.length <= 0) + return; // TODO: throw exception? - /** - * Trigger an event - * @param {String} event - * @param {Object | null} params - * @param {String} [senderId] Optional id of the sender. - * @private - */ - DataSet.prototype._trigger = function (event, params, senderId) { - if (event == '*') { - throw new Error('Cannot trigger event *'); - } + // calculate the translations of all points + for (i = 0; i < this.dataPoints.length; i++) { + var trans = this._convertPointToTranslation(this.dataPoints[i].point); + var screen = this._convertTranslationToScreen(trans); + this.dataPoints[i].trans = trans; + this.dataPoints[i].screen = screen; - var subscribers = []; - if (event in this._subscribers) { - subscribers = subscribers.concat(this._subscribers[event]); - } - if ('*' in this._subscribers) { - subscribers = subscribers.concat(this._subscribers['*']); + // calculate the distance from the point at the bottom to the camera + var transBottom = this._convertPointToTranslation(this.dataPoints[i].bottom); + this.dataPoints[i].dist = this.showPerspective ? transBottom.length() : -transBottom.z; } - for (var i = 0; i < subscribers.length; i++) { - var subscriber = subscribers[i]; - if (subscriber.callback) { - subscriber.callback(event, params, senderId || null); - } - } - }; + // order the translated points by depth + var sortDepth = function (a, b) { + return b.dist - a.dist; + }; + this.dataPoints.sort(sortDepth); - /** - * Add data. - * Adding an item will fail when there already is an item with the same id. - * @param {Object | Array | DataTable} data - * @param {String} [senderId] Optional sender id - * @return {Array} addedIds Array with the ids of the added items - */ - DataSet.prototype.add = function (data, senderId) { - var addedIds = [], - id, - me = this; + // draw the datapoints as colored circles + var dotSize = this.frame.clientWidth * 0.02; // px + for (i = 0; i < this.dataPoints.length; i++) { + var point = this.dataPoints[i]; - if (Array.isArray(data)) { - // Array - for (var i = 0, len = data.length; i < len; i++) { - id = me._addItem(data[i]); - addedIds.push(id); + if (this.style === Graph3d.STYLE.DOTLINE) { + // draw a vertical line from the bottom to the graph value + //var from = this._convert3Dto2D(new Point3d(point.point.x, point.point.y, this.zMin)); + var from = this._convert3Dto2D(point.bottom); + ctx.lineWidth = 1; + ctx.strokeStyle = this.colorGrid; + ctx.beginPath(); + ctx.moveTo(from.x, from.y); + ctx.lineTo(point.screen.x, point.screen.y); + ctx.stroke(); } - } - else if (util.isDataTable(data)) { - // Google DataTable - var columns = this._getColumnNames(data); - for (var row = 0, rows = data.getNumberOfRows(); row < rows; row++) { - var item = {}; - for (var col = 0, cols = columns.length; col < cols; col++) { - var field = columns[col]; - item[field] = data.getValue(row, col); - } - id = me._addItem(item); - addedIds.push(id); + // calculate radius for the circle + var size; + if (this.style === Graph3d.STYLE.DOTSIZE) { + size = dotSize/2 + 2*dotSize * (point.point.value - this.valueMin) / (this.valueMax - this.valueMin); + } + else { + size = dotSize; } - } - else if (data instanceof Object) { - // Single item - id = me._addItem(data); - addedIds.push(id); - } - else { - throw new Error('Unknown dataType'); - } - - if (addedIds.length) { - this._trigger('add', {items: addedIds}, senderId); - } - - return addedIds; - }; - - /** - * Update existing items. When an item does not exist, it will be created - * @param {Object | Array | DataTable} data - * @param {String} [senderId] Optional sender id - * @return {Array} updatedIds The ids of the added or updated items - */ - DataSet.prototype.update = function (data, senderId) { - var addedIds = [], - updatedIds = [], - me = this, - fieldId = me._fieldId; - var addOrUpdate = function (item) { - var id = item[fieldId]; - if (me._data[id]) { - // update item - id = me._updateItem(item); - updatedIds.push(id); + var radius; + if (this.showPerspective) { + radius = size / -point.trans.z; } else { - // add new item - id = me._addItem(item); - addedIds.push(id); + radius = size * -(this.eye.z / this.camera.getArmLength()); } - }; - - if (Array.isArray(data)) { - // Array - for (var i = 0, len = data.length; i < len; i++) { - addOrUpdate(data[i]); + if (radius < 0) { + radius = 0; } - } - else if (util.isDataTable(data)) { - // Google DataTable - var columns = this._getColumnNames(data); - for (var row = 0, rows = data.getNumberOfRows(); row < rows; row++) { - var item = {}; - for (var col = 0, cols = columns.length; col < cols; col++) { - var field = columns[col]; - item[field] = data.getValue(row, col); - } - addOrUpdate(item); + var hue, color, borderColor; + if (this.style === Graph3d.STYLE.DOTCOLOR ) { + // calculate the color based on the value + hue = (1 - (point.point.value - this.valueMin) * this.scale.value) * 240; + color = this._hsv2rgb(hue, 1, 1); + borderColor = this._hsv2rgb(hue, 1, 0.8); + } + else if (this.style === Graph3d.STYLE.DOTSIZE) { + color = this.colorDot; + borderColor = this.colorDotBorder; + } + else { + // calculate Hue from the current value. At zMin the hue is 240, at zMax the hue is 0 + hue = (1 - (point.point.z - this.zMin) * this.scale.z / this.verticalRatio) * 240; + color = this._hsv2rgb(hue, 1, 1); + borderColor = this._hsv2rgb(hue, 1, 0.8); } - } - else if (data instanceof Object) { - // Single item - addOrUpdate(data); - } - else { - throw new Error('Unknown dataType'); - } - if (addedIds.length) { - this._trigger('add', {items: addedIds}, senderId); - } - if (updatedIds.length) { - this._trigger('update', {items: updatedIds}, senderId); + // draw the circle + ctx.lineWidth = 1.0; + ctx.strokeStyle = borderColor; + ctx.fillStyle = color; + ctx.beginPath(); + ctx.arc(point.screen.x, point.screen.y, radius, 0, Math.PI*2, true); + ctx.fill(); + ctx.stroke(); } - - return addedIds.concat(updatedIds); }; /** - * Get a data item or multiple items. - * - * Usage: - * - * get() - * get(options: Object) - * get(options: Object, data: Array | DataTable) - * - * get(id: Number | String) - * get(id: Number | String, options: Object) - * get(id: Number | String, options: Object, data: Array | DataTable) - * - * get(ids: Number[] | String[]) - * get(ids: Number[] | String[], options: Object) - * get(ids: Number[] | String[], options: Object, data: Array | DataTable) - * - * Where: - * - * {Number | String} id The id of an item - * {Number[] | String{}} ids An array with ids of items - * {Object} options An Object with options. Available options: - * {String} [returnType] Type of data to be - * returned. Can be 'DataTable' or 'Array' (default) - * {Object.} [type] - * {String[]} [fields] field names to be returned - * {function} [filter] filter items - * {String | function} [order] Order the items by - * a field name or custom sort function. - * {Array | DataTable} [data] If provided, items will be appended to this - * array or table. Required in case of Google - * DataTable. - * - * @throws Error + * Draw all datapoints as bars. + * This function can be used when the style is 'bar', 'bar-color', or 'bar-size' */ - DataSet.prototype.get = function (args) { - var me = this; + Graph3d.prototype._redrawDataBar = function() { + var canvas = this.frame.canvas; + var ctx = canvas.getContext('2d'); + var i, j, surface, corners; - // parse the arguments - var id, ids, options, data; - var firstType = util.getType(arguments[0]); - if (firstType == 'String' || firstType == 'Number') { - // get(id [, options] [, data]) - id = arguments[0]; - options = arguments[1]; - data = arguments[2]; - } - else if (firstType == 'Array') { - // get(ids [, options] [, data]) - ids = arguments[0]; - options = arguments[1]; - data = arguments[2]; - } - else { - // get([, options] [, data]) - options = arguments[0]; - data = arguments[1]; - } + if (this.dataPoints === undefined || this.dataPoints.length <= 0) + return; // TODO: throw exception? - // determine the return type - var returnType; - if (options && options.returnType) { - var allowedValues = ["DataTable", "Array", "Object"]; - returnType = allowedValues.indexOf(options.returnType) == -1 ? "Array" : options.returnType; + // calculate the translations of all points + for (i = 0; i < this.dataPoints.length; i++) { + var trans = this._convertPointToTranslation(this.dataPoints[i].point); + var screen = this._convertTranslationToScreen(trans); + this.dataPoints[i].trans = trans; + this.dataPoints[i].screen = screen; - if (data && (returnType != util.getType(data))) { - throw new Error('Type of parameter "data" (' + util.getType(data) + ') ' + - 'does not correspond with specified options.type (' + options.type + ')'); - } - if (returnType == 'DataTable' && !util.isDataTable(data)) { - throw new Error('Parameter "data" must be a DataTable ' + - 'when options.type is "DataTable"'); - } - } - else if (data) { - returnType = (util.getType(data) == 'DataTable') ? 'DataTable' : 'Array'; - } - else { - returnType = 'Array'; + // calculate the distance from the point at the bottom to the camera + var transBottom = this._convertPointToTranslation(this.dataPoints[i].bottom); + this.dataPoints[i].dist = this.showPerspective ? transBottom.length() : -transBottom.z; } - // build options - var type = options && options.type || this._options.type; - var filter = options && options.filter; - var items = [], item, itemId, i, len; + // order the translated points by depth + var sortDepth = function (a, b) { + return b.dist - a.dist; + }; + this.dataPoints.sort(sortDepth); - // convert items - if (id != undefined) { - // return a single item - item = me._getItem(id, type); - if (filter && !filter(item)) { - item = null; - } - } - else if (ids != undefined) { - // return a subset of items - for (i = 0, len = ids.length; i < len; i++) { - item = me._getItem(ids[i], type); - if (!filter || filter(item)) { - items.push(item); - } - } - } - else { - // return all items - for (itemId in this._data) { - if (this._data.hasOwnProperty(itemId)) { - item = me._getItem(itemId, type); - if (!filter || filter(item)) { - items.push(item); - } - } - } - } - - // order the results - if (options && options.order && id == undefined) { - this._sort(items, options.order); - } + // draw the datapoints as bars + var xWidth = this.xBarWidth / 2; + var yWidth = this.yBarWidth / 2; + for (i = 0; i < this.dataPoints.length; i++) { + var point = this.dataPoints[i]; - // filter fields of the items - if (options && options.fields) { - var fields = options.fields; - if (id != undefined) { - item = this._filterFields(item, fields); - } - else { - for (i = 0, len = items.length; i < len; i++) { - items[i] = this._filterFields(items[i], fields); - } + // determine color + var hue, color, borderColor; + if (this.style === Graph3d.STYLE.BARCOLOR ) { + // calculate the color based on the value + hue = (1 - (point.point.value - this.valueMin) * this.scale.value) * 240; + color = this._hsv2rgb(hue, 1, 1); + borderColor = this._hsv2rgb(hue, 1, 0.8); } - } - - // return the results - if (returnType == 'DataTable') { - var columns = this._getColumnNames(data); - if (id != undefined) { - // append a single item to the data table - me._appendRow(data, columns, item); + else if (this.style === Graph3d.STYLE.BARSIZE) { + color = this.colorDot; + borderColor = this.colorDotBorder; } else { - // copy the items to the provided data table - for (i = 0; i < items.length; i++) { - me._appendRow(data, columns, items[i]); - } - } - return data; - } - else if (returnType == "Object") { - var result = {}; - for (i = 0; i < items.length; i++) { - result[items[i].id] = items[i]; - } - return result; - } - else { - // return an array - if (id != undefined) { - // a single item - return item; + // calculate Hue from the current value. At zMin the hue is 240, at zMax the hue is 0 + hue = (1 - (point.point.z - this.zMin) * this.scale.z / this.verticalRatio) * 240; + color = this._hsv2rgb(hue, 1, 1); + borderColor = this._hsv2rgb(hue, 1, 0.8); } - else { - // multiple items - if (data) { - // copy the items to the provided array - for (i = 0, len = items.length; i < len; i++) { - data.push(items[i]); - } - return data; - } - else { - // just return our array - return items; - } + + // calculate size for the bar + if (this.style === Graph3d.STYLE.BARSIZE) { + xWidth = (this.xBarWidth / 2) * ((point.point.value - this.valueMin) / (this.valueMax - this.valueMin) * 0.8 + 0.2); + yWidth = (this.yBarWidth / 2) * ((point.point.value - this.valueMin) / (this.valueMax - this.valueMin) * 0.8 + 0.2); } - } - }; - /** - * Get ids of all items or from a filtered set of items. - * @param {Object} [options] An Object with options. Available options: - * {function} [filter] filter items - * {String | function} [order] Order the items by - * a field name or custom sort function. - * @return {Array} ids - */ - DataSet.prototype.getIds = function (options) { - var data = this._data, - filter = options && options.filter, - order = options && options.order, - type = options && options.type || this._options.type, - i, - len, - id, - item, - items, - ids = []; + // calculate all corner points + var me = this; + var point3d = point.point; + var top = [ + {point: new Point3d(point3d.x - xWidth, point3d.y - yWidth, point3d.z)}, + {point: new Point3d(point3d.x + xWidth, point3d.y - yWidth, point3d.z)}, + {point: new Point3d(point3d.x + xWidth, point3d.y + yWidth, point3d.z)}, + {point: new Point3d(point3d.x - xWidth, point3d.y + yWidth, point3d.z)} + ]; + var bottom = [ + {point: new Point3d(point3d.x - xWidth, point3d.y - yWidth, this.zMin)}, + {point: new Point3d(point3d.x + xWidth, point3d.y - yWidth, this.zMin)}, + {point: new Point3d(point3d.x + xWidth, point3d.y + yWidth, this.zMin)}, + {point: new Point3d(point3d.x - xWidth, point3d.y + yWidth, this.zMin)} + ]; - if (filter) { - // get filtered items - if (order) { - // create ordered list - items = []; - for (id in data) { - if (data.hasOwnProperty(id)) { - item = this._getItem(id, type); - if (filter(item)) { - items.push(item); - } - } - } + // calculate screen location of the points + top.forEach(function (obj) { + obj.screen = me._convert3Dto2D(obj.point); + }); + bottom.forEach(function (obj) { + obj.screen = me._convert3Dto2D(obj.point); + }); - this._sort(items, order); + // create five sides, calculate both corner points and center points + var surfaces = [ + {corners: top, center: Point3d.avg(bottom[0].point, bottom[2].point)}, + {corners: [top[0], top[1], bottom[1], bottom[0]], center: Point3d.avg(bottom[1].point, bottom[0].point)}, + {corners: [top[1], top[2], bottom[2], bottom[1]], center: Point3d.avg(bottom[2].point, bottom[1].point)}, + {corners: [top[2], top[3], bottom[3], bottom[2]], center: Point3d.avg(bottom[3].point, bottom[2].point)}, + {corners: [top[3], top[0], bottom[0], bottom[3]], center: Point3d.avg(bottom[0].point, bottom[3].point)} + ]; + point.surfaces = surfaces; - for (i = 0, len = items.length; i < len; i++) { - ids[i] = items[i][this._fieldId]; - } - } - else { - // create unordered list - for (id in data) { - if (data.hasOwnProperty(id)) { - item = this._getItem(id, type); - if (filter(item)) { - ids.push(item[this._fieldId]); - } - } - } + // calculate the distance of each of the surface centers to the camera + for (j = 0; j < surfaces.length; j++) { + surface = surfaces[j]; + var transCenter = this._convertPointToTranslation(surface.center); + surface.dist = this.showPerspective ? transCenter.length() : -transCenter.z; + // TODO: this dept calculation doesn't work 100% of the cases due to perspective, + // but the current solution is fast/simple and works in 99.9% of all cases + // the issue is visible in example 14, with graph.setCameraPosition({horizontal: 2.97, vertical: 0.5, distance: 0.9}) } - } - else { - // get all items - if (order) { - // create an ordered list - items = []; - for (id in data) { - if (data.hasOwnProperty(id)) { - items.push(data[id]); - } - } - this._sort(items, order); + // order the surfaces by their (translated) depth + surfaces.sort(function (a, b) { + var diff = b.dist - a.dist; + if (diff) return diff; - for (i = 0, len = items.length; i < len; i++) { - ids[i] = items[i][this._fieldId]; - } - } - else { - // create unordered list - for (id in data) { - if (data.hasOwnProperty(id)) { - item = data[id]; - ids.push(item[this._fieldId]); - } - } + // if equal depth, sort the top surface last + if (a.corners === top) return 1; + if (b.corners === top) return -1; + + // both are equal + return 0; + }); + + // draw the ordered surfaces + ctx.lineWidth = 1; + ctx.strokeStyle = borderColor; + ctx.fillStyle = color; + // NOTE: we start at j=2 instead of j=0 as we don't need to draw the two surfaces at the backside + for (j = 2; j < surfaces.length; j++) { + surface = surfaces[j]; + corners = surface.corners; + ctx.beginPath(); + ctx.moveTo(corners[3].screen.x, corners[3].screen.y); + ctx.lineTo(corners[0].screen.x, corners[0].screen.y); + ctx.lineTo(corners[1].screen.x, corners[1].screen.y); + ctx.lineTo(corners[2].screen.x, corners[2].screen.y); + ctx.lineTo(corners[3].screen.x, corners[3].screen.y); + ctx.fill(); + ctx.stroke(); } } - - return ids; }; - /** - * Returns the DataSet itself. Is overwritten for example by the DataView, - * which returns the DataSet it is connected to instead. - */ - DataSet.prototype.getDataSet = function () { - return this; - }; /** - * Execute a callback function for every item in the dataset. - * @param {function} callback - * @param {Object} [options] Available options: - * {Object.} [type] - * {String[]} [fields] filter fields - * {function} [filter] filter items - * {String | function} [order] Order the items by - * a field name or custom sort function. + * Draw a line through all datapoints. + * This function can be used when the style is 'line' */ - DataSet.prototype.forEach = function (callback, options) { - var filter = options && options.filter, - type = options && options.type || this._options.type, - data = this._data, - item, - id; + Graph3d.prototype._redrawDataLine = function() { + var canvas = this.frame.canvas, + ctx = canvas.getContext('2d'), + point, i; - if (options && options.order) { - // execute forEach on ordered list - var items = this.get(options); + if (this.dataPoints === undefined || this.dataPoints.length <= 0) + return; // TODO: throw exception? - for (var i = 0, len = items.length; i < len; i++) { - item = items[i]; - id = item[this._fieldId]; - callback(item, id); - } - } - else { - // unordered - for (id in data) { - if (data.hasOwnProperty(id)) { - item = this._getItem(id, type); - if (!filter || filter(item)) { - callback(item, id); - } - } - } + // calculate the translations of all points + for (i = 0; i < this.dataPoints.length; i++) { + var trans = this._convertPointToTranslation(this.dataPoints[i].point); + var screen = this._convertTranslationToScreen(trans); + + this.dataPoints[i].trans = trans; + this.dataPoints[i].screen = screen; } - }; - /** - * Map every item in the dataset. - * @param {function} callback - * @param {Object} [options] Available options: - * {Object.} [type] - * {String[]} [fields] filter fields - * {function} [filter] filter items - * {String | function} [order] Order the items by - * a field name or custom sort function. - * @return {Object[]} mappedItems - */ - DataSet.prototype.map = function (callback, options) { - var filter = options && options.filter, - type = options && options.type || this._options.type, - mappedItems = [], - data = this._data, - item; + // start the line + if (this.dataPoints.length > 0) { + point = this.dataPoints[0]; - // convert and filter items - for (var id in data) { - if (data.hasOwnProperty(id)) { - item = this._getItem(id, type); - if (!filter || filter(item)) { - mappedItems.push(callback(item, id)); - } - } + ctx.lineWidth = 1; // TODO: make customizable + ctx.strokeStyle = 'blue'; // TODO: make customizable + ctx.beginPath(); + ctx.moveTo(point.screen.x, point.screen.y); } - // order items - if (options && options.order) { - this._sort(mappedItems, options.order); + // draw the datapoints as colored circles + for (i = 1; i < this.dataPoints.length; i++) { + point = this.dataPoints[i]; + ctx.lineTo(point.screen.x, point.screen.y); } - return mappedItems; + // finish the line + if (this.dataPoints.length > 0) { + ctx.stroke(); + } }; /** - * Filter the fields of an item - * @param {Object} item - * @param {String[]} fields Field names - * @return {Object} filteredItem - * @private + * Start a moving operation inside the provided parent element + * @param {Event} event The event that occurred (required for + * retrieving the mouse position) */ - DataSet.prototype._filterFields = function (item, fields) { - var filteredItem = {}; + Graph3d.prototype._onMouseDown = function(event) { + event = event || window.event; - for (var field in item) { - if (item.hasOwnProperty(field) && (fields.indexOf(field) != -1)) { - filteredItem[field] = item[field]; - } + // check if mouse is still down (may be up when focus is lost for example + // in an iframe) + if (this.leftButtonDown) { + this._onMouseUp(event); } - return filteredItem; - }; + // only react on left mouse button down + this.leftButtonDown = event.which ? (event.which === 1) : (event.button === 1); + if (!this.leftButtonDown && !this.touchDown) return; - /** - * Sort the provided array with items - * @param {Object[]} items - * @param {String | function} order A field name or custom sort function. - * @private - */ - DataSet.prototype._sort = function (items, order) { - if (util.isString(order)) { - // order by provided field name - var name = order; // field name - items.sort(function (a, b) { - var av = a[name]; - var bv = b[name]; - return (av > bv) ? 1 : ((av < bv) ? -1 : 0); - }); - } - else if (typeof order === 'function') { - // order by sort function - items.sort(order); - } - // TODO: extend order by an Object {field:String, direction:String} - // where direction can be 'asc' or 'desc' - else { - throw new TypeError('Order must be a function or a string'); - } + // get mouse position (different code for IE and all other browsers) + this.startMouseX = getMouseX(event); + this.startMouseY = getMouseY(event); + + this.startStart = new Date(this.start); + this.startEnd = new Date(this.end); + this.startArmRotation = this.camera.getArmRotation(); + + this.frame.style.cursor = 'move'; + + // add event listeners to handle moving the contents + // we store the function onmousemove and onmouseup in the graph, so we can + // remove the eventlisteners lateron in the function mouseUp() + var me = this; + this.onmousemove = function (event) {me._onMouseMove(event);}; + this.onmouseup = function (event) {me._onMouseUp(event);}; + util.addEventListener(document, 'mousemove', me.onmousemove); + util.addEventListener(document, 'mouseup', me.onmouseup); + util.preventDefault(event); }; + /** - * Remove an object by pointer or by id - * @param {String | Number | Object | Array} id Object or id, or an array with - * objects or ids to be removed - * @param {String} [senderId] Optional sender id - * @return {Array} removedIds + * Perform moving operating. + * This function activated from within the funcion Graph.mouseDown(). + * @param {Event} event Well, eehh, the event */ - DataSet.prototype.remove = function (id, senderId) { - var removedIds = [], - i, len, removedId; + Graph3d.prototype._onMouseMove = function (event) { + event = event || window.event; - if (Array.isArray(id)) { - for (i = 0, len = id.length; i < len; i++) { - removedId = this._remove(id[i]); - if (removedId != null) { - removedIds.push(removedId); - } - } - } - else { - removedId = this._remove(id); - if (removedId != null) { - removedIds.push(removedId); - } - } + // calculate change in mouse position + var diffX = parseFloat(getMouseX(event)) - this.startMouseX; + var diffY = parseFloat(getMouseY(event)) - this.startMouseY; - if (removedIds.length) { - this._trigger('remove', {items: removedIds}, senderId); - } + var horizontalNew = this.startArmRotation.horizontal + diffX / 200; + var verticalNew = this.startArmRotation.vertical + diffY / 200; - return removedIds; - }; + var snapAngle = 4; // degrees + var snapValue = Math.sin(snapAngle / 360 * 2 * Math.PI); - /** - * Remove an item by its id - * @param {Number | String | Object} id id or item - * @returns {Number | String | null} id - * @private - */ - DataSet.prototype._remove = function (id) { - if (util.isNumber(id) || util.isString(id)) { - if (this._data[id]) { - delete this._data[id]; - return id; - } + // snap horizontally to nice angles at 0pi, 0.5pi, 1pi, 1.5pi, etc... + // the -0.001 is to take care that the vertical axis is always drawn at the left front corner + if (Math.abs(Math.sin(horizontalNew)) < snapValue) { + horizontalNew = Math.round((horizontalNew / Math.PI)) * Math.PI - 0.001; } - else if (id instanceof Object) { - var itemId = id[this._fieldId]; - if (itemId && this._data[itemId]) { - delete this._data[itemId]; - return itemId; - } + if (Math.abs(Math.cos(horizontalNew)) < snapValue) { + horizontalNew = (Math.round((horizontalNew/ Math.PI - 0.5)) + 0.5) * Math.PI - 0.001; } - return null; - }; - /** - * Clear the data - * @param {String} [senderId] Optional sender id - * @return {Array} removedIds The ids of all removed items - */ - DataSet.prototype.clear = function (senderId) { - var ids = Object.keys(this._data); + // snap vertically to nice angles + if (Math.abs(Math.sin(verticalNew)) < snapValue) { + verticalNew = Math.round((verticalNew / Math.PI)) * Math.PI; + } + if (Math.abs(Math.cos(verticalNew)) < snapValue) { + verticalNew = (Math.round((verticalNew/ Math.PI - 0.5)) + 0.5) * Math.PI; + } - this._data = {}; + this.camera.setArmRotation(horizontalNew, verticalNew); + this.redraw(); - this._trigger('remove', {items: ids}, senderId); + // fire a cameraPositionChange event + var parameters = this.getCameraPosition(); + this.emit('cameraPositionChange', parameters); - return ids; + util.preventDefault(event); }; + /** - * Find the item with maximum value of a specified field - * @param {String} field - * @return {Object | null} item Item containing max value, or null if no items + * Stop moving operating. + * This function activated from within the funcion Graph.mouseDown(). + * @param {event} event The event */ - DataSet.prototype.max = function (field) { - var data = this._data, - max = null, - maxField = null; - - for (var id in data) { - if (data.hasOwnProperty(id)) { - var item = data[id]; - var itemField = item[field]; - if (itemField != null && (!max || itemField > maxField)) { - max = item; - maxField = itemField; - } - } - } + Graph3d.prototype._onMouseUp = function (event) { + this.frame.style.cursor = 'auto'; + this.leftButtonDown = false; - return max; + // remove event listeners here + util.removeEventListener(document, 'mousemove', this.onmousemove); + util.removeEventListener(document, 'mouseup', this.onmouseup); + util.preventDefault(event); }; /** - * Find the item with minimum value of a specified field - * @param {String} field - * @return {Object | null} item Item containing max value, or null if no items + * After having moved the mouse, a tooltip should pop up when the mouse is resting on a data point + * @param {Event} event A mouse move event */ - DataSet.prototype.min = function (field) { - var data = this._data, - min = null, - minField = null; + Graph3d.prototype._onTooltip = function (event) { + var delay = 300; // ms + var mouseX = getMouseX(event) - util.getAbsoluteLeft(this.frame); + var mouseY = getMouseY(event) - util.getAbsoluteTop(this.frame); - for (var id in data) { - if (data.hasOwnProperty(id)) { - var item = data[id]; - var itemField = item[field]; - if (itemField != null && (!min || itemField < minField)) { - min = item; - minField = itemField; - } - } + if (!this.showTooltip) { + return; } - return min; - }; + if (this.tooltipTimeout) { + clearTimeout(this.tooltipTimeout); + } - /** - * Find all distinct values of a specified field - * @param {String} field - * @return {Array} values Array containing all distinct values. If data items - * do not contain the specified field are ignored. - * The returned array is unordered. - */ - DataSet.prototype.distinct = function (field) { - var data = this._data; - var values = []; - var fieldType = this._options.type && this._options.type[field] || null; - var count = 0; - var i; + // (delayed) display of a tooltip only if no mouse button is down + if (this.leftButtonDown) { + this._hideTooltip(); + return; + } - for (var prop in data) { - if (data.hasOwnProperty(prop)) { - var item = data[prop]; - var value = item[field]; - var exists = false; - for (i = 0; i < count; i++) { - if (values[i] == value) { - exists = true; - break; - } + if (this.tooltip && this.tooltip.dataPoint) { + // tooltip is currently visible + var dataPoint = this._dataPointFromXY(mouseX, mouseY); + if (dataPoint !== this.tooltip.dataPoint) { + // datapoint changed + if (dataPoint) { + this._showTooltip(dataPoint); } - if (!exists && (value !== undefined)) { - values[count] = value; - count++; + else { + this._hideTooltip(); } } } + else { + // tooltip is currently not visible + var me = this; + this.tooltipTimeout = setTimeout(function () { + me.tooltipTimeout = null; - if (fieldType) { - for (i = 0; i < values.length; i++) { - values[i] = util.convert(values[i], fieldType); - } + // show a tooltip if we have a data point + var dataPoint = me._dataPointFromXY(mouseX, mouseY); + if (dataPoint) { + me._showTooltip(dataPoint); + } + }, delay); } - - return values; }; /** - * Add a single item. Will fail when an item with the same id already exists. - * @param {Object} item - * @return {String} id - * @private + * Event handler for touchstart event on mobile devices */ - DataSet.prototype._addItem = function (item) { - var id = item[this._fieldId]; + Graph3d.prototype._onTouchStart = function(event) { + this.touchDown = true; - if (id != undefined) { - // check whether this id is already taken - if (this._data[id]) { - // item already exists - throw new Error('Cannot add item: item with id ' + id + ' already exists'); - } - } - else { - // generate an id - id = util.randomUUID(); - item[this._fieldId] = id; - } + var me = this; + this.ontouchmove = function (event) {me._onTouchMove(event);}; + this.ontouchend = function (event) {me._onTouchEnd(event);}; + util.addEventListener(document, 'touchmove', me.ontouchmove); + util.addEventListener(document, 'touchend', me.ontouchend); - var d = {}; - for (var field in item) { - if (item.hasOwnProperty(field)) { - var fieldType = this._type[field]; // type may be undefined - d[field] = util.convert(item[field], fieldType); - } - } - this._data[id] = d; + this._onMouseDown(event); + }; - return id; + /** + * Event handler for touchmove event on mobile devices + */ + Graph3d.prototype._onTouchMove = function(event) { + this._onMouseMove(event); }; /** - * Get an item. Fields can be converted to a specific type - * @param {String} id - * @param {Object.} [types] field types to convert - * @return {Object | null} item - * @private + * Event handler for touchend event on mobile devices */ - DataSet.prototype._getItem = function (id, types) { - var field, value; + Graph3d.prototype._onTouchEnd = function(event) { + this.touchDown = false; - // get the item from the dataset - var raw = this._data[id]; - if (!raw) { - return null; - } + util.removeEventListener(document, 'touchmove', this.ontouchmove); + util.removeEventListener(document, 'touchend', this.ontouchend); - // convert the items field types - var converted = {}; - if (types) { - for (field in raw) { - if (raw.hasOwnProperty(field)) { - value = raw[field]; - converted[field] = util.convert(value, types[field]); - } - } - } - else { - // no field types specified, no converting needed - for (field in raw) { - if (raw.hasOwnProperty(field)) { - value = raw[field]; - converted[field] = value; - } - } - } - return converted; + this._onMouseUp(event); }; + /** - * Update a single item: merge with existing item. - * Will fail when the item has no id, or when there does not exist an item - * with the same id. - * @param {Object} item - * @return {String} id - * @private + * Event handler for mouse wheel event, used to zoom the graph + * Code from http://adomas.org/javascript-mouse-wheel/ + * @param {event} event The event */ - DataSet.prototype._updateItem = function (item) { - var id = item[this._fieldId]; - if (id == undefined) { - throw new Error('Cannot update item: item has no id (item: ' + JSON.stringify(item) + ')'); - } - var d = this._data[id]; - if (!d) { - // item doesn't exist - throw new Error('Cannot update item: no item with id ' + id + ' found'); + Graph3d.prototype._onWheel = function(event) { + if (!event) /* For IE. */ + event = window.event; + + // retrieve delta + var delta = 0; + if (event.wheelDelta) { /* IE/Opera. */ + delta = event.wheelDelta/120; + } else if (event.detail) { /* Mozilla case. */ + // In Mozilla, sign of delta is different than in IE. + // Also, delta is multiple of 3. + delta = -event.detail/3; } - // merge with current item - for (var field in item) { - if (item.hasOwnProperty(field)) { - var fieldType = this._type[field]; // type may be undefined - d[field] = util.convert(item[field], fieldType); - } + // If delta is nonzero, handle it. + // Basically, delta is now positive if wheel was scrolled up, + // and negative, if wheel was scrolled down. + if (delta) { + var oldLength = this.camera.getArmLength(); + var newLength = oldLength * (1 - delta / 10); + + this.camera.setArmLength(newLength); + this.redraw(); + + this._hideTooltip(); } - return id; + // fire a cameraPositionChange event + var parameters = this.getCameraPosition(); + this.emit('cameraPositionChange', parameters); + + // Prevent default actions caused by mouse wheel. + // That might be ugly, but we handle scrolls somehow + // anyway, so don't bother here.. + util.preventDefault(event); }; /** - * Get an array with the column names of a Google DataTable - * @param {DataTable} dataTable - * @return {String[]} columnNames + * Test whether a point lies inside given 2D triangle + * @param {Point2d} point + * @param {Point2d[]} triangle + * @return {boolean} Returns true if given point lies inside or on the edge of the triangle * @private */ - DataSet.prototype._getColumnNames = function (dataTable) { - var columns = []; - for (var col = 0, cols = dataTable.getNumberOfColumns(); col < cols; col++) { - columns[col] = dataTable.getColumnId(col) || dataTable.getColumnLabel(col); + Graph3d.prototype._insideTriangle = function (point, triangle) { + var a = triangle[0], + b = triangle[1], + c = triangle[2]; + + function sign (x) { + return x > 0 ? 1 : x < 0 ? -1 : 0; } - return columns; + + var as = sign((b.x - a.x) * (point.y - a.y) - (b.y - a.y) * (point.x - a.x)); + var bs = sign((c.x - b.x) * (point.y - b.y) - (c.y - b.y) * (point.x - b.x)); + var cs = sign((a.x - c.x) * (point.y - c.y) - (a.y - c.y) * (point.x - c.x)); + + // each of the three signs must be either equal to each other or zero + return (as == 0 || bs == 0 || as == bs) && + (bs == 0 || cs == 0 || bs == cs) && + (as == 0 || cs == 0 || as == cs); }; /** - * Append an item as a row to the dataTable - * @param dataTable - * @param columns - * @param item + * Find a data point close to given screen position (x, y) + * @param {Number} x + * @param {Number} y + * @return {Object | null} The closest data point or null if not close to any data point * @private */ - DataSet.prototype._appendRow = function (dataTable, columns, item) { - var row = dataTable.addRow(); + Graph3d.prototype._dataPointFromXY = function (x, y) { + var i, + distMax = 100, // px + dataPoint = null, + closestDataPoint = null, + closestDist = null, + center = new Point2d(x, y); - for (var col = 0, cols = columns.length; col < cols; col++) { - var field = columns[col]; - dataTable.setValue(row, col, item[field]); + if (this.style === Graph3d.STYLE.BAR || + this.style === Graph3d.STYLE.BARCOLOR || + this.style === Graph3d.STYLE.BARSIZE) { + // the data points are ordered from far away to closest + for (i = this.dataPoints.length - 1; i >= 0; i--) { + dataPoint = this.dataPoints[i]; + var surfaces = dataPoint.surfaces; + if (surfaces) { + for (var s = surfaces.length - 1; s >= 0; s--) { + // split each surface in two triangles, and see if the center point is inside one of these + var surface = surfaces[s]; + var corners = surface.corners; + var triangle1 = [corners[0].screen, corners[1].screen, corners[2].screen]; + var triangle2 = [corners[2].screen, corners[3].screen, corners[0].screen]; + if (this._insideTriangle(center, triangle1) || + this._insideTriangle(center, triangle2)) { + // return immediately at the first hit + return dataPoint; + } + } + } + } } - }; - - module.exports = DataSet; + else { + // find the closest data point, using distance to the center of the point on 2d screen + for (i = 0; i < this.dataPoints.length; i++) { + dataPoint = this.dataPoints[i]; + var point = dataPoint.screen; + if (point) { + var distX = Math.abs(x - point.x); + var distY = Math.abs(y - point.y); + var dist = Math.sqrt(distX * distX + distY * distY); + if ((closestDist === null || dist < closestDist) && dist < distMax) { + closestDist = dist; + closestDataPoint = dataPoint; + } + } + } + } -/***/ }, -/* 8 */ -/***/ function(module, exports, __webpack_require__) { - var util = __webpack_require__(1); - var DataSet = __webpack_require__(7); + return closestDataPoint; + }; /** - * DataView - * - * a dataview offers a filtered view on a dataset or an other dataview. - * - * @param {DataSet | DataView} data - * @param {Object} [options] Available options: see method get - * - * @constructor DataView + * Display a tooltip for given data point + * @param {Object} dataPoint + * @private */ - function DataView (data, options) { - this._data = null; - this._ids = {}; // ids of the items currently in memory (just contains a boolean true) - this._options = options || {}; - this._fieldId = 'id'; // name of the field containing id - this._subscribers = {}; // event subscribers + Graph3d.prototype._showTooltip = function (dataPoint) { + var content, line, dot; - var me = this; - this.listener = function () { - me._onEvent.apply(me, arguments); - }; + if (!this.tooltip) { + content = document.createElement('div'); + content.style.position = 'absolute'; + content.style.padding = '10px'; + content.style.border = '1px solid #4d4d4d'; + content.style.color = '#1a1a1a'; + content.style.background = 'rgba(255,255,255,0.7)'; + content.style.borderRadius = '2px'; + content.style.boxShadow = '5px 5px 10px rgba(128,128,128,0.5)'; - this.setData(data); - } + line = document.createElement('div'); + line.style.position = 'absolute'; + line.style.height = '40px'; + line.style.width = '0'; + line.style.borderLeft = '1px solid #4d4d4d'; - // TODO: implement a function .config() to dynamically update things like configured filter - // and trigger changes accordingly + dot = document.createElement('div'); + dot.style.position = 'absolute'; + dot.style.height = '0'; + dot.style.width = '0'; + dot.style.border = '5px solid #4d4d4d'; + dot.style.borderRadius = '5px'; - /** - * Set a data source for the view - * @param {DataSet | DataView} data - */ - DataView.prototype.setData = function (data) { - var ids, i, len; + this.tooltip = { + dataPoint: null, + dom: { + content: content, + line: line, + dot: dot + } + }; + } + else { + content = this.tooltip.dom.content; + line = this.tooltip.dom.line; + dot = this.tooltip.dom.dot; + } - if (this._data) { - // unsubscribe from current dataset - if (this._data.unsubscribe) { - this._data.unsubscribe('*', this.listener); - } + this._hideTooltip(); - // trigger a remove of all items in memory - ids = []; - for (var id in this._ids) { - if (this._ids.hasOwnProperty(id)) { - ids.push(id); - } - } - this._ids = {}; - this._trigger('remove', {items: ids}); + this.tooltip.dataPoint = dataPoint; + if (typeof this.showTooltip === 'function') { + content.innerHTML = this.showTooltip(dataPoint.point); + } + else { + content.innerHTML = '' + + '' + + '' + + '' + + '
x:' + dataPoint.point.x + '
y:' + dataPoint.point.y + '
z:' + dataPoint.point.z + '
'; } - this._data = data; + content.style.left = '0'; + content.style.top = '0'; + this.frame.appendChild(content); + this.frame.appendChild(line); + this.frame.appendChild(dot); - if (this._data) { - // update fieldId - this._fieldId = this._options.fieldId || - (this._data && this._data.options && this._data.options.fieldId) || - 'id'; + // calculate sizes + var contentWidth = content.offsetWidth; + var contentHeight = content.offsetHeight; + var lineHeight = line.offsetHeight; + var dotWidth = dot.offsetWidth; + var dotHeight = dot.offsetHeight; - // trigger an add of all added items - ids = this._data.getIds({filter: this._options && this._options.filter}); - for (i = 0, len = ids.length; i < len; i++) { - id = ids[i]; - this._ids[id] = true; - } - this._trigger('add', {items: ids}); + var left = dataPoint.screen.x - contentWidth / 2; + left = Math.min(Math.max(left, 10), this.frame.clientWidth - 10 - contentWidth); - // subscribe to new dataset - if (this._data.on) { - this._data.on('*', this.listener); - } - } + line.style.left = dataPoint.screen.x + 'px'; + line.style.top = (dataPoint.screen.y - lineHeight) + 'px'; + content.style.left = left + 'px'; + content.style.top = (dataPoint.screen.y - lineHeight - contentHeight) + 'px'; + dot.style.left = (dataPoint.screen.x - dotWidth / 2) + 'px'; + dot.style.top = (dataPoint.screen.y - dotHeight / 2) + 'px'; }; /** - * Get data from the data view - * - * Usage: - * - * get() - * get(options: Object) - * get(options: Object, data: Array | DataTable) - * - * get(id: Number) - * get(id: Number, options: Object) - * get(id: Number, options: Object, data: Array | DataTable) - * - * get(ids: Number[]) - * get(ids: Number[], options: Object) - * get(ids: Number[], options: Object, data: Array | DataTable) - * - * Where: - * - * {Number | String} id The id of an item - * {Number[] | String{}} ids An array with ids of items - * {Object} options An Object with options. Available options: - * {String} [type] Type of data to be returned. Can - * be 'DataTable' or 'Array' (default) - * {Object.} [convert] - * {String[]} [fields] field names to be returned - * {function} [filter] filter items - * {String | function} [order] Order the items by - * a field name or custom sort function. - * {Array | DataTable} [data] If provided, items will be appended to this - * array or table. Required in case of Google - * DataTable. - * @param args + * Hide the tooltip when displayed + * @private */ - DataView.prototype.get = function (args) { - var me = this; + Graph3d.prototype._hideTooltip = function () { + if (this.tooltip) { + this.tooltip.dataPoint = null; - // parse the arguments - var ids, options, data; - var firstType = util.getType(arguments[0]); - if (firstType == 'String' || firstType == 'Number' || firstType == 'Array') { - // get(id(s) [, options] [, data]) - ids = arguments[0]; // can be a single id or an array with ids - options = arguments[1]; - data = arguments[2]; - } - else { - // get([, options] [, data]) - options = arguments[0]; - data = arguments[1]; - } - - // extend the options with the default options and provided options - var viewOptions = util.extend({}, this._options, options); - - // create a combined filter method when needed - if (this._options.filter && options && options.filter) { - viewOptions.filter = function (item) { - return me._options.filter(item) && options.filter(item); + for (var prop in this.tooltip.dom) { + if (this.tooltip.dom.hasOwnProperty(prop)) { + var elem = this.tooltip.dom[prop]; + if (elem && elem.parentNode) { + elem.parentNode.removeChild(elem); + } + } } } + }; - // build up the call to the linked data set - var getArguments = []; - if (ids != undefined) { - getArguments.push(ids); - } - getArguments.push(viewOptions); - getArguments.push(data); + /**--------------------------------------------------------------------------**/ - return this._data && this._data.get.apply(this._data, getArguments); + + /** + * Get the horizontal mouse position from a mouse event + * @param {Event} event + * @return {Number} mouse x + */ + getMouseX = function(event) { + if ('clientX' in event) return event.clientX; + return event.targetTouches[0] && event.targetTouches[0].clientX || 0; }; /** - * Get ids of all items or from a filtered set of items. - * @param {Object} [options] An Object with options. Available options: - * {function} [filter] filter items - * {String | function} [order] Order the items by - * a field name or custom sort function. - * @return {Array} ids + * Get the vertical mouse position from a mouse event + * @param {Event} event + * @return {Number} mouse y */ - DataView.prototype.getIds = function (options) { - var ids; + getMouseY = function(event) { + if ('clientY' in event) return event.clientY; + return event.targetTouches[0] && event.targetTouches[0].clientY || 0; + }; - if (this._data) { - var defaultFilter = this._options.filter; - var filter; + module.exports = Graph3d; - if (options && options.filter) { - if (defaultFilter) { - filter = function (item) { - return defaultFilter(item) && options.filter(item); - } - } - else { - filter = options.filter; - } - } - else { - filter = defaultFilter; - } - ids = this._data.getIds({ - filter: filter, - order: options && options.order - }); - } - else { - ids = []; - } +/***/ }, +/* 6 */ +/***/ function(module, exports, __webpack_require__) { - return ids; - }; + var Point3d = __webpack_require__(9); /** - * Get the DataSet to which this DataView is connected. In case there is a chain - * of multiple DataViews, the root DataSet of this chain is returned. - * @return {DataSet} dataSet + * @class Camera + * The camera is mounted on a (virtual) camera arm. The camera arm can rotate + * The camera is always looking in the direction of the origin of the arm. + * This way, the camera always rotates around one fixed point, the location + * of the camera arm. + * + * Documentation: + * http://en.wikipedia.org/wiki/3D_projection */ - DataView.prototype.getDataSet = function () { - var dataSet = this; - while (dataSet instanceof DataView) { - dataSet = dataSet._data; - } - return dataSet || null; + Camera = function () { + this.armLocation = new Point3d(); + this.armRotation = {}; + this.armRotation.horizontal = 0; + this.armRotation.vertical = 0; + this.armLength = 1.7; + + this.cameraLocation = new Point3d(); + this.cameraRotation = new Point3d(0.5*Math.PI, 0, 0); + + this.calculateCameraOrientation(); }; /** - * Event listener. Will propagate all events from the connected data set to - * the subscribers of the DataView, but will filter the items and only trigger - * when there are changes in the filtered data set. - * @param {String} event - * @param {Object | null} params - * @param {String} senderId - * @private + * Set the location (origin) of the arm + * @param {Number} x Normalized value of x + * @param {Number} y Normalized value of y + * @param {Number} z Normalized value of z */ - DataView.prototype._onEvent = function (event, params, senderId) { - var i, len, id, item, - ids = params && params.items, - data = this._data, - added = [], - updated = [], - removed = []; - - if (ids && data) { - switch (event) { - case 'add': - // filter the ids of the added items - for (i = 0, len = ids.length; i < len; i++) { - id = ids[i]; - item = this.get(id); - if (item) { - this._ids[id] = true; - added.push(id); - } - } - - break; - - case 'update': - // determine the event from the views viewpoint: an updated - // item can be added, updated, or removed from this view. - for (i = 0, len = ids.length; i < len; i++) { - id = ids[i]; - item = this.get(id); - - if (item) { - if (this._ids[id]) { - updated.push(id); - } - else { - this._ids[id] = true; - added.push(id); - } - } - else { - if (this._ids[id]) { - delete this._ids[id]; - removed.push(id); - } - else { - // nothing interesting for me :-( - } - } - } + Camera.prototype.setArmLocation = function(x, y, z) { + this.armLocation.x = x; + this.armLocation.y = y; + this.armLocation.z = z; - break; + this.calculateCameraOrientation(); + }; - case 'remove': - // filter the ids of the removed items - for (i = 0, len = ids.length; i < len; i++) { - id = ids[i]; - if (this._ids[id]) { - delete this._ids[id]; - removed.push(id); - } - } + /** + * Set the rotation of the camera arm + * @param {Number} horizontal The horizontal rotation, between 0 and 2*PI. + * Optional, can be left undefined. + * @param {Number} vertical The vertical rotation, between 0 and 0.5*PI + * if vertical=0.5*PI, the graph is shown from the + * top. Optional, can be left undefined. + */ + Camera.prototype.setArmRotation = function(horizontal, vertical) { + if (horizontal !== undefined) { + this.armRotation.horizontal = horizontal; + } - break; - } + if (vertical !== undefined) { + this.armRotation.vertical = vertical; + if (this.armRotation.vertical < 0) this.armRotation.vertical = 0; + if (this.armRotation.vertical > 0.5*Math.PI) this.armRotation.vertical = 0.5*Math.PI; + } - if (added.length) { - this._trigger('add', {items: added}, senderId); - } - if (updated.length) { - this._trigger('update', {items: updated}, senderId); - } - if (removed.length) { - this._trigger('remove', {items: removed}, senderId); - } + if (horizontal !== undefined || vertical !== undefined) { + this.calculateCameraOrientation(); } }; - // copy subscription functionality from DataSet - DataView.prototype.on = DataSet.prototype.on; - DataView.prototype.off = DataSet.prototype.off; - DataView.prototype._trigger = DataSet.prototype._trigger; - - // TODO: make these functions deprecated (replaced with `on` and `off` since version 0.5) - DataView.prototype.subscribe = DataView.prototype.on; - DataView.prototype.unsubscribe = DataView.prototype.off; + /** + * Retrieve the current arm rotation + * @return {object} An object with parameters horizontal and vertical + */ + Camera.prototype.getArmRotation = function() { + var rot = {}; + rot.horizontal = this.armRotation.horizontal; + rot.vertical = this.armRotation.vertical; - module.exports = DataView; + return rot; + }; -/***/ }, -/* 9 */ -/***/ function(module, exports, __webpack_require__) { + /** + * Set the (normalized) length of the camera arm. + * @param {Number} length A length between 0.71 and 5.0 + */ + Camera.prototype.setArmLength = function(length) { + if (length === undefined) + return; - var Emitter = __webpack_require__(10); - var DataSet = __webpack_require__(7); - var DataView = __webpack_require__(8); - var util = __webpack_require__(1); - var Point3d = __webpack_require__(11); - var Point2d = __webpack_require__(12); - var Camera = __webpack_require__(13); - var Filter = __webpack_require__(14); - var Slider = __webpack_require__(15); - var StepNumber = __webpack_require__(16); + this.armLength = length; - /** - * @constructor Graph3d - * Graph3d displays data in 3d. - * - * Graph3d is developed in javascript as a Google Visualization Chart. - * - * @param {Element} container The DOM element in which the Graph3d will - * be created. Normally a div element. - * @param {DataSet | DataView | Array} [data] - * @param {Object} [options] + // Radius must be larger than the corner of the graph, + // which has a distance of sqrt(0.5^2+0.5^2) = 0.71 from the center of the + // graph + if (this.armLength < 0.71) this.armLength = 0.71; + if (this.armLength > 5.0) this.armLength = 5.0; + + this.calculateCameraOrientation(); + }; + + /** + * Retrieve the arm length + * @return {Number} length */ - function Graph3d(container, data, options) { - if (!(this instanceof Graph3d)) { - throw new SyntaxError('Constructor must be called with the new operator'); - } + Camera.prototype.getArmLength = function() { + return this.armLength; + }; - // create variables and set default values - this.containerElement = container; - this.width = '400px'; - this.height = '400px'; - this.margin = 10; // px - this.defaultXCenter = '55%'; - this.defaultYCenter = '50%'; + /** + * Retrieve the camera location + * @return {Point3d} cameraLocation + */ + Camera.prototype.getCameraLocation = function() { + return this.cameraLocation; + }; - this.xLabel = 'x'; - this.yLabel = 'y'; - this.zLabel = 'z'; - this.filterLabel = 'time'; - this.legendLabel = 'value'; + /** + * Retrieve the camera rotation + * @return {Point3d} cameraRotation + */ + Camera.prototype.getCameraRotation = function() { + return this.cameraRotation; + }; - this.style = Graph3d.STYLE.DOT; - this.showPerspective = true; - this.showGrid = true; - this.keepAspectRatio = true; - this.showShadow = false; - this.showGrayBottom = false; // TODO: this does not work correctly - this.showTooltip = false; - this.verticalRatio = 0.5; // 0.1 to 1.0, where 1.0 results in a 'cube' + /** + * Calculate the location and rotation of the camera based on the + * position and orientation of the camera arm + */ + Camera.prototype.calculateCameraOrientation = function() { + // calculate location of the camera + this.cameraLocation.x = this.armLocation.x - this.armLength * Math.sin(this.armRotation.horizontal) * Math.cos(this.armRotation.vertical); + this.cameraLocation.y = this.armLocation.y - this.armLength * Math.cos(this.armRotation.horizontal) * Math.cos(this.armRotation.vertical); + this.cameraLocation.z = this.armLocation.z + this.armLength * Math.sin(this.armRotation.vertical); - this.animationInterval = 1000; // milliseconds - this.animationPreload = false; + // calculate rotation of the camera + this.cameraRotation.x = Math.PI/2 - this.armRotation.vertical; + this.cameraRotation.y = 0; + this.cameraRotation.z = -this.armRotation.horizontal; + }; - this.camera = new Camera(); - this.eye = new Point3d(0, 0, -1); // TODO: set eye.z about 3/4 of the width of the window? + module.exports = Camera; - this.dataTable = null; // The original data table - this.dataPoints = null; // The table with point objects +/***/ }, +/* 7 */ +/***/ function(module, exports, __webpack_require__) { - // the column indexes - this.colX = undefined; - this.colY = undefined; - this.colZ = undefined; - this.colValue = undefined; - this.colFilter = undefined; + var DataView = __webpack_require__(4); - this.xMin = 0; - this.xStep = undefined; // auto by default - this.xMax = 1; - this.yMin = 0; - this.yStep = undefined; // auto by default - this.yMax = 1; - this.zMin = 0; - this.zStep = undefined; // auto by default - this.zMax = 1; - this.valueMin = 0; - this.valueMax = 1; - this.xBarWidth = 1; - this.yBarWidth = 1; - // TODO: customize axis range + /** + * @class Filter + * + * @param {DataSet} data The google data table + * @param {Number} column The index of the column to be filtered + * @param {Graph} graph The graph + */ + function Filter (data, column, graph) { + this.data = data; + this.column = column; + this.graph = graph; // the parent graph - // constants - this.colorAxis = '#4D4D4D'; - this.colorGrid = '#D3D3D3'; - this.colorDot = '#7DC1FF'; - this.colorDotBorder = '#3267D2'; + this.index = undefined; + this.value = undefined; - // create a frame and canvas - this.create(); + // read all distinct values and select the first one + this.values = graph.getDistinctValues(data.get(), this.column); - // apply options (also when undefined) - this.setOptions(options); + // sort both numeric and string values correctly + this.values.sort(function (a, b) { + return a > b ? 1 : a < b ? -1 : 0; + }); - // apply data - if (data) { - this.setData(data); + if (this.values.length > 0) { + this.selectValue(0); } - } - // Extend Graph3d with an Emitter mixin - Emitter(Graph3d.prototype); + // create an array with the filtered datapoints. this will be loaded afterwards + this.dataPoints = []; + + this.loaded = false; + this.onLoadCallback = undefined; + + if (graph.animationPreload) { + this.loaded = false; + this.loadInBackground(); + } + else { + this.loaded = true; + } + }; + /** - * Calculate the scaling values, dependent on the range in x, y, and z direction + * Return the label + * @return {string} label */ - Graph3d.prototype._setScale = function() { - this.scale = new Point3d(1 / (this.xMax - this.xMin), - 1 / (this.yMax - this.yMin), - 1 / (this.zMax - this.zMin)); + Filter.prototype.isLoaded = function() { + return this.loaded; + }; - // keep aspect ration between x and y scale if desired - if (this.keepAspectRatio) { - if (this.scale.x < this.scale.y) { - //noinspection JSSuspiciousNameCombination - this.scale.y = this.scale.x; - } - else { - //noinspection JSSuspiciousNameCombination - this.scale.x = this.scale.y; - } - } - // scale the vertical axis - this.scale.z *= this.verticalRatio; - // TODO: can this be automated? verticalRatio? + /** + * Return the loaded progress + * @return {Number} percentage between 0 and 100 + */ + Filter.prototype.getLoadedProgress = function() { + var len = this.values.length; - // determine scale for (optional) value - this.scale.value = 1 / (this.valueMax - this.valueMin); + var i = 0; + while (this.dataPoints[i]) { + i++; + } - // position the camera arm - var xCenter = (this.xMax + this.xMin) / 2 * this.scale.x; - var yCenter = (this.yMax + this.yMin) / 2 * this.scale.y; - var zCenter = (this.zMax + this.zMin) / 2 * this.scale.z; - this.camera.setArmLocation(xCenter, yCenter, zCenter); + return Math.round(i / len * 100); }; /** - * Convert a 3D location to a 2D location on screen - * http://en.wikipedia.org/wiki/3D_projection - * @param {Point3d} point3d A 3D point with parameters x, y, z - * @return {Point2d} point2d A 2D point with parameters x, y + * Return the label + * @return {string} label */ - Graph3d.prototype._convert3Dto2D = function(point3d) { - var translation = this._convertPointToTranslation(point3d); - return this._convertTranslationToScreen(translation); + Filter.prototype.getLabel = function() { + return this.graph.filterLabel; }; + /** - * Convert a 3D location its translation seen from the camera - * http://en.wikipedia.org/wiki/3D_projection - * @param {Point3d} point3d A 3D point with parameters x, y, z - * @return {Point3d} translation A 3D point with parameters x, y, z This is - * the translation of the point, seen from the - * camera + * Return the columnIndex of the filter + * @return {Number} columnIndex */ - Graph3d.prototype._convertPointToTranslation = function(point3d) { - var ax = point3d.x * this.scale.x, - ay = point3d.y * this.scale.y, - az = point3d.z * this.scale.z, - - cx = this.camera.getCameraLocation().x, - cy = this.camera.getCameraLocation().y, - cz = this.camera.getCameraLocation().z, + Filter.prototype.getColumn = function() { + return this.column; + }; - // calculate angles - sinTx = Math.sin(this.camera.getCameraRotation().x), - cosTx = Math.cos(this.camera.getCameraRotation().x), - sinTy = Math.sin(this.camera.getCameraRotation().y), - cosTy = Math.cos(this.camera.getCameraRotation().y), - sinTz = Math.sin(this.camera.getCameraRotation().z), - cosTz = Math.cos(this.camera.getCameraRotation().z), + /** + * Return the currently selected value. Returns undefined if there is no selection + * @return {*} value + */ + Filter.prototype.getSelectedValue = function() { + if (this.index === undefined) + return undefined; - // calculate translation - dx = cosTy * (sinTz * (ay - cy) + cosTz * (ax - cx)) - sinTy * (az - cz), - dy = sinTx * (cosTy * (az - cz) + sinTy * (sinTz * (ay - cy) + cosTz * (ax - cx))) + cosTx * (cosTz * (ay - cy) - sinTz * (ax-cx)), - dz = cosTx * (cosTy * (az - cz) + sinTy * (sinTz * (ay - cy) + cosTz * (ax - cx))) - sinTx * (cosTz * (ay - cy) - sinTz * (ax-cx)); + return this.values[this.index]; + }; - return new Point3d(dx, dy, dz); + /** + * Retrieve all values of the filter + * @return {Array} values + */ + Filter.prototype.getValues = function() { + return this.values; }; /** - * Convert a translation point to a point on the screen - * @param {Point3d} translation A 3D point with parameters x, y, z This is - * the translation of the point, seen from the - * camera - * @return {Point2d} point2d A 2D point with parameters x, y + * Retrieve one value of the filter + * @param {Number} index + * @return {*} value */ - Graph3d.prototype._convertTranslationToScreen = function(translation) { - var ex = this.eye.x, - ey = this.eye.y, - ez = this.eye.z, - dx = translation.x, - dy = translation.y, - dz = translation.z; - - // calculate position on screen from translation - var bx; - var by; - if (this.showPerspective) { - bx = (dx - ex) * (ez / dz); - by = (dy - ey) * (ez / dz); - } - else { - bx = dx * -(ez / this.camera.getArmLength()); - by = dy * -(ez / this.camera.getArmLength()); - } + Filter.prototype.getValue = function(index) { + if (index >= this.values.length) + throw 'Error: index out of range'; - // shift and scale the point to the center of the screen - // use the width of the graph to scale both horizontally and vertically. - return new Point2d( - this.xcenter + bx * this.frame.canvas.clientWidth, - this.ycenter - by * this.frame.canvas.clientWidth); + return this.values[index]; }; + /** - * Set the background styling for the graph - * @param {string | {fill: string, stroke: string, strokeWidth: string}} backgroundColor + * Retrieve the (filtered) dataPoints for the currently selected filter index + * @param {Number} [index] (optional) + * @return {Array} dataPoints */ - Graph3d.prototype._setBackgroundColor = function(backgroundColor) { - var fill = 'white'; - var stroke = 'gray'; - var strokeWidth = 1; + Filter.prototype._getDataPoints = function(index) { + if (index === undefined) + index = this.index; - if (typeof(backgroundColor) === 'string') { - fill = backgroundColor; - stroke = 'none'; - strokeWidth = 0; - } - else if (typeof(backgroundColor) === 'object') { - if (backgroundColor.fill !== undefined) fill = backgroundColor.fill; - if (backgroundColor.stroke !== undefined) stroke = backgroundColor.stroke; - if (backgroundColor.strokeWidth !== undefined) strokeWidth = backgroundColor.strokeWidth; - } - else if (backgroundColor === undefined) { - // use use defaults + if (index === undefined) + return []; + + var dataPoints; + if (this.dataPoints[index]) { + dataPoints = this.dataPoints[index]; } else { - throw 'Unsupported type of backgroundColor'; + var f = {}; + f.column = this.column; + f.value = this.values[index]; + + var dataView = new DataView(this.data,{filter: function (item) {return (item[f.column] == f.value);}}).get(); + dataPoints = this.graph._getDataPoints(dataView); + + this.dataPoints[index] = dataPoints; } - this.frame.style.backgroundColor = fill; - this.frame.style.borderColor = stroke; - this.frame.style.borderWidth = strokeWidth + 'px'; - this.frame.style.borderStyle = 'solid'; + return dataPoints; }; - /// enumerate the available styles - Graph3d.STYLE = { - BAR: 0, - BARCOLOR: 1, - BARSIZE: 2, - DOT : 3, - DOTLINE : 4, - DOTCOLOR: 5, - DOTSIZE: 6, - GRID : 7, - LINE: 8, - SURFACE : 9 + + /** + * Set a callback function when the filter is fully loaded. + */ + Filter.prototype.setOnLoadCallback = function(callback) { + this.onLoadCallback = callback; }; + /** - * Retrieve the style index from given styleName - * @param {string} styleName Style name such as 'dot', 'grid', 'dot-line' - * @return {Number} styleNumber Enumeration value representing the style, or -1 - * when not found + * Add a value to the list with available values for this filter + * No double entries will be created. + * @param {Number} index */ - Graph3d.prototype._getStyleNumber = function(styleName) { - switch (styleName) { - case 'dot': return Graph3d.STYLE.DOT; - case 'dot-line': return Graph3d.STYLE.DOTLINE; - case 'dot-color': return Graph3d.STYLE.DOTCOLOR; - case 'dot-size': return Graph3d.STYLE.DOTSIZE; - case 'line': return Graph3d.STYLE.LINE; - case 'grid': return Graph3d.STYLE.GRID; - case 'surface': return Graph3d.STYLE.SURFACE; - case 'bar': return Graph3d.STYLE.BAR; - case 'bar-color': return Graph3d.STYLE.BARCOLOR; - case 'bar-size': return Graph3d.STYLE.BARSIZE; - } + Filter.prototype.selectValue = function(index) { + if (index >= this.values.length) + throw 'Error: index out of range'; - return -1; + this.index = index; + this.value = this.values[index]; }; /** - * Determine the indexes of the data columns, based on the given style and data - * @param {DataSet} data - * @param {Number} style + * Load all filtered rows in the background one by one + * Start this method without providing an index! */ - Graph3d.prototype._determineColumnIndexes = function(data, style) { - if (this.style === Graph3d.STYLE.DOT || - this.style === Graph3d.STYLE.DOTLINE || - this.style === Graph3d.STYLE.LINE || - this.style === Graph3d.STYLE.GRID || - this.style === Graph3d.STYLE.SURFACE || - this.style === Graph3d.STYLE.BAR) { - // 3 columns expected, and optionally a 4th with filter values - this.colX = 0; - this.colY = 1; - this.colZ = 2; - this.colValue = undefined; + Filter.prototype.loadInBackground = function(index) { + if (index === undefined) + index = 0; - if (data.getNumberOfColumns() > 3) { - this.colFilter = 3; - } - } - else if (this.style === Graph3d.STYLE.DOTCOLOR || - this.style === Graph3d.STYLE.DOTSIZE || - this.style === Graph3d.STYLE.BARCOLOR || - this.style === Graph3d.STYLE.BARSIZE) { - // 4 columns expected, and optionally a 5th with filter values - this.colX = 0; - this.colY = 1; - this.colZ = 2; - this.colValue = 3; + var frame = this.graph.frame; - if (data.getNumberOfColumns() > 4) { - this.colFilter = 4; + if (index < this.values.length) { + var dataPointsTemp = this._getDataPoints(index); + //this.graph.redrawInfo(); // TODO: not neat + + // create a progress box + if (frame.progress === undefined) { + frame.progress = document.createElement('DIV'); + frame.progress.style.position = 'absolute'; + frame.progress.style.color = 'gray'; + frame.appendChild(frame.progress); } + var progress = this.getLoadedProgress(); + frame.progress.innerHTML = 'Loading animation... ' + progress + '%'; + // TODO: this is no nice solution... + frame.progress.style.bottom = 60 + 'px'; // TODO: use height of slider + frame.progress.style.left = 10 + 'px'; + + var me = this; + setTimeout(function() {me.loadInBackground(index+1);}, 10); + this.loaded = false; } else { - throw 'Unknown style "' + this.style + '"'; - } - }; - - Graph3d.prototype.getNumberOfRows = function(data) { - return data.length; - } - + this.loaded = true; - Graph3d.prototype.getNumberOfColumns = function(data) { - var counter = 0; - for (var column in data[0]) { - if (data[0].hasOwnProperty(column)) { - counter++; + // remove the progress box + if (frame.progress !== undefined) { + frame.removeChild(frame.progress); + frame.progress = undefined; } - } - return counter; - } - - Graph3d.prototype.getDistinctValues = function(data, column) { - var distinctValues = []; - for (var i = 0; i < data.length; i++) { - if (distinctValues.indexOf(data[i][column]) == -1) { - distinctValues.push(data[i][column]); - } + if (this.onLoadCallback) + this.onLoadCallback(); } - return distinctValues; - } + }; + module.exports = Filter; - Graph3d.prototype.getColumnRange = function(data,column) { - var minMax = {min:data[0][column],max:data[0][column]}; - for (var i = 0; i < data.length; i++) { - if (minMax.min > data[i][column]) { minMax.min = data[i][column]; } - if (minMax.max < data[i][column]) { minMax.max = data[i][column]; } - } - return minMax; - }; + +/***/ }, +/* 8 */ +/***/ function(module, exports, __webpack_require__) { /** - * Initialize the data from the data table. Calculate minimum and maximum values - * and column index values - * @param {Array | DataSet | DataView} rawData The data containing the items for the Graph. - * @param {Number} style Style Number + * @prototype Point2d + * @param {Number} [x] + * @param {Number} [y] */ - Graph3d.prototype._dataInitialize = function (rawData, style) { - var me = this; + Point2d = function (x, y) { + this.x = x !== undefined ? x : 0; + this.y = y !== undefined ? y : 0; + }; - // unsubscribe from the dataTable - if (this.dataSet) { - this.dataSet.off('*', this._onChange); - } + module.exports = Point2d; - if (rawData === undefined) - return; - if (Array.isArray(rawData)) { - rawData = new DataSet(rawData); - } +/***/ }, +/* 9 */ +/***/ function(module, exports, __webpack_require__) { - var data; - if (rawData instanceof DataSet || rawData instanceof DataView) { - data = rawData.get(); - } - else { - throw new Error('Array, DataSet, or DataView expected'); - } + /** + * @prototype Point3d + * @param {Number} [x] + * @param {Number} [y] + * @param {Number} [z] + */ + function Point3d(x, y, z) { + this.x = x !== undefined ? x : 0; + this.y = y !== undefined ? y : 0; + this.z = z !== undefined ? z : 0; + }; - if (data.length == 0) - return; + /** + * Subtract the two provided points, returns a-b + * @param {Point3d} a + * @param {Point3d} b + * @return {Point3d} a-b + */ + Point3d.subtract = function(a, b) { + var sub = new Point3d(); + sub.x = a.x - b.x; + sub.y = a.y - b.y; + sub.z = a.z - b.z; + return sub; + }; - this.dataSet = rawData; - this.dataTable = data; + /** + * Add the two provided points, returns a+b + * @param {Point3d} a + * @param {Point3d} b + * @return {Point3d} a+b + */ + Point3d.add = function(a, b) { + var sum = new Point3d(); + sum.x = a.x + b.x; + sum.y = a.y + b.y; + sum.z = a.z + b.z; + return sum; + }; - // subscribe to changes in the dataset - this._onChange = function () { - me.setData(me.dataSet); - }; - this.dataSet.on('*', this._onChange); + /** + * Calculate the average of two 3d points + * @param {Point3d} a + * @param {Point3d} b + * @return {Point3d} The average, (a+b)/2 + */ + Point3d.avg = function(a, b) { + return new Point3d( + (a.x + b.x) / 2, + (a.y + b.y) / 2, + (a.z + b.z) / 2 + ); + }; - // _determineColumnIndexes - // getNumberOfRows (points) - // getNumberOfColumns (x,y,z,v,t,t1,t2...) - // getDistinctValues (unique values?) - // getColumnRange + /** + * Calculate the cross product of the two provided points, returns axb + * Documentation: http://en.wikipedia.org/wiki/Cross_product + * @param {Point3d} a + * @param {Point3d} b + * @return {Point3d} cross product axb + */ + Point3d.crossProduct = function(a, b) { + var crossproduct = new Point3d(); - // determine the location of x,y,z,value,filter columns - this.colX = 'x'; - this.colY = 'y'; - this.colZ = 'z'; - this.colValue = 'style'; - this.colFilter = 'filter'; + crossproduct.x = a.y * b.z - a.z * b.y; + crossproduct.y = a.z * b.x - a.x * b.z; + crossproduct.z = a.x * b.y - a.y * b.x; + return crossproduct; + }; - // check if a filter column is provided - if (data[0].hasOwnProperty('filter')) { - if (this.dataFilter === undefined) { - this.dataFilter = new Filter(rawData, this.colFilter, this); - this.dataFilter.setOnLoadCallback(function() {me.redraw();}); - } - } + /** + * Rtrieve the length of the vector (or the distance from this point to the origin + * @return {Number} length + */ + Point3d.prototype.length = function() { + return Math.sqrt( + this.x * this.x + + this.y * this.y + + this.z * this.z + ); + }; + module.exports = Point3d; - var withBars = this.style == Graph3d.STYLE.BAR || - this.style == Graph3d.STYLE.BARCOLOR || - this.style == Graph3d.STYLE.BARSIZE; - // determine barWidth from data - if (withBars) { - if (this.defaultXBarWidth !== undefined) { - this.xBarWidth = this.defaultXBarWidth; - } - else { - var dataX = this.getDistinctValues(data,this.colX); - this.xBarWidth = (dataX[1] - dataX[0]) || 1; - } +/***/ }, +/* 10 */ +/***/ function(module, exports, __webpack_require__) { - if (this.defaultYBarWidth !== undefined) { - this.yBarWidth = this.defaultYBarWidth; - } - else { - var dataY = this.getDistinctValues(data,this.colY); - this.yBarWidth = (dataY[1] - dataY[0]) || 1; - } - } + var util = __webpack_require__(1); - // calculate minimums and maximums - var xRange = this.getColumnRange(data,this.colX); - if (withBars) { - xRange.min -= this.xBarWidth / 2; - xRange.max += this.xBarWidth / 2; + /** + * @constructor Slider + * + * An html slider control with start/stop/prev/next buttons + * @param {Element} container The element where the slider will be created + * @param {Object} options Available options: + * {boolean} visible If true (default) the + * slider is visible. + */ + function Slider(container, options) { + if (container === undefined) { + throw 'Error: No container element defined'; } - this.xMin = (this.defaultXMin !== undefined) ? this.defaultXMin : xRange.min; - this.xMax = (this.defaultXMax !== undefined) ? this.defaultXMax : xRange.max; - if (this.xMax <= this.xMin) this.xMax = this.xMin + 1; - this.xStep = (this.defaultXStep !== undefined) ? this.defaultXStep : (this.xMax-this.xMin)/5; + this.container = container; + this.visible = (options && options.visible != undefined) ? options.visible : true; - var yRange = this.getColumnRange(data,this.colY); - if (withBars) { - yRange.min -= this.yBarWidth / 2; - yRange.max += this.yBarWidth / 2; - } - this.yMin = (this.defaultYMin !== undefined) ? this.defaultYMin : yRange.min; - this.yMax = (this.defaultYMax !== undefined) ? this.defaultYMax : yRange.max; - if (this.yMax <= this.yMin) this.yMax = this.yMin + 1; - this.yStep = (this.defaultYStep !== undefined) ? this.defaultYStep : (this.yMax-this.yMin)/5; + if (this.visible) { + this.frame = document.createElement('DIV'); + //this.frame.style.backgroundColor = '#E5E5E5'; + this.frame.style.width = '100%'; + this.frame.style.position = 'relative'; + this.container.appendChild(this.frame); - var zRange = this.getColumnRange(data,this.colZ); - this.zMin = (this.defaultZMin !== undefined) ? this.defaultZMin : zRange.min; - this.zMax = (this.defaultZMax !== undefined) ? this.defaultZMax : zRange.max; - if (this.zMax <= this.zMin) this.zMax = this.zMin + 1; - this.zStep = (this.defaultZStep !== undefined) ? this.defaultZStep : (this.zMax-this.zMin)/5; + this.frame.prev = document.createElement('INPUT'); + this.frame.prev.type = 'BUTTON'; + this.frame.prev.value = 'Prev'; + this.frame.appendChild(this.frame.prev); - if (this.colValue !== undefined) { - var valueRange = this.getColumnRange(data,this.colValue); - this.valueMin = (this.defaultValueMin !== undefined) ? this.defaultValueMin : valueRange.min; - this.valueMax = (this.defaultValueMax !== undefined) ? this.defaultValueMax : valueRange.max; - if (this.valueMax <= this.valueMin) this.valueMax = this.valueMin + 1; + this.frame.play = document.createElement('INPUT'); + this.frame.play.type = 'BUTTON'; + this.frame.play.value = 'Play'; + this.frame.appendChild(this.frame.play); + + this.frame.next = document.createElement('INPUT'); + this.frame.next.type = 'BUTTON'; + this.frame.next.value = 'Next'; + this.frame.appendChild(this.frame.next); + + this.frame.bar = document.createElement('INPUT'); + this.frame.bar.type = 'BUTTON'; + this.frame.bar.style.position = 'absolute'; + this.frame.bar.style.border = '1px solid red'; + this.frame.bar.style.width = '100px'; + this.frame.bar.style.height = '6px'; + this.frame.bar.style.borderRadius = '2px'; + this.frame.bar.style.MozBorderRadius = '2px'; + this.frame.bar.style.border = '1px solid #7F7F7F'; + this.frame.bar.style.backgroundColor = '#E5E5E5'; + this.frame.appendChild(this.frame.bar); + + this.frame.slide = document.createElement('INPUT'); + this.frame.slide.type = 'BUTTON'; + this.frame.slide.style.margin = '0px'; + this.frame.slide.value = ' '; + this.frame.slide.style.position = 'relative'; + this.frame.slide.style.left = '-100px'; + this.frame.appendChild(this.frame.slide); + + // create events + var me = this; + this.frame.slide.onmousedown = function (event) {me._onMouseDown(event);}; + this.frame.prev.onclick = function (event) {me.prev(event);}; + this.frame.play.onclick = function (event) {me.togglePlay(event);}; + this.frame.next.onclick = function (event) {me.next(event);}; } - // set the scale dependent on the ranges. - this._setScale(); - }; + this.onChangeCallback = undefined; + this.values = []; + this.index = undefined; + this.playTimeout = undefined; + this.playInterval = 1000; // milliseconds + this.playLoop = true; + } /** - * Filter the data based on the current filter - * @param {Array} data - * @return {Array} dataPoints Array with point objects which can be drawn on screen + * Select the previous index */ - Graph3d.prototype._getDataPoints = function (data) { - // TODO: store the created matrix dataPoints in the filters instead of reloading each time - var x, y, i, z, obj, point; + Slider.prototype.prev = function() { + var index = this.getIndex(); + if (index > 0) { + index--; + this.setIndex(index); + } + }; - var dataPoints = []; + /** + * Select the next index + */ + Slider.prototype.next = function() { + var index = this.getIndex(); + if (index < this.values.length - 1) { + index++; + this.setIndex(index); + } + }; - if (this.style === Graph3d.STYLE.GRID || - this.style === Graph3d.STYLE.SURFACE) { - // copy all values from the google data table to a matrix - // the provided values are supposed to form a grid of (x,y) positions - - // create two lists with all present x and y values - var dataX = []; - var dataY = []; - for (i = 0; i < this.getNumberOfRows(data); i++) { - x = data[i][this.colX] || 0; - y = data[i][this.colY] || 0; - - if (dataX.indexOf(x) === -1) { - dataX.push(x); - } - if (dataY.indexOf(y) === -1) { - dataY.push(y); - } - } - - function sortNumber(a, b) { - return a - b; - } - dataX.sort(sortNumber); - dataY.sort(sortNumber); - - // create a grid, a 2d matrix, with all values. - var dataMatrix = []; // temporary data matrix - for (i = 0; i < data.length; i++) { - x = data[i][this.colX] || 0; - y = data[i][this.colY] || 0; - z = data[i][this.colZ] || 0; - - var xIndex = dataX.indexOf(x); // TODO: implement Array().indexOf() for Internet Explorer - var yIndex = dataY.indexOf(y); - - if (dataMatrix[xIndex] === undefined) { - dataMatrix[xIndex] = []; - } + /** + * Select the next index + */ + Slider.prototype.playNext = function() { + var start = new Date(); - var point3d = new Point3d(); - point3d.x = x; - point3d.y = y; - point3d.z = z; + var index = this.getIndex(); + if (index < this.values.length - 1) { + index++; + this.setIndex(index); + } + else if (this.playLoop) { + // jump to the start + index = 0; + this.setIndex(index); + } - obj = {}; - obj.point = point3d; - obj.trans = undefined; - obj.screen = undefined; - obj.bottom = new Point3d(x, y, this.zMin); + var end = new Date(); + var diff = (end - start); - dataMatrix[xIndex][yIndex] = obj; + // calculate how much time it to to set the index and to execute the callback + // function. + var interval = Math.max(this.playInterval - diff, 0); + // document.title = diff // TODO: cleanup - dataPoints.push(obj); - } + var me = this; + this.playTimeout = setTimeout(function() {me.playNext();}, interval); + }; - // fill in the pointers to the neighbors. - for (x = 0; x < dataMatrix.length; x++) { - for (y = 0; y < dataMatrix[x].length; y++) { - if (dataMatrix[x][y]) { - dataMatrix[x][y].pointRight = (x < dataMatrix.length-1) ? dataMatrix[x+1][y] : undefined; - dataMatrix[x][y].pointTop = (y < dataMatrix[x].length-1) ? dataMatrix[x][y+1] : undefined; - dataMatrix[x][y].pointCross = - (x < dataMatrix.length-1 && y < dataMatrix[x].length-1) ? - dataMatrix[x+1][y+1] : - undefined; - } - } - } + /** + * Toggle start or stop playing + */ + Slider.prototype.togglePlay = function() { + if (this.playTimeout === undefined) { + this.play(); + } else { + this.stop(); } - else { // 'dot', 'dot-line', etc. - // copy all values from the google data table to a list with Point3d objects - for (i = 0; i < data.length; i++) { - point = new Point3d(); - point.x = data[i][this.colX] || 0; - point.y = data[i][this.colY] || 0; - point.z = data[i][this.colZ] || 0; + }; - if (this.colValue !== undefined) { - point.value = data[i][this.colValue] || 0; - } + /** + * Start playing + */ + Slider.prototype.play = function() { + // Test whether already playing + if (this.playTimeout) return; - obj = {}; - obj.point = point; - obj.bottom = new Point3d(point.x, point.y, this.zMin); - obj.trans = undefined; - obj.screen = undefined; + this.playNext(); - dataPoints.push(obj); - } + if (this.frame) { + this.frame.play.value = 'Stop'; } - - return dataPoints; }; /** - * Create the main frame for the Graph3d. - * This function is executed once when a Graph3d object is created. The frame - * contains a canvas, and this canvas contains all objects like the axis and - * nodes. + * Stop playing */ - Graph3d.prototype.create = function () { - // remove all elements from the container element. - while (this.containerElement.hasChildNodes()) { - this.containerElement.removeChild(this.containerElement.firstChild); - } - - this.frame = document.createElement('div'); - this.frame.style.position = 'relative'; - this.frame.style.overflow = 'hidden'; + Slider.prototype.stop = function() { + clearInterval(this.playTimeout); + this.playTimeout = undefined; - // create the graph canvas (HTML canvas element) - this.frame.canvas = document.createElement( 'canvas' ); - this.frame.canvas.style.position = 'relative'; - this.frame.appendChild(this.frame.canvas); - //if (!this.frame.canvas.getContext) { - { - var noCanvas = document.createElement( 'DIV' ); - noCanvas.style.color = 'red'; - noCanvas.style.fontWeight = 'bold' ; - noCanvas.style.padding = '10px'; - noCanvas.innerHTML = 'Error: your browser does not support HTML canvas'; - this.frame.canvas.appendChild(noCanvas); + if (this.frame) { + this.frame.play.value = 'Play'; } - - this.frame.filter = document.createElement( 'div' ); - this.frame.filter.style.position = 'absolute'; - this.frame.filter.style.bottom = '0px'; - this.frame.filter.style.left = '0px'; - this.frame.filter.style.width = '100%'; - this.frame.appendChild(this.frame.filter); - - // add event listeners to handle moving and zooming the contents - var me = this; - var onmousedown = function (event) {me._onMouseDown(event);}; - var ontouchstart = function (event) {me._onTouchStart(event);}; - var onmousewheel = function (event) {me._onWheel(event);}; - var ontooltip = function (event) {me._onTooltip(event);}; - // TODO: these events are never cleaned up... can give a 'memory leakage' - - util.addEventListener(this.frame.canvas, 'keydown', onkeydown); - util.addEventListener(this.frame.canvas, 'mousedown', onmousedown); - util.addEventListener(this.frame.canvas, 'touchstart', ontouchstart); - util.addEventListener(this.frame.canvas, 'mousewheel', onmousewheel); - util.addEventListener(this.frame.canvas, 'mousemove', ontooltip); - - // add the new graph to the container element - this.containerElement.appendChild(this.frame); }; - /** - * Set a new size for the graph - * @param {string} width Width in pixels or percentage (for example '800px' - * or '50%') - * @param {string} height Height in pixels or percentage (for example '400px' - * or '30%') + * Set a callback function which will be triggered when the value of the + * slider bar has changed. */ - Graph3d.prototype.setSize = function(width, height) { - this.frame.style.width = width; - this.frame.style.height = height; - - this._resizeCanvas(); + Slider.prototype.setOnChangeCallback = function(callback) { + this.onChangeCallback = callback; }; /** - * Resize the canvas to the current size of the frame + * Set the interval for playing the list + * @param {Number} interval The interval in milliseconds */ - Graph3d.prototype._resizeCanvas = function() { - this.frame.canvas.style.width = '100%'; - this.frame.canvas.style.height = '100%'; - - this.frame.canvas.width = this.frame.canvas.clientWidth; - this.frame.canvas.height = this.frame.canvas.clientHeight; - - // adjust with for margin - this.frame.filter.style.width = (this.frame.canvas.clientWidth - 2 * 10) + 'px'; + Slider.prototype.setPlayInterval = function(interval) { + this.playInterval = interval; }; /** - * Start animation + * Retrieve the current play interval + * @return {Number} interval The interval in milliseconds */ - Graph3d.prototype.animationStart = function() { - if (!this.frame.filter || !this.frame.filter.slider) - throw 'No animation available'; - - this.frame.filter.slider.play(); + Slider.prototype.getPlayInterval = function(interval) { + return this.playInterval; }; - /** - * Stop animation + * Set looping on or off + * @pararm {boolean} doLoop If true, the slider will jump to the start when + * the end is passed, and will jump to the end + * when the start is passed. */ - Graph3d.prototype.animationStop = function() { - if (!this.frame.filter || !this.frame.filter.slider) return; - - this.frame.filter.slider.stop(); + Slider.prototype.setPlayLoop = function(doLoop) { + this.playLoop = doLoop; }; /** - * Resize the center position based on the current values in this.defaultXCenter - * and this.defaultYCenter (which are strings with a percentage or a value - * in pixels). The center positions are the variables this.xCenter - * and this.yCenter + * Execute the onchange callback function */ - Graph3d.prototype._resizeCenter = function() { - // calculate the horizontal center position - if (this.defaultXCenter.charAt(this.defaultXCenter.length-1) === '%') { - this.xcenter = - parseFloat(this.defaultXCenter) / 100 * - this.frame.canvas.clientWidth; - } - else { - this.xcenter = parseFloat(this.defaultXCenter); // supposed to be in px - } - - // calculate the vertical center position - if (this.defaultYCenter.charAt(this.defaultYCenter.length-1) === '%') { - this.ycenter = - parseFloat(this.defaultYCenter) / 100 * - (this.frame.canvas.clientHeight - this.frame.filter.clientHeight); - } - else { - this.ycenter = parseFloat(this.defaultYCenter); // supposed to be in px + Slider.prototype.onChange = function() { + if (this.onChangeCallback !== undefined) { + this.onChangeCallback(); } }; /** - * Set the rotation and distance of the camera - * @param {Object} pos An object with the camera position. The object - * contains three parameters: - * - horizontal {Number} - * The horizontal rotation, between 0 and 2*PI. - * Optional, can be left undefined. - * - vertical {Number} - * The vertical rotation, between 0 and 0.5*PI - * if vertical=0.5*PI, the graph is shown from the - * top. Optional, can be left undefined. - * - distance {Number} - * The (normalized) distance of the camera to the - * center of the graph, a value between 0.71 and 5.0. - * Optional, can be left undefined. + * redraw the slider on the correct place */ - Graph3d.prototype.setCameraPosition = function(pos) { - if (pos === undefined) { - return; - } - - if (pos.horizontal !== undefined && pos.vertical !== undefined) { - this.camera.setArmRotation(pos.horizontal, pos.vertical); - } + Slider.prototype.redraw = function() { + if (this.frame) { + // resize the bar + this.frame.bar.style.top = (this.frame.clientHeight/2 - + this.frame.bar.offsetHeight/2) + 'px'; + this.frame.bar.style.width = (this.frame.clientWidth - + this.frame.prev.clientWidth - + this.frame.play.clientWidth - + this.frame.next.clientWidth - 30) + 'px'; - if (pos.distance !== undefined) { - this.camera.setArmLength(pos.distance); + // position the slider button + var left = this.indexToLeft(this.index); + this.frame.slide.style.left = (left) + 'px'; } - - this.redraw(); }; /** - * Retrieve the current camera rotation - * @return {object} An object with parameters horizontal, vertical, and - * distance + * Set the list with values for the slider + * @param {Array} values A javascript array with values (any type) */ - Graph3d.prototype.getCameraPosition = function() { - var pos = this.camera.getArmRotation(); - pos.distance = this.camera.getArmLength(); - return pos; + Slider.prototype.setValues = function(values) { + this.values = values; + + if (this.values.length > 0) + this.setIndex(0); + else + this.index = undefined; }; /** - * Load data into the 3D Graph + * Select a value by its index + * @param {Number} index */ - Graph3d.prototype._readData = function(data) { - // read the data - this._dataInitialize(data, this.style); - + Slider.prototype.setIndex = function(index) { + if (index < this.values.length) { + this.index = index; - if (this.dataFilter) { - // apply filtering - this.dataPoints = this.dataFilter._getDataPoints(); + this.redraw(); + this.onChange(); } else { - // no filtering. load all data - this.dataPoints = this._getDataPoints(this.dataTable); + throw 'Error: index out of range'; } - - // draw the filter - this._redrawFilter(); }; /** - * Replace the dataset of the Graph3d - * @param {Array | DataSet | DataView} data + * retrieve the index of the currently selected vaue + * @return {Number} index */ - Graph3d.prototype.setData = function (data) { - this._readData(data); - this.redraw(); - - // start animation when option is true - if (this.animationAutoStart && this.dataFilter) { - this.animationStart(); - } + Slider.prototype.getIndex = function() { + return this.index; }; + /** - * Update the options. Options will be merged with current options - * @param {Object} options + * retrieve the currently selected value + * @return {*} value */ - Graph3d.prototype.setOptions = function (options) { - var cameraPosition = undefined; + Slider.prototype.get = function() { + return this.values[this.index]; + }; - this.animationStop(); - if (options !== undefined) { - // retrieve parameter values - if (options.width !== undefined) this.width = options.width; - if (options.height !== undefined) this.height = options.height; + Slider.prototype._onMouseDown = function(event) { + // only react on left mouse button down + var leftButtonDown = event.which ? (event.which === 1) : (event.button === 1); + if (!leftButtonDown) return; - if (options.xCenter !== undefined) this.defaultXCenter = options.xCenter; - if (options.yCenter !== undefined) this.defaultYCenter = options.yCenter; + this.startClientX = event.clientX; + this.startSlideX = parseFloat(this.frame.slide.style.left); - if (options.filterLabel !== undefined) this.filterLabel = options.filterLabel; - if (options.legendLabel !== undefined) this.legendLabel = options.legendLabel; - if (options.xLabel !== undefined) this.xLabel = options.xLabel; - if (options.yLabel !== undefined) this.yLabel = options.yLabel; - if (options.zLabel !== undefined) this.zLabel = options.zLabel; + this.frame.style.cursor = 'move'; - if (options.style !== undefined) { - var styleNumber = this._getStyleNumber(options.style); - if (styleNumber !== -1) { - this.style = styleNumber; - } - } - if (options.showGrid !== undefined) this.showGrid = options.showGrid; - if (options.showPerspective !== undefined) this.showPerspective = options.showPerspective; - if (options.showShadow !== undefined) this.showShadow = options.showShadow; - if (options.tooltip !== undefined) this.showTooltip = options.tooltip; - if (options.showAnimationControls !== undefined) this.showAnimationControls = options.showAnimationControls; - if (options.keepAspectRatio !== undefined) this.keepAspectRatio = options.keepAspectRatio; - if (options.verticalRatio !== undefined) this.verticalRatio = options.verticalRatio; + // add event listeners to handle moving the contents + // we store the function onmousemove and onmouseup in the graph, so we can + // remove the eventlisteners lateron in the function mouseUp() + var me = this; + this.onmousemove = function (event) {me._onMouseMove(event);}; + this.onmouseup = function (event) {me._onMouseUp(event);}; + util.addEventListener(document, 'mousemove', this.onmousemove); + util.addEventListener(document, 'mouseup', this.onmouseup); + util.preventDefault(event); + }; - if (options.animationInterval !== undefined) this.animationInterval = options.animationInterval; - if (options.animationPreload !== undefined) this.animationPreload = options.animationPreload; - if (options.animationAutoStart !== undefined)this.animationAutoStart = options.animationAutoStart; - if (options.xBarWidth !== undefined) this.defaultXBarWidth = options.xBarWidth; - if (options.yBarWidth !== undefined) this.defaultYBarWidth = options.yBarWidth; + Slider.prototype.leftToIndex = function (left) { + var width = parseFloat(this.frame.bar.style.width) - + this.frame.slide.clientWidth - 10; + var x = left - 3; - if (options.xMin !== undefined) this.defaultXMin = options.xMin; - if (options.xStep !== undefined) this.defaultXStep = options.xStep; - if (options.xMax !== undefined) this.defaultXMax = options.xMax; - if (options.yMin !== undefined) this.defaultYMin = options.yMin; - if (options.yStep !== undefined) this.defaultYStep = options.yStep; - if (options.yMax !== undefined) this.defaultYMax = options.yMax; - if (options.zMin !== undefined) this.defaultZMin = options.zMin; - if (options.zStep !== undefined) this.defaultZStep = options.zStep; - if (options.zMax !== undefined) this.defaultZMax = options.zMax; - if (options.valueMin !== undefined) this.defaultValueMin = options.valueMin; - if (options.valueMax !== undefined) this.defaultValueMax = options.valueMax; + var index = Math.round(x / width * (this.values.length-1)); + if (index < 0) index = 0; + if (index > this.values.length-1) index = this.values.length-1; - if (options.cameraPosition !== undefined) cameraPosition = options.cameraPosition; + return index; + }; - if (cameraPosition !== undefined) { - this.camera.setArmRotation(cameraPosition.horizontal, cameraPosition.vertical); - this.camera.setArmLength(cameraPosition.distance); - } - else { - this.camera.setArmRotation(1.0, 0.5); - this.camera.setArmLength(1.7); - } - } + Slider.prototype.indexToLeft = function (index) { + var width = parseFloat(this.frame.bar.style.width) - + this.frame.slide.clientWidth - 10; - this._setBackgroundColor(options && options.backgroundColor); + var x = index / (this.values.length-1) * width; + var left = x + 3; - this.setSize(this.width, this.height); + return left; + }; - // re-load the data - if (this.dataTable) { - this.setData(this.dataTable); - } - // start animation when option is true - if (this.animationAutoStart && this.dataFilter) { - this.animationStart(); - } - }; - /** - * Redraw the Graph. - */ - Graph3d.prototype.redraw = function() { - if (this.dataPoints === undefined) { - throw 'Error: graph data not initialized'; - } + Slider.prototype._onMouseMove = function (event) { + var diff = event.clientX - this.startClientX; + var x = this.startSlideX + diff; - this._resizeCanvas(); - this._resizeCenter(); - this._redrawSlider(); - this._redrawClear(); - this._redrawAxis(); + var index = this.leftToIndex(x); - if (this.style === Graph3d.STYLE.GRID || - this.style === Graph3d.STYLE.SURFACE) { - this._redrawDataGrid(); - } - else if (this.style === Graph3d.STYLE.LINE) { - this._redrawDataLine(); - } - else if (this.style === Graph3d.STYLE.BAR || - this.style === Graph3d.STYLE.BARCOLOR || - this.style === Graph3d.STYLE.BARSIZE) { - this._redrawDataBar(); - } - else { - // style is DOT, DOTLINE, DOTCOLOR, DOTSIZE - this._redrawDataDot(); - } + this.setIndex(index); - this._redrawInfo(); - this._redrawLegend(); + util.preventDefault(); }; - /** - * Clear the canvas before redrawing - */ - Graph3d.prototype._redrawClear = function() { - var canvas = this.frame.canvas; - var ctx = canvas.getContext('2d'); - ctx.clearRect(0, 0, canvas.width, canvas.height); - }; + Slider.prototype._onMouseUp = function (event) { + this.frame.style.cursor = 'auto'; + // remove event listeners + util.removeEventListener(document, 'mousemove', this.onmousemove); + util.removeEventListener(document, 'mouseup', this.onmouseup); - /** - * Redraw the legend showing the colors - */ - Graph3d.prototype._redrawLegend = function() { - var y; + util.preventDefault(); + }; - if (this.style === Graph3d.STYLE.DOTCOLOR || - this.style === Graph3d.STYLE.DOTSIZE) { + module.exports = Slider; - var dotSize = this.frame.clientWidth * 0.02; - var widthMin, widthMax; - if (this.style === Graph3d.STYLE.DOTSIZE) { - widthMin = dotSize / 2; // px - widthMax = dotSize / 2 + dotSize * 2; // Todo: put this in one function - } - else { - widthMin = 20; // px - widthMax = 20; // px - } - - var height = Math.max(this.frame.clientHeight * 0.25, 100); - var top = this.margin; - var right = this.frame.clientWidth - this.margin; - var left = right - widthMax; - var bottom = top + height; - } - - var canvas = this.frame.canvas; - var ctx = canvas.getContext('2d'); - ctx.lineWidth = 1; - ctx.font = '14px arial'; // TODO: put in options - - if (this.style === Graph3d.STYLE.DOTCOLOR) { - // draw the color bar - var ymin = 0; - var ymax = height; // Todo: make height customizable - for (y = ymin; y < ymax; y++) { - var f = (y - ymin) / (ymax - ymin); - - //var width = (dotSize / 2 + (1-f) * dotSize * 2); // Todo: put this in one function - var hue = f * 240; - var color = this._hsv2rgb(hue, 1, 1); - - ctx.strokeStyle = color; - ctx.beginPath(); - ctx.moveTo(left, top + y); - ctx.lineTo(right, top + y); - ctx.stroke(); - } +/***/ }, +/* 11 */ +/***/ function(module, exports, __webpack_require__) { - ctx.strokeStyle = this.colorAxis; - ctx.strokeRect(left, top, widthMax, height); - } + /** + * @prototype StepNumber + * The class StepNumber is an iterator for Numbers. You provide a start and end + * value, and a best step size. StepNumber itself rounds to fixed values and + * a finds the step that best fits the provided step. + * + * If prettyStep is true, the step size is chosen as close as possible to the + * provided step, but being a round value like 1, 2, 5, 10, 20, 50, .... + * + * Example usage: + * var step = new StepNumber(0, 10, 2.5, true); + * step.start(); + * while (!step.end()) { + * alert(step.getCurrent()); + * step.next(); + * } + * + * Version: 1.0 + * + * @param {Number} start The start value + * @param {Number} end The end value + * @param {Number} step Optional. Step size. Must be a positive value. + * @param {boolean} prettyStep Optional. If true, the step size is rounded + * To a pretty step size (like 1, 2, 5, 10, 20, 50, ...) + */ + function StepNumber(start, end, step, prettyStep) { + // set default values + this._start = 0; + this._end = 0; + this._step = 1; + this.prettyStep = true; + this.precision = 5; - if (this.style === Graph3d.STYLE.DOTSIZE) { - // draw border around color bar - ctx.strokeStyle = this.colorAxis; - ctx.fillStyle = this.colorDot; - ctx.beginPath(); - ctx.moveTo(left, top); - ctx.lineTo(right, top); - ctx.lineTo(right - widthMax + widthMin, bottom); - ctx.lineTo(left, bottom); - ctx.closePath(); - ctx.fill(); - ctx.stroke(); - } + this._current = 0; + this.setRange(start, end, step, prettyStep); + }; - if (this.style === Graph3d.STYLE.DOTCOLOR || - this.style === Graph3d.STYLE.DOTSIZE) { - // print values along the color bar - var gridLineLen = 5; // px - var step = new StepNumber(this.valueMin, this.valueMax, (this.valueMax-this.valueMin)/5, true); - step.start(); - if (step.getCurrent() < this.valueMin) { - step.next(); - } - while (!step.end()) { - y = bottom - (step.getCurrent() - this.valueMin) / (this.valueMax - this.valueMin) * height; + /** + * Set a new range: start, end and step. + * + * @param {Number} start The start value + * @param {Number} end The end value + * @param {Number} step Optional. Step size. Must be a positive value. + * @param {boolean} prettyStep Optional. If true, the step size is rounded + * To a pretty step size (like 1, 2, 5, 10, 20, 50, ...) + */ + StepNumber.prototype.setRange = function(start, end, step, prettyStep) { + this._start = start ? start : 0; + this._end = end ? end : 0; - ctx.beginPath(); - ctx.moveTo(left - gridLineLen, y); - ctx.lineTo(left, y); - ctx.stroke(); + this.setStep(step, prettyStep); + }; - ctx.textAlign = 'right'; - ctx.textBaseline = 'middle'; - ctx.fillStyle = this.colorAxis; - ctx.fillText(step.getCurrent(), left - 2 * gridLineLen, y); + /** + * Set a new step size + * @param {Number} step New step size. Must be a positive value + * @param {boolean} prettyStep Optional. If true, the provided step is rounded + * to a pretty step size (like 1, 2, 5, 10, 20, 50, ...) + */ + StepNumber.prototype.setStep = function(step, prettyStep) { + if (step === undefined || step <= 0) + return; - step.next(); - } + if (prettyStep !== undefined) + this.prettyStep = prettyStep; - ctx.textAlign = 'right'; - ctx.textBaseline = 'top'; - var label = this.legendLabel; - ctx.fillText(label, right, bottom + this.margin); - } + if (this.prettyStep === true) + this._step = StepNumber.calculatePrettyStep(step); + else + this._step = step; }; /** - * Redraw the filter + * Calculate a nice step size, closest to the desired step size. + * Returns a value in one of the ranges 1*10^n, 2*10^n, or 5*10^n, where n is an + * integer Number. For example 1, 2, 5, 10, 20, 50, etc... + * @param {Number} step Desired step size + * @return {Number} Nice step size */ - Graph3d.prototype._redrawFilter = function() { - this.frame.filter.innerHTML = ''; + StepNumber.calculatePrettyStep = function (step) { + var log10 = function (x) {return Math.log(x) / Math.LN10;}; - if (this.dataFilter) { - var options = { - 'visible': this.showAnimationControls - }; - var slider = new Slider(this.frame.filter, options); - this.frame.filter.slider = slider; + // try three steps (multiple of 1, 2, or 5 + var step1 = Math.pow(10, Math.round(log10(step))), + step2 = 2 * Math.pow(10, Math.round(log10(step / 2))), + step5 = 5 * Math.pow(10, Math.round(log10(step / 5))); - // TODO: css here is not nice here... - this.frame.filter.style.padding = '10px'; - //this.frame.filter.style.backgroundColor = '#EFEFEF'; + // choose the best step (closest to minimum step) + var prettyStep = step1; + if (Math.abs(step2 - step) <= Math.abs(prettyStep - step)) prettyStep = step2; + if (Math.abs(step5 - step) <= Math.abs(prettyStep - step)) prettyStep = step5; - slider.setValues(this.dataFilter.values); - slider.setPlayInterval(this.animationInterval); + // for safety + if (prettyStep <= 0) { + prettyStep = 1; + } - // create an event handler - var me = this; - var onchange = function () { - var index = slider.getIndex(); + return prettyStep; + }; - me.dataFilter.selectValue(index); - me.dataPoints = me.dataFilter._getDataPoints(); + /** + * returns the current value of the step + * @return {Number} current value + */ + StepNumber.prototype.getCurrent = function () { + return parseFloat(this._current.toPrecision(this.precision)); + }; - me.redraw(); - }; - slider.setOnChangeCallback(onchange); - } - else { - this.frame.filter.slider = undefined; - } + /** + * returns the current step size + * @return {Number} current step size + */ + StepNumber.prototype.getStep = function () { + return this._step; }; /** - * Redraw the slider + * Set the current value to the largest value smaller than start, which + * is a multiple of the step size */ - Graph3d.prototype._redrawSlider = function() { - if ( this.frame.filter.slider !== undefined) { - this.frame.filter.slider.redraw(); - } + StepNumber.prototype.start = function() { + this._current = this._start - this._start % this._step; }; + /** + * Do a step, add the step size to the current value + */ + StepNumber.prototype.next = function () { + this._current += this._step; + }; /** - * Redraw common information + * Returns true whether the end is reached + * @return {boolean} True if the current value has passed the end value. */ - Graph3d.prototype._redrawInfo = function() { - if (this.dataFilter) { - var canvas = this.frame.canvas; - var ctx = canvas.getContext('2d'); + StepNumber.prototype.end = function () { + return (this._current > this._end); + }; - ctx.font = '14px arial'; // TODO: put in options - ctx.lineStyle = 'gray'; - ctx.fillStyle = 'gray'; - ctx.textAlign = 'left'; - ctx.textBaseline = 'top'; + module.exports = StepNumber; - var x = this.margin; - var y = this.margin; - ctx.fillText(this.dataFilter.getLabel() + ': ' + this.dataFilter.getSelectedValue(), x, y); - } - }; +/***/ }, +/* 12 */ +/***/ function(module, exports, __webpack_require__) { + + var Emitter = __webpack_require__(46); + var Hammer = __webpack_require__(41); + var util = __webpack_require__(1); + var DataSet = __webpack_require__(3); + var DataView = __webpack_require__(4); + var Range = __webpack_require__(15); + var Core = __webpack_require__(42); + var TimeAxis = __webpack_require__(27); + var CurrentTime = __webpack_require__(19); + var CustomTime = __webpack_require__(20); + var ItemSet = __webpack_require__(24); /** - * Redraw the axis + * Create a timeline visualization + * @param {HTMLElement} container + * @param {vis.DataSet | Array | google.visualization.DataTable} [items] + * @param {Object} [options] See Timeline.setOptions for the available options. + * @constructor */ - Graph3d.prototype._redrawAxis = function() { - var canvas = this.frame.canvas, - ctx = canvas.getContext('2d'), - from, to, step, prettyStep, - text, xText, yText, zText, - offset, xOffset, yOffset, - xMin2d, xMax2d; + function Timeline (container, items, options) { + // mix the core properties in here + for (var coreProp in Core.prototype) { + if (Core.prototype.hasOwnProperty(coreProp) && !Timeline.prototype.hasOwnProperty(coreProp)) { + Timeline.prototype[coreProp] = Core.prototype[coreProp]; + } + } - // TODO: get the actual rendered style of the containerElement - //ctx.font = this.containerElement.style.font; - ctx.font = 24 / this.camera.getArmLength() + 'px arial'; + if (!(this instanceof Timeline)) { + throw new SyntaxError('Constructor must be called with the new operator'); + } - // calculate the length for the short grid lines - var gridLenX = 0.025 / this.scale.x; - var gridLenY = 0.025 / this.scale.y; - var textMargin = 5 / this.camera.getArmLength(); // px - var armAngle = this.camera.getArmRotation().horizontal; + var me = this; + this.defaultOptions = { + start: null, + end: null, - // draw x-grid lines - ctx.lineWidth = 1; - prettyStep = (this.defaultXStep === undefined); - step = new StepNumber(this.xMin, this.xMax, this.xStep, prettyStep); - step.start(); - if (step.getCurrent() < this.xMin) { - step.next(); - } - while (!step.end()) { - var x = step.getCurrent(); + autoResize: true, - if (this.showGrid) { - from = this._convert3Dto2D(new Point3d(x, this.yMin, this.zMin)); - to = this._convert3Dto2D(new Point3d(x, this.yMax, this.zMin)); - ctx.strokeStyle = this.colorGrid; - ctx.beginPath(); - ctx.moveTo(from.x, from.y); - ctx.lineTo(to.x, to.y); - ctx.stroke(); - } - else { - from = this._convert3Dto2D(new Point3d(x, this.yMin, this.zMin)); - to = this._convert3Dto2D(new Point3d(x, this.yMin+gridLenX, this.zMin)); - ctx.strokeStyle = this.colorAxis; - ctx.beginPath(); - ctx.moveTo(from.x, from.y); - ctx.lineTo(to.x, to.y); - ctx.stroke(); + orientation: 'bottom', + width: null, + height: null, + maxHeight: null, + minHeight: null + }; + this.options = util.deepExtend({}, this.defaultOptions); - from = this._convert3Dto2D(new Point3d(x, this.yMax, this.zMin)); - to = this._convert3Dto2D(new Point3d(x, this.yMax-gridLenX, this.zMin)); - ctx.strokeStyle = this.colorAxis; - ctx.beginPath(); - ctx.moveTo(from.x, from.y); - ctx.lineTo(to.x, to.y); - ctx.stroke(); - } + // Create the DOM, props, and emitter + this._create(container); - yText = (Math.cos(armAngle) > 0) ? this.yMin : this.yMax; - text = this._convert3Dto2D(new Point3d(x, yText, this.zMin)); - if (Math.cos(armAngle * 2) > 0) { - ctx.textAlign = 'center'; - ctx.textBaseline = 'top'; - text.y += textMargin; - } - else if (Math.sin(armAngle * 2) < 0){ - ctx.textAlign = 'right'; - ctx.textBaseline = 'middle'; - } - else { - ctx.textAlign = 'left'; - ctx.textBaseline = 'middle'; + // all components listed here will be repainted automatically + this.components = []; + + this.body = { + dom: this.dom, + domProps: this.props, + emitter: { + on: this.on.bind(this), + off: this.off.bind(this), + emit: this.emit.bind(this) + }, + util: { + snap: null, // will be specified after TimeAxis is created + toScreen: me._toScreen.bind(me), + toGlobalScreen: me._toGlobalScreen.bind(me), // this refers to the root.width + toTime: me._toTime.bind(me), + toGlobalTime : me._toGlobalTime.bind(me) } - ctx.fillStyle = this.colorAxis; - ctx.fillText(' ' + step.getCurrent() + ' ', text.x, text.y); + }; - step.next(); - } + // range + this.range = new Range(this.body); + this.components.push(this.range); + this.body.range = this.range; - // draw y-grid lines - ctx.lineWidth = 1; - prettyStep = (this.defaultYStep === undefined); - step = new StepNumber(this.yMin, this.yMax, this.yStep, prettyStep); - step.start(); - if (step.getCurrent() < this.yMin) { - step.next(); - } - while (!step.end()) { - if (this.showGrid) { - from = this._convert3Dto2D(new Point3d(this.xMin, step.getCurrent(), this.zMin)); - to = this._convert3Dto2D(new Point3d(this.xMax, step.getCurrent(), this.zMin)); - ctx.strokeStyle = this.colorGrid; - ctx.beginPath(); - ctx.moveTo(from.x, from.y); - ctx.lineTo(to.x, to.y); - ctx.stroke(); - } - else { - from = this._convert3Dto2D(new Point3d(this.xMin, step.getCurrent(), this.zMin)); - to = this._convert3Dto2D(new Point3d(this.xMin+gridLenY, step.getCurrent(), this.zMin)); - ctx.strokeStyle = this.colorAxis; - ctx.beginPath(); - ctx.moveTo(from.x, from.y); - ctx.lineTo(to.x, to.y); - ctx.stroke(); + // time axis + this.timeAxis = new TimeAxis(this.body); + this.components.push(this.timeAxis); + this.body.util.snap = this.timeAxis.snap.bind(this.timeAxis); - from = this._convert3Dto2D(new Point3d(this.xMax, step.getCurrent(), this.zMin)); - to = this._convert3Dto2D(new Point3d(this.xMax-gridLenY, step.getCurrent(), this.zMin)); - ctx.strokeStyle = this.colorAxis; - ctx.beginPath(); - ctx.moveTo(from.x, from.y); - ctx.lineTo(to.x, to.y); - ctx.stroke(); - } + // current time bar + this.currentTime = new CurrentTime(this.body); + this.components.push(this.currentTime); - xText = (Math.sin(armAngle ) > 0) ? this.xMin : this.xMax; - text = this._convert3Dto2D(new Point3d(xText, step.getCurrent(), this.zMin)); - if (Math.cos(armAngle * 2) < 0) { - ctx.textAlign = 'center'; - ctx.textBaseline = 'top'; - text.y += textMargin; - } - else if (Math.sin(armAngle * 2) > 0){ - ctx.textAlign = 'right'; - ctx.textBaseline = 'middle'; - } - else { - ctx.textAlign = 'left'; - ctx.textBaseline = 'middle'; - } - ctx.fillStyle = this.colorAxis; - ctx.fillText(' ' + step.getCurrent() + ' ', text.x, text.y); + // custom time bar + // Note: time bar will be attached in this.setOptions when selected + this.customTime = new CustomTime(this.body); + this.components.push(this.customTime); - step.next(); + // item set + this.itemSet = new ItemSet(this.body); + this.components.push(this.itemSet); + + this.itemsData = null; // DataSet + this.groupsData = null; // DataSet + + // apply options + if (options) { + this.setOptions(options); } - // draw z-grid lines and axis - ctx.lineWidth = 1; - prettyStep = (this.defaultZStep === undefined); - step = new StepNumber(this.zMin, this.zMax, this.zStep, prettyStep); - step.start(); - if (step.getCurrent() < this.zMin) { - step.next(); + // create itemset + if (items) { + this.setItems(items); } - xText = (Math.cos(armAngle ) > 0) ? this.xMin : this.xMax; - yText = (Math.sin(armAngle ) < 0) ? this.yMin : this.yMax; - while (!step.end()) { - // TODO: make z-grid lines really 3d? - from = this._convert3Dto2D(new Point3d(xText, yText, step.getCurrent())); - ctx.strokeStyle = this.colorAxis; - ctx.beginPath(); - ctx.moveTo(from.x, from.y); - ctx.lineTo(from.x - textMargin, from.y); - ctx.stroke(); + else { + this.redraw(); + } + } - ctx.textAlign = 'right'; - ctx.textBaseline = 'middle'; - ctx.fillStyle = this.colorAxis; - ctx.fillText(step.getCurrent() + ' ', from.x - 5, from.y); + /** + * Set options. Options will be passed to all components loaded in the Timeline. + * @param {Object} [options] + * {String} orientation + * Vertical orientation for the Timeline, + * can be 'bottom' (default) or 'top'. + * {String | Number} width + * Width for the timeline, a number in pixels or + * a css string like '1000px' or '75%'. '100%' by default. + * {String | Number} height + * Fixed height for the Timeline, a number in pixels or + * a css string like '400px' or '75%'. If undefined, + * The Timeline will automatically size such that + * its contents fit. + * {String | Number} minHeight + * Minimum height for the Timeline, a number in pixels or + * a css string like '400px' or '75%'. + * {String | Number} maxHeight + * Maximum height for the Timeline, a number in pixels or + * a css string like '400px' or '75%'. + * {Number | Date | String} start + * Start date for the visible window + * {Number | Date | String} end + * End date for the visible window + */ + Timeline.prototype.setOptions = function (options) { + if (options) { + // copy the known options + var fields = ['width', 'height', 'minHeight', 'maxHeight', 'autoResize', 'start', 'end', 'orientation']; + util.selectiveExtend(fields, this.options, options); - step.next(); + // enable/disable autoResize + this._initAutoResize(); } - ctx.lineWidth = 1; - from = this._convert3Dto2D(new Point3d(xText, yText, this.zMin)); - to = this._convert3Dto2D(new Point3d(xText, yText, this.zMax)); - ctx.strokeStyle = this.colorAxis; - ctx.beginPath(); - ctx.moveTo(from.x, from.y); - ctx.lineTo(to.x, to.y); - ctx.stroke(); - // draw x-axis - ctx.lineWidth = 1; - // line at yMin - xMin2d = this._convert3Dto2D(new Point3d(this.xMin, this.yMin, this.zMin)); - xMax2d = this._convert3Dto2D(new Point3d(this.xMax, this.yMin, this.zMin)); - ctx.strokeStyle = this.colorAxis; - ctx.beginPath(); - ctx.moveTo(xMin2d.x, xMin2d.y); - ctx.lineTo(xMax2d.x, xMax2d.y); - ctx.stroke(); - // line at ymax - xMin2d = this._convert3Dto2D(new Point3d(this.xMin, this.yMax, this.zMin)); - xMax2d = this._convert3Dto2D(new Point3d(this.xMax, this.yMax, this.zMin)); - ctx.strokeStyle = this.colorAxis; - ctx.beginPath(); - ctx.moveTo(xMin2d.x, xMin2d.y); - ctx.lineTo(xMax2d.x, xMax2d.y); - ctx.stroke(); - - // draw y-axis - ctx.lineWidth = 1; - // line at xMin - from = this._convert3Dto2D(new Point3d(this.xMin, this.yMin, this.zMin)); - to = this._convert3Dto2D(new Point3d(this.xMin, this.yMax, this.zMin)); - ctx.strokeStyle = this.colorAxis; - ctx.beginPath(); - ctx.moveTo(from.x, from.y); - ctx.lineTo(to.x, to.y); - ctx.stroke(); - // line at xMax - from = this._convert3Dto2D(new Point3d(this.xMax, this.yMin, this.zMin)); - to = this._convert3Dto2D(new Point3d(this.xMax, this.yMax, this.zMin)); - ctx.strokeStyle = this.colorAxis; - ctx.beginPath(); - ctx.moveTo(from.x, from.y); - ctx.lineTo(to.x, to.y); - ctx.stroke(); - - // draw x-label - var xLabel = this.xLabel; - if (xLabel.length > 0) { - yOffset = 0.1 / this.scale.y; - xText = (this.xMin + this.xMax) / 2; - yText = (Math.cos(armAngle) > 0) ? this.yMin - yOffset: this.yMax + yOffset; - text = this._convert3Dto2D(new Point3d(xText, yText, this.zMin)); - if (Math.cos(armAngle * 2) > 0) { - ctx.textAlign = 'center'; - ctx.textBaseline = 'top'; - } - else if (Math.sin(armAngle * 2) < 0){ - ctx.textAlign = 'right'; - ctx.textBaseline = 'middle'; - } - else { - ctx.textAlign = 'left'; - ctx.textBaseline = 'middle'; - } - ctx.fillStyle = this.colorAxis; - ctx.fillText(xLabel, text.x, text.y); - } + // propagate options to all components + this.components.forEach(function (component) { + component.setOptions(options); + }); - // draw y-label - var yLabel = this.yLabel; - if (yLabel.length > 0) { - xOffset = 0.1 / this.scale.x; - xText = (Math.sin(armAngle ) > 0) ? this.xMin - xOffset : this.xMax + xOffset; - yText = (this.yMin + this.yMax) / 2; - text = this._convert3Dto2D(new Point3d(xText, yText, this.zMin)); - if (Math.cos(armAngle * 2) < 0) { - ctx.textAlign = 'center'; - ctx.textBaseline = 'top'; - } - else if (Math.sin(armAngle * 2) > 0){ - ctx.textAlign = 'right'; - ctx.textBaseline = 'middle'; - } - else { - ctx.textAlign = 'left'; - ctx.textBaseline = 'middle'; - } - ctx.fillStyle = this.colorAxis; - ctx.fillText(yLabel, text.x, text.y); + // TODO: remove deprecation error one day (deprecated since version 0.8.0) + if (options && options.order) { + throw new Error('Option order is deprecated. There is no replacement for this feature.'); } - // draw z-label - var zLabel = this.zLabel; - if (zLabel.length > 0) { - offset = 30; // pixels. // TODO: relate to the max width of the values on the z axis? - xText = (Math.cos(armAngle ) > 0) ? this.xMin : this.xMax; - yText = (Math.sin(armAngle ) < 0) ? this.yMin : this.yMax; - zText = (this.zMin + this.zMax) / 2; - text = this._convert3Dto2D(new Point3d(xText, yText, zText)); - ctx.textAlign = 'right'; - ctx.textBaseline = 'middle'; - ctx.fillStyle = this.colorAxis; - ctx.fillText(zLabel, text.x - offset, text.y); - } + // redraw everything + this.redraw(); }; /** - * Calculate the color based on the given value. - * @param {Number} H Hue, a value be between 0 and 360 - * @param {Number} S Saturation, a value between 0 and 1 - * @param {Number} V Value, a value between 0 and 1 + * Set items + * @param {vis.DataSet | Array | google.visualization.DataTable | null} items */ - Graph3d.prototype._hsv2rgb = function(H, S, V) { - var R, G, B, C, Hi, X; + Timeline.prototype.setItems = function(items) { + var initialLoad = (this.itemsData == null); - C = V * S; - Hi = Math.floor(H/60); // hi = 0,1,2,3,4,5 - X = C * (1 - Math.abs(((H/60) % 2) - 1)); + // convert to type DataSet when needed + var newDataSet; + if (!items) { + newDataSet = null; + } + else if (items instanceof DataSet || items instanceof DataView) { + newDataSet = items; + } + else { + // turn an array into a dataset + newDataSet = new DataSet(items, { + type: { + start: 'Date', + end: 'Date' + } + }); + } - switch (Hi) { - case 0: R = C; G = X; B = 0; break; - case 1: R = X; G = C; B = 0; break; - case 2: R = 0; G = C; B = X; break; - case 3: R = 0; G = X; B = C; break; - case 4: R = X; G = 0; B = C; break; - case 5: R = C; G = 0; B = X; break; + // set items + this.itemsData = newDataSet; + this.itemSet && this.itemSet.setItems(newDataSet); - default: R = 0; G = 0; B = 0; break; - } + if (initialLoad && ('start' in this.options || 'end' in this.options)) { + this.fit(); - return 'RGB(' + parseInt(R*255) + ',' + parseInt(G*255) + ',' + parseInt(B*255) + ')'; + var start = ('start' in this.options) ? util.convert(this.options.start, 'Date') : null; + var end = ('end' in this.options) ? util.convert(this.options.end, 'Date') : null; + + this.setWindow(start, end); + } }; + /** + * Set groups + * @param {vis.DataSet | Array | google.visualization.DataTable} groups + */ + Timeline.prototype.setGroups = function(groups) { + // convert to type DataSet when needed + var newDataSet; + if (!groups) { + newDataSet = null; + } + else if (groups instanceof DataSet || groups instanceof DataView) { + newDataSet = groups; + } + else { + // turn an array into a dataset + newDataSet = new DataSet(groups); + } + + this.groupsData = newDataSet; + this.itemSet.setGroups(newDataSet); + }; /** - * Draw all datapoints as a grid - * This function can be used when the style is 'grid' + * Set selected items by their id. Replaces the current selection + * Unknown id's are silently ignored. + * @param {Array} [ids] An array with zero or more id's of the items to be + * selected. If ids is an empty array, all items will be + * unselected. */ - Graph3d.prototype._redrawDataGrid = function() { - var canvas = this.frame.canvas, - ctx = canvas.getContext('2d'), - point, right, top, cross, - i, - topSideVisible, fillStyle, strokeStyle, lineWidth, - h, s, v, zAvg; + Timeline.prototype.setSelection = function(ids) { + this.itemSet && this.itemSet.setSelection(ids); + }; + /** + * Get the selected items by their id + * @return {Array} ids The ids of the selected items + */ + Timeline.prototype.getSelection = function() { + return this.itemSet && this.itemSet.getSelection() || []; + }; - if (this.dataPoints === undefined || this.dataPoints.length <= 0) - return; // TODO: throw exception? - // calculate the translations and screen position of all points - for (i = 0; i < this.dataPoints.length; i++) { - var trans = this._convertPointToTranslation(this.dataPoints[i].point); - var screen = this._convertTranslationToScreen(trans); + /** + * Get the data range of the item set. + * @returns {{min: Date, max: Date}} range A range with a start and end Date. + * When no minimum is found, min==null + * When no maximum is found, max==null + */ + Timeline.prototype.getItemRange = function() { + // calculate min from start filed + var dataset = this.itemsData.getDataSet(), + min = null, + max = null; - this.dataPoints[i].trans = trans; - this.dataPoints[i].screen = screen; + if (dataset) { + // calculate the minimum value of the field 'start' + var minItem = dataset.min('start'); + min = minItem ? util.convert(minItem.start, 'Date').valueOf() : null; + // Note: we convert first to Date and then to number because else + // a conversion from ISODate to Number will fail - // calculate the translation of the point at the bottom (needed for sorting) - var transBottom = this._convertPointToTranslation(this.dataPoints[i].bottom); - this.dataPoints[i].dist = this.showPerspective ? transBottom.length() : -transBottom.z; + // calculate maximum value of fields 'start' and 'end' + var maxStartItem = dataset.max('start'); + if (maxStartItem) { + max = util.convert(maxStartItem.start, 'Date').valueOf(); + } + var maxEndItem = dataset.max('end'); + if (maxEndItem) { + if (max == null) { + max = util.convert(maxEndItem.end, 'Date').valueOf(); + } + else { + max = Math.max(max, util.convert(maxEndItem.end, 'Date').valueOf()); + } + } } - // sort the points on depth of their (x,y) position (not on z) - var sortDepth = function (a, b) { - return b.dist - a.dist; + return { + min: (min != null) ? new Date(min) : null, + max: (max != null) ? new Date(max) : null }; - this.dataPoints.sort(sortDepth); + }; - if (this.style === Graph3d.STYLE.SURFACE) { - for (i = 0; i < this.dataPoints.length; i++) { - point = this.dataPoints[i]; - right = this.dataPoints[i].pointRight; - top = this.dataPoints[i].pointTop; - cross = this.dataPoints[i].pointCross; - if (point !== undefined && right !== undefined && top !== undefined && cross !== undefined) { + module.exports = Timeline; - if (this.showGrayBottom || this.showShadow) { - // calculate the cross product of the two vectors from center - // to left and right, in order to know whether we are looking at the - // bottom or at the top side. We can also use the cross product - // for calculating light intensity - var aDiff = Point3d.subtract(cross.trans, point.trans); - var bDiff = Point3d.subtract(top.trans, right.trans); - var crossproduct = Point3d.crossProduct(aDiff, bDiff); - var len = crossproduct.length(); - // FIXME: there is a bug with determining the surface side (shadow or colored) - - topSideVisible = (crossproduct.z > 0); - } - else { - topSideVisible = true; - } - if (topSideVisible) { - // calculate Hue from the current value. At zMin the hue is 240, at zMax the hue is 0 - zAvg = (point.point.z + right.point.z + top.point.z + cross.point.z) / 4; - h = (1 - (zAvg - this.zMin) * this.scale.z / this.verticalRatio) * 240; - s = 1; // saturation +/***/ }, +/* 13 */ +/***/ function(module, exports, __webpack_require__) { - if (this.showShadow) { - v = Math.min(1 + (crossproduct.x / len) / 2, 1); // value. TODO: scale - fillStyle = this._hsv2rgb(h, s, v); - strokeStyle = fillStyle; - } - else { - v = 1; - fillStyle = this._hsv2rgb(h, s, v); - strokeStyle = this.colorAxis; - } - } - else { - fillStyle = 'gray'; - strokeStyle = this.colorAxis; - } - lineWidth = 0.5; + var Emitter = __webpack_require__(46); + var Hammer = __webpack_require__(41); + var util = __webpack_require__(1); + var DataSet = __webpack_require__(3); + var DataView = __webpack_require__(4); + var Range = __webpack_require__(15); + var Core = __webpack_require__(42); + var TimeAxis = __webpack_require__(27); + var CurrentTime = __webpack_require__(19); + var CustomTime = __webpack_require__(20); + var LineGraph = __webpack_require__(26); - ctx.lineWidth = lineWidth; - ctx.fillStyle = fillStyle; - ctx.strokeStyle = strokeStyle; - ctx.beginPath(); - ctx.moveTo(point.screen.x, point.screen.y); - ctx.lineTo(right.screen.x, right.screen.y); - ctx.lineTo(cross.screen.x, cross.screen.y); - ctx.lineTo(top.screen.x, top.screen.y); - ctx.closePath(); - ctx.fill(); - ctx.stroke(); - } + /** + * Create a timeline visualization + * @param {HTMLElement} container + * @param {vis.DataSet | Array | google.visualization.DataTable} [items] + * @param {Object} [options] See Graph2d.setOptions for the available options. + * @constructor + */ + function Graph2d (container, items, options, groups) { + for (var coreProp in Core.prototype) { + if (Core.prototype.hasOwnProperty(coreProp) && !Graph2d.prototype.hasOwnProperty(coreProp)) { + Graph2d.prototype[coreProp] = Core.prototype[coreProp]; } } - else { // grid style - for (i = 0; i < this.dataPoints.length; i++) { - point = this.dataPoints[i]; - right = this.dataPoints[i].pointRight; - top = this.dataPoints[i].pointTop; - - if (point !== undefined) { - if (this.showPerspective) { - lineWidth = 2 / -point.trans.z; - } - else { - lineWidth = 2 * -(this.eye.z / this.camera.getArmLength()); - } - } - - if (point !== undefined && right !== undefined) { - // calculate Hue from the current value. At zMin the hue is 240, at zMax the hue is 0 - zAvg = (point.point.z + right.point.z) / 2; - h = (1 - (zAvg - this.zMin) * this.scale.z / this.verticalRatio) * 240; - ctx.lineWidth = lineWidth; - ctx.strokeStyle = this._hsv2rgb(h, 1, 1); - ctx.beginPath(); - ctx.moveTo(point.screen.x, point.screen.y); - ctx.lineTo(right.screen.x, right.screen.y); - ctx.stroke(); - } + var me = this; + this.defaultOptions = { + start: null, + end: null, - if (point !== undefined && top !== undefined) { - // calculate Hue from the current value. At zMin the hue is 240, at zMax the hue is 0 - zAvg = (point.point.z + top.point.z) / 2; - h = (1 - (zAvg - this.zMin) * this.scale.z / this.verticalRatio) * 240; + autoResize: true, - ctx.lineWidth = lineWidth; - ctx.strokeStyle = this._hsv2rgb(h, 1, 1); - ctx.beginPath(); - ctx.moveTo(point.screen.x, point.screen.y); - ctx.lineTo(top.screen.x, top.screen.y); - ctx.stroke(); - } - } - } - }; + orientation: 'bottom', + width: null, + height: null, + maxHeight: null, + minHeight: null + }; + this.options = util.deepExtend({}, this.defaultOptions); + // Create the DOM, props, and emitter + this._create(container); - /** - * Draw all datapoints as dots. - * This function can be used when the style is 'dot' or 'dot-line' - */ - Graph3d.prototype._redrawDataDot = function() { - var canvas = this.frame.canvas; - var ctx = canvas.getContext('2d'); - var i; + // all components listed here will be repainted automatically + this.components = []; - if (this.dataPoints === undefined || this.dataPoints.length <= 0) - return; // TODO: throw exception? + this.body = { + dom: this.dom, + domProps: this.props, + emitter: { + on: this.on.bind(this), + off: this.off.bind(this), + emit: this.emit.bind(this) + }, + util: { + snap: null, // will be specified after TimeAxis is created + toScreen: me._toScreen.bind(me), + toGlobalScreen: me._toGlobalScreen.bind(me), // this refers to the root.width + toTime: me._toTime.bind(me), + toGlobalTime : me._toGlobalTime.bind(me) + } + }; - // calculate the translations of all points - for (i = 0; i < this.dataPoints.length; i++) { - var trans = this._convertPointToTranslation(this.dataPoints[i].point); - var screen = this._convertTranslationToScreen(trans); - this.dataPoints[i].trans = trans; - this.dataPoints[i].screen = screen; + // range + this.range = new Range(this.body); + this.components.push(this.range); + this.body.range = this.range; - // calculate the distance from the point at the bottom to the camera - var transBottom = this._convertPointToTranslation(this.dataPoints[i].bottom); - this.dataPoints[i].dist = this.showPerspective ? transBottom.length() : -transBottom.z; - } + // time axis + this.timeAxis = new TimeAxis(this.body); + this.components.push(this.timeAxis); + this.body.util.snap = this.timeAxis.snap.bind(this.timeAxis); - // order the translated points by depth - var sortDepth = function (a, b) { - return b.dist - a.dist; - }; - this.dataPoints.sort(sortDepth); + // current time bar + this.currentTime = new CurrentTime(this.body); + this.components.push(this.currentTime); - // draw the datapoints as colored circles - var dotSize = this.frame.clientWidth * 0.02; // px - for (i = 0; i < this.dataPoints.length; i++) { - var point = this.dataPoints[i]; + // custom time bar + // Note: time bar will be attached in this.setOptions when selected + this.customTime = new CustomTime(this.body); + this.components.push(this.customTime); - if (this.style === Graph3d.STYLE.DOTLINE) { - // draw a vertical line from the bottom to the graph value - //var from = this._convert3Dto2D(new Point3d(point.point.x, point.point.y, this.zMin)); - var from = this._convert3Dto2D(point.bottom); - ctx.lineWidth = 1; - ctx.strokeStyle = this.colorGrid; - ctx.beginPath(); - ctx.moveTo(from.x, from.y); - ctx.lineTo(point.screen.x, point.screen.y); - ctx.stroke(); - } + // item set + this.linegraph = new LineGraph(this.body); + this.components.push(this.linegraph); - // calculate radius for the circle - var size; - if (this.style === Graph3d.STYLE.DOTSIZE) { - size = dotSize/2 + 2*dotSize * (point.point.value - this.valueMin) / (this.valueMax - this.valueMin); - } - else { - size = dotSize; - } + this.itemsData = null; // DataSet + this.groupsData = null; // DataSet - var radius; - if (this.showPerspective) { - radius = size / -point.trans.z; - } - else { - radius = size * -(this.eye.z / this.camera.getArmLength()); - } - if (radius < 0) { - radius = 0; - } + // apply options + if (options) { + this.setOptions(options); + } - var hue, color, borderColor; - if (this.style === Graph3d.STYLE.DOTCOLOR ) { - // calculate the color based on the value - hue = (1 - (point.point.value - this.valueMin) * this.scale.value) * 240; - color = this._hsv2rgb(hue, 1, 1); - borderColor = this._hsv2rgb(hue, 1, 0.8); - } - else if (this.style === Graph3d.STYLE.DOTSIZE) { - color = this.colorDot; - borderColor = this.colorDotBorder; - } - else { - // calculate Hue from the current value. At zMin the hue is 240, at zMax the hue is 0 - hue = (1 - (point.point.z - this.zMin) * this.scale.z / this.verticalRatio) * 240; - color = this._hsv2rgb(hue, 1, 1); - borderColor = this._hsv2rgb(hue, 1, 0.8); - } + // IMPORTANT: THIS HAPPENS BEFORE SET ITEMS! + if (groups) { + this.setGroups(groups); + } - // draw the circle - ctx.lineWidth = 1.0; - ctx.strokeStyle = borderColor; - ctx.fillStyle = color; - ctx.beginPath(); - ctx.arc(point.screen.x, point.screen.y, radius, 0, Math.PI*2, true); - ctx.fill(); - ctx.stroke(); + // create itemset + if (items) { + this.setItems(items); } - }; + else { + this.redraw(); + } + } /** - * Draw all datapoints as bars. - * This function can be used when the style is 'bar', 'bar-color', or 'bar-size' + * Set options. Options will be passed to all components loaded in the Graph2d. + * @param {Object} [options] + * {String} orientation + * Vertical orientation for the Graph2d, + * can be 'bottom' (default) or 'top'. + * {String | Number} width + * Width for the timeline, a number in pixels or + * a css string like '1000px' or '75%'. '100%' by default. + * {String | Number} height + * Fixed height for the Graph2d, a number in pixels or + * a css string like '400px' or '75%'. If undefined, + * The Graph2d will automatically size such that + * its contents fit. + * {String | Number} minHeight + * Minimum height for the Graph2d, a number in pixels or + * a css string like '400px' or '75%'. + * {String | Number} maxHeight + * Maximum height for the Graph2d, a number in pixels or + * a css string like '400px' or '75%'. + * {Number | Date | String} start + * Start date for the visible window + * {Number | Date | String} end + * End date for the visible window */ - Graph3d.prototype._redrawDataBar = function() { - var canvas = this.frame.canvas; - var ctx = canvas.getContext('2d'); - var i, j, surface, corners; - - if (this.dataPoints === undefined || this.dataPoints.length <= 0) - return; // TODO: throw exception? - - // calculate the translations of all points - for (i = 0; i < this.dataPoints.length; i++) { - var trans = this._convertPointToTranslation(this.dataPoints[i].point); - var screen = this._convertTranslationToScreen(trans); - this.dataPoints[i].trans = trans; - this.dataPoints[i].screen = screen; + Graph2d.prototype.setOptions = function (options) { + if (options) { + // copy the known options + var fields = ['width', 'height', 'minHeight', 'maxHeight', 'autoResize', 'start', 'end', 'orientation']; + util.selectiveExtend(fields, this.options, options); - // calculate the distance from the point at the bottom to the camera - var transBottom = this._convertPointToTranslation(this.dataPoints[i].bottom); - this.dataPoints[i].dist = this.showPerspective ? transBottom.length() : -transBottom.z; + // enable/disable autoResize + this._initAutoResize(); } - // order the translated points by depth - var sortDepth = function (a, b) { - return b.dist - a.dist; - }; - this.dataPoints.sort(sortDepth); + // propagate options to all components + this.components.forEach(function (component) { + component.setOptions(options); + }); - // draw the datapoints as bars - var xWidth = this.xBarWidth / 2; - var yWidth = this.yBarWidth / 2; - for (i = 0; i < this.dataPoints.length; i++) { - var point = this.dataPoints[i]; + // TODO: remove deprecation error one day (deprecated since version 0.8.0) + if (options && options.order) { + throw new Error('Option order is deprecated. There is no replacement for this feature.'); + } - // determine color - var hue, color, borderColor; - if (this.style === Graph3d.STYLE.BARCOLOR ) { - // calculate the color based on the value - hue = (1 - (point.point.value - this.valueMin) * this.scale.value) * 240; - color = this._hsv2rgb(hue, 1, 1); - borderColor = this._hsv2rgb(hue, 1, 0.8); - } - else if (this.style === Graph3d.STYLE.BARSIZE) { - color = this.colorDot; - borderColor = this.colorDotBorder; - } - else { - // calculate Hue from the current value. At zMin the hue is 240, at zMax the hue is 0 - hue = (1 - (point.point.z - this.zMin) * this.scale.z / this.verticalRatio) * 240; - color = this._hsv2rgb(hue, 1, 1); - borderColor = this._hsv2rgb(hue, 1, 0.8); - } + // redraw everything + this.redraw(); + }; - // calculate size for the bar - if (this.style === Graph3d.STYLE.BARSIZE) { - xWidth = (this.xBarWidth / 2) * ((point.point.value - this.valueMin) / (this.valueMax - this.valueMin) * 0.8 + 0.2); - yWidth = (this.yBarWidth / 2) * ((point.point.value - this.valueMin) / (this.valueMax - this.valueMin) * 0.8 + 0.2); - } - // calculate all corner points - var me = this; - var point3d = point.point; - var top = [ - {point: new Point3d(point3d.x - xWidth, point3d.y - yWidth, point3d.z)}, - {point: new Point3d(point3d.x + xWidth, point3d.y - yWidth, point3d.z)}, - {point: new Point3d(point3d.x + xWidth, point3d.y + yWidth, point3d.z)}, - {point: new Point3d(point3d.x - xWidth, point3d.y + yWidth, point3d.z)} - ]; - var bottom = [ - {point: new Point3d(point3d.x - xWidth, point3d.y - yWidth, this.zMin)}, - {point: new Point3d(point3d.x + xWidth, point3d.y - yWidth, this.zMin)}, - {point: new Point3d(point3d.x + xWidth, point3d.y + yWidth, this.zMin)}, - {point: new Point3d(point3d.x - xWidth, point3d.y + yWidth, this.zMin)} - ]; + /** + * Set items + * @param {vis.DataSet | Array | google.visualization.DataTable | null} items + */ + Graph2d.prototype.setItems = function(items) { + var initialLoad = (this.itemsData == null); - // calculate screen location of the points - top.forEach(function (obj) { - obj.screen = me._convert3Dto2D(obj.point); - }); - bottom.forEach(function (obj) { - obj.screen = me._convert3Dto2D(obj.point); + // convert to type DataSet when needed + var newDataSet; + if (!items) { + newDataSet = null; + } + else if (items instanceof DataSet || items instanceof DataView) { + newDataSet = items; + } + else { + // turn an array into a dataset + newDataSet = new DataSet(items, { + type: { + start: 'Date', + end: 'Date' + } }); + } - // create five sides, calculate both corner points and center points - var surfaces = [ - {corners: top, center: Point3d.avg(bottom[0].point, bottom[2].point)}, - {corners: [top[0], top[1], bottom[1], bottom[0]], center: Point3d.avg(bottom[1].point, bottom[0].point)}, - {corners: [top[1], top[2], bottom[2], bottom[1]], center: Point3d.avg(bottom[2].point, bottom[1].point)}, - {corners: [top[2], top[3], bottom[3], bottom[2]], center: Point3d.avg(bottom[3].point, bottom[2].point)}, - {corners: [top[3], top[0], bottom[0], bottom[3]], center: Point3d.avg(bottom[0].point, bottom[3].point)} - ]; - point.surfaces = surfaces; - - // calculate the distance of each of the surface centers to the camera - for (j = 0; j < surfaces.length; j++) { - surface = surfaces[j]; - var transCenter = this._convertPointToTranslation(surface.center); - surface.dist = this.showPerspective ? transCenter.length() : -transCenter.z; - // TODO: this dept calculation doesn't work 100% of the cases due to perspective, - // but the current solution is fast/simple and works in 99.9% of all cases - // the issue is visible in example 14, with graph.setCameraPosition({horizontal: 2.97, vertical: 0.5, distance: 0.9}) - } - - // order the surfaces by their (translated) depth - surfaces.sort(function (a, b) { - var diff = b.dist - a.dist; - if (diff) return diff; + // set items + this.itemsData = newDataSet; + this.linegraph && this.linegraph.setItems(newDataSet); - // if equal depth, sort the top surface last - if (a.corners === top) return 1; - if (b.corners === top) return -1; + if (initialLoad && ('start' in this.options || 'end' in this.options)) { + this.fit(); - // both are equal - return 0; - }); + var start = ('start' in this.options) ? util.convert(this.options.start, 'Date') : null; + var end = ('end' in this.options) ? util.convert(this.options.end, 'Date') : null; - // draw the ordered surfaces - ctx.lineWidth = 1; - ctx.strokeStyle = borderColor; - ctx.fillStyle = color; - // NOTE: we start at j=2 instead of j=0 as we don't need to draw the two surfaces at the backside - for (j = 2; j < surfaces.length; j++) { - surface = surfaces[j]; - corners = surface.corners; - ctx.beginPath(); - ctx.moveTo(corners[3].screen.x, corners[3].screen.y); - ctx.lineTo(corners[0].screen.x, corners[0].screen.y); - ctx.lineTo(corners[1].screen.x, corners[1].screen.y); - ctx.lineTo(corners[2].screen.x, corners[2].screen.y); - ctx.lineTo(corners[3].screen.x, corners[3].screen.y); - ctx.fill(); - ctx.stroke(); - } + this.setWindow(start, end); } }; - /** - * Draw a line through all datapoints. - * This function can be used when the style is 'line' + * Set groups + * @param {vis.DataSet | Array | google.visualization.DataTable} groups */ - Graph3d.prototype._redrawDataLine = function() { - var canvas = this.frame.canvas, - ctx = canvas.getContext('2d'), - point, i; - - if (this.dataPoints === undefined || this.dataPoints.length <= 0) - return; // TODO: throw exception? - - // calculate the translations of all points - for (i = 0; i < this.dataPoints.length; i++) { - var trans = this._convertPointToTranslation(this.dataPoints[i].point); - var screen = this._convertTranslationToScreen(trans); - - this.dataPoints[i].trans = trans; - this.dataPoints[i].screen = screen; + Graph2d.prototype.setGroups = function(groups) { + // convert to type DataSet when needed + var newDataSet; + if (!groups) { + newDataSet = null; } - - // start the line - if (this.dataPoints.length > 0) { - point = this.dataPoints[0]; - - ctx.lineWidth = 1; // TODO: make customizable - ctx.strokeStyle = 'blue'; // TODO: make customizable - ctx.beginPath(); - ctx.moveTo(point.screen.x, point.screen.y); + else if (groups instanceof DataSet || groups instanceof DataView) { + newDataSet = groups; } - - // draw the datapoints as colored circles - for (i = 1; i < this.dataPoints.length; i++) { - point = this.dataPoints[i]; - ctx.lineTo(point.screen.x, point.screen.y); + else { + // turn an array into a dataset + newDataSet = new DataSet(groups); } - // finish the line - if (this.dataPoints.length > 0) { - ctx.stroke(); - } + this.groupsData = newDataSet; + this.linegraph.setGroups(newDataSet); }; /** - * Start a moving operation inside the provided parent element - * @param {Event} event The event that occurred (required for - * retrieving the mouse position) + * Returns an object containing an SVG element with the icon of the group (size determined by iconWidth and iconHeight), the label of the group (content) and the yAxisOrientation of the group (left or right). + * @param groupId + * @param width + * @param height */ - Graph3d.prototype._onMouseDown = function(event) { - event = event || window.event; - - // check if mouse is still down (may be up when focus is lost for example - // in an iframe) - if (this.leftButtonDown) { - this._onMouseUp(event); - } - - // only react on left mouse button down - this.leftButtonDown = event.which ? (event.which === 1) : (event.button === 1); - if (!this.leftButtonDown && !this.touchDown) return; + Graph2d.prototype.getLegend = function(groupId, width, height) { + if (width === undefined) {width = 15;} + if (height === undefined) {height = 15;} + if (this.linegraph.groups[groupId] !== undefined) { + return this.linegraph.groups[groupId].getLegend(width,height); + } + else { + return "cannot find group:" + groupId; + } + } - // get mouse position (different code for IE and all other browsers) - this.startMouseX = getMouseX(event); - this.startMouseY = getMouseY(event); + /** + * This checks if the visible option of the supplied group (by ID) is true or false. + * @param groupId + * @returns {*} + */ + Graph2d.prototype.isGroupVisible = function(groupId) { + if (this.linegraph.groups[groupId] !== undefined) { + return this.linegraph.groups[groupId].visible; + } + else { + return false; + } + } - this.startStart = new Date(this.start); - this.startEnd = new Date(this.end); - this.startArmRotation = this.camera.getArmRotation(); - this.frame.style.cursor = 'move'; + /** + * Get the data range of the item set. + * @returns {{min: Date, max: Date}} range A range with a start and end Date. + * When no minimum is found, min==null + * When no maximum is found, max==null + */ + Graph2d.prototype.getItemRange = function() { + var min = null; + var max = null; - // add event listeners to handle moving the contents - // we store the function onmousemove and onmouseup in the graph, so we can - // remove the eventlisteners lateron in the function mouseUp() - var me = this; - this.onmousemove = function (event) {me._onMouseMove(event);}; - this.onmouseup = function (event) {me._onMouseUp(event);}; - util.addEventListener(document, 'mousemove', me.onmousemove); - util.addEventListener(document, 'mouseup', me.onmouseup); - util.preventDefault(event); + // calculate min from start filed + for (var groupId in this.linegraph.groups) { + if (this.linegraph.groups.hasOwnProperty(groupId)) { + if (this.linegraph.groups[groupId].visible == true) { + for (var i = 0; i < this.linegraph.groups[groupId].itemsData.length; i++) { + var item = this.linegraph.groups[groupId].itemsData[i]; + var value = util.convert(item.x, 'Date').valueOf(); + min = min == null ? value : min > value ? value : min; + max = max == null ? value : max < value ? value : max; + } + } + } + } + + return { + min: (min != null) ? new Date(min) : null, + max: (max != null) ? new Date(max) : null + }; }; - /** - * Perform moving operating. - * This function activated from within the funcion Graph.mouseDown(). - * @param {Event} event Well, eehh, the event - */ - Graph3d.prototype._onMouseMove = function (event) { - event = event || window.event; - // calculate change in mouse position - var diffX = parseFloat(getMouseX(event)) - this.startMouseX; - var diffY = parseFloat(getMouseY(event)) - this.startMouseY; + module.exports = Graph2d; - var horizontalNew = this.startArmRotation.horizontal + diffX / 200; - var verticalNew = this.startArmRotation.vertical + diffY / 200; - var snapAngle = 4; // degrees - var snapValue = Math.sin(snapAngle / 360 * 2 * Math.PI); +/***/ }, +/* 14 */ +/***/ function(module, exports, __webpack_require__) { - // snap horizontally to nice angles at 0pi, 0.5pi, 1pi, 1.5pi, etc... - // the -0.001 is to take care that the vertical axis is always drawn at the left front corner - if (Math.abs(Math.sin(horizontalNew)) < snapValue) { - horizontalNew = Math.round((horizontalNew / Math.PI)) * Math.PI - 0.001; - } - if (Math.abs(Math.cos(horizontalNew)) < snapValue) { - horizontalNew = (Math.round((horizontalNew/ Math.PI - 0.5)) + 0.5) * Math.PI - 0.001; - } + /** + * @constructor DataStep + * The class DataStep is an iterator for data for the lineGraph. You provide a start data point and an + * end data point. The class itself determines the best scale (step size) based on the + * provided start Date, end Date, and minimumStep. + * + * If minimumStep is provided, the step size is chosen as close as possible + * to the minimumStep but larger than minimumStep. If minimumStep is not + * provided, the scale is set to 1 DAY. + * The minimumStep should correspond with the onscreen size of about 6 characters + * + * Alternatively, you can set a scale by hand. + * After creation, you can initialize the class by executing first(). Then you + * can iterate from the start date to the end date via next(). You can check if + * the end date is reached with the function hasNext(). After each step, you can + * retrieve the current date via getCurrent(). + * The DataStep has scales ranging from milliseconds, seconds, minutes, hours, + * days, to years. + * + * Version: 1.2 + * + * @param {Date} [start] The start date, for example new Date(2010, 9, 21) + * or new Date(2010, 9, 21, 23, 45, 00) + * @param {Date} [end] The end date + * @param {Number} [minimumStep] Optional. Minimum step size in milliseconds + */ + function DataStep(start, end, minimumStep, containerHeight, forcedStepSize) { + // variables + this.current = 0; - // snap vertically to nice angles - if (Math.abs(Math.sin(verticalNew)) < snapValue) { - verticalNew = Math.round((verticalNew / Math.PI)) * Math.PI; - } - if (Math.abs(Math.cos(verticalNew)) < snapValue) { - verticalNew = (Math.round((verticalNew/ Math.PI - 0.5)) + 0.5) * Math.PI; - } + this.autoScale = true; + this.stepIndex = 0; + this.step = 1; + this.scale = 1; - this.camera.setArmRotation(horizontalNew, verticalNew); - this.redraw(); + this.marginStart; + this.marginEnd; - // fire a cameraPositionChange event - var parameters = this.getCameraPosition(); - this.emit('cameraPositionChange', parameters); + this.majorSteps = [1, 2, 5, 10]; + this.minorSteps = [0.25, 0.5, 1, 2]; + + this.setRange(start, end, minimumStep, containerHeight, forcedStepSize); + } - util.preventDefault(event); - }; /** - * Stop moving operating. - * This function activated from within the funcion Graph.mouseDown(). - * @param {event} event The event + * Set a new range + * If minimumStep is provided, the step size is chosen as close as possible + * to the minimumStep but larger than minimumStep. If minimumStep is not + * provided, the scale is set to 1 DAY. + * The minimumStep should correspond with the onscreen size of about 6 characters + * @param {Number} [start] The start date and time. + * @param {Number} [end] The end date and time. + * @param {Number} [minimumStep] Optional. Minimum step size in milliseconds */ - Graph3d.prototype._onMouseUp = function (event) { - this.frame.style.cursor = 'auto'; - this.leftButtonDown = false; + DataStep.prototype.setRange = function(start, end, minimumStep, containerHeight, forcedStepSize) { + this._start = start; + this._end = end; - // remove event listeners here - util.removeEventListener(document, 'mousemove', this.onmousemove); - util.removeEventListener(document, 'mouseup', this.onmouseup); - util.preventDefault(event); + if (start == end) { + this._start = start - 0.75; + this._end = end + 1; + } + + if (this.autoScale) { + this.setMinimumStep(minimumStep, containerHeight, forcedStepSize); + } + this.setFirst(); }; /** - * After having moved the mouse, a tooltip should pop up when the mouse is resting on a data point - * @param {Event} event A mouse move event + * Automatically determine the scale that bests fits the provided minimum step + * @param {Number} [minimumStep] The minimum step size in milliseconds */ - Graph3d.prototype._onTooltip = function (event) { - var delay = 300; // ms - var mouseX = getMouseX(event) - util.getAbsoluteLeft(this.frame); - var mouseY = getMouseY(event) - util.getAbsoluteTop(this.frame); - - if (!this.showTooltip) { - return; - } + DataStep.prototype.setMinimumStep = function(minimumStep, containerHeight) { + // round to floor + var size = this._end - this._start; + var safeSize = size * 1.1; + var minimumStepValue = minimumStep * (safeSize / containerHeight); + var orderOfMagnitude = Math.round(Math.log(safeSize)/Math.LN10); - if (this.tooltipTimeout) { - clearTimeout(this.tooltipTimeout); - } + var minorStepIdx = -1; + var magnitudefactor = Math.pow(10,orderOfMagnitude); - // (delayed) display of a tooltip only if no mouse button is down - if (this.leftButtonDown) { - this._hideTooltip(); - return; + var start = 0; + if (orderOfMagnitude < 0) { + start = orderOfMagnitude; } - if (this.tooltip && this.tooltip.dataPoint) { - // tooltip is currently visible - var dataPoint = this._dataPointFromXY(mouseX, mouseY); - if (dataPoint !== this.tooltip.dataPoint) { - // datapoint changed - if (dataPoint) { - this._showTooltip(dataPoint); - } - else { - this._hideTooltip(); + var solutionFound = false; + for (var i = start; Math.abs(i) <= Math.abs(orderOfMagnitude); i++) { + magnitudefactor = Math.pow(10,i); + for (var j = 0; j < this.minorSteps.length; j++) { + var stepSize = magnitudefactor * this.minorSteps[j]; + if (stepSize >= minimumStepValue) { + solutionFound = true; + minorStepIdx = j; + break; } } + if (solutionFound == true) { + break; + } } - else { - // tooltip is currently not visible - var me = this; - this.tooltipTimeout = setTimeout(function () { - me.tooltipTimeout = null; - - // show a tooltip if we have a data point - var dataPoint = me._dataPointFromXY(mouseX, mouseY); - if (dataPoint) { - me._showTooltip(dataPoint); - } - }, delay); - } + this.stepIndex = minorStepIdx; + this.scale = magnitudefactor; + this.step = magnitudefactor * this.minorSteps[minorStepIdx]; }; + /** - * Event handler for touchstart event on mobile devices + * Set the range iterator to the start date. */ - Graph3d.prototype._onTouchStart = function(event) { - this.touchDown = true; + DataStep.prototype.first = function() { + this.setFirst(); + }; - var me = this; - this.ontouchmove = function (event) {me._onTouchMove(event);}; - this.ontouchend = function (event) {me._onTouchEnd(event);}; - util.addEventListener(document, 'touchmove', me.ontouchmove); - util.addEventListener(document, 'touchend', me.ontouchend); + /** + * Round the current date to the first minor date value + * This must be executed once when the current date is set to start Date + */ + DataStep.prototype.setFirst = function() { + var niceStart = this._start - (this.scale * this.minorSteps[this.stepIndex]); + var niceEnd = this._end + (this.scale * this.minorSteps[this.stepIndex]); + + this.marginEnd = this.roundToMinor(niceEnd); + this.marginStart = this.roundToMinor(niceStart); + this.marginRange = this.marginEnd - this.marginStart; + + this.current = this.marginEnd; - this._onMouseDown(event); }; + DataStep.prototype.roundToMinor = function(value) { + var rounded = value - (value % (this.scale * this.minorSteps[this.stepIndex])); + if (value % (this.scale * this.minorSteps[this.stepIndex]) > 0.5 * (this.scale * this.minorSteps[this.stepIndex])) { + return rounded + (this.scale * this.minorSteps[this.stepIndex]); + } + else { + return rounded; + } + } + + /** - * Event handler for touchmove event on mobile devices + * Check if the there is a next step + * @return {boolean} true if the current date has not passed the end date */ - Graph3d.prototype._onTouchMove = function(event) { - this._onMouseMove(event); + DataStep.prototype.hasNext = function () { + return (this.current >= this.marginStart); }; /** - * Event handler for touchend event on mobile devices + * Do the next step */ - Graph3d.prototype._onTouchEnd = function(event) { - this.touchDown = false; - - util.removeEventListener(document, 'touchmove', this.ontouchmove); - util.removeEventListener(document, 'touchend', this.ontouchend); + DataStep.prototype.next = function() { + var prev = this.current; + this.current -= this.step; - this._onMouseUp(event); + // safety mechanism: if current time is still unchanged, move to the end + if (this.current == prev) { + this.current = this._end; + } }; - /** - * Event handler for mouse wheel event, used to zoom the graph - * Code from http://adomas.org/javascript-mouse-wheel/ - * @param {event} event The event + * Do the next step */ - Graph3d.prototype._onWheel = function(event) { - if (!event) /* For IE. */ - event = window.event; - - // retrieve delta - var delta = 0; - if (event.wheelDelta) { /* IE/Opera. */ - delta = event.wheelDelta/120; - } else if (event.detail) { /* Mozilla case. */ - // In Mozilla, sign of delta is different than in IE. - // Also, delta is multiple of 3. - delta = -event.detail/3; - } + DataStep.prototype.previous = function() { + this.current += this.step; + this.marginEnd += this.step; + this.marginRange = this.marginEnd - this.marginStart; + }; - // If delta is nonzero, handle it. - // Basically, delta is now positive if wheel was scrolled up, - // and negative, if wheel was scrolled down. - if (delta) { - var oldLength = this.camera.getArmLength(); - var newLength = oldLength * (1 - delta / 10); - this.camera.setArmLength(newLength); - this.redraw(); - this._hideTooltip(); + /** + * Get the current datetime + * @return {String} current The current date + */ + DataStep.prototype.getCurrent = function() { + var toPrecision = '' + Number(this.current).toPrecision(5); + for (var i = toPrecision.length-1; i > 0; i--) { + if (toPrecision[i] == "0") { + toPrecision = toPrecision.slice(0,i); + } + else if (toPrecision[i] == "." || toPrecision[i] == ",") { + toPrecision = toPrecision.slice(0,i); + break; + } + else{ + break; + } } - // fire a cameraPositionChange event - var parameters = this.getCameraPosition(); - this.emit('cameraPositionChange', parameters); - - // Prevent default actions caused by mouse wheel. - // That might be ugly, but we handle scrolls somehow - // anyway, so don't bother here.. - util.preventDefault(event); + return toPrecision; }; - /** - * Test whether a point lies inside given 2D triangle - * @param {Point2d} point - * @param {Point2d[]} triangle - * @return {boolean} Returns true if given point lies inside or on the edge of the triangle - * @private - */ - Graph3d.prototype._insideTriangle = function (point, triangle) { - var a = triangle[0], - b = triangle[1], - c = triangle[2]; - function sign (x) { - return x > 0 ? 1 : x < 0 ? -1 : 0; - } - var as = sign((b.x - a.x) * (point.y - a.y) - (b.y - a.y) * (point.x - a.x)); - var bs = sign((c.x - b.x) * (point.y - b.y) - (c.y - b.y) * (point.x - b.x)); - var cs = sign((a.x - c.x) * (point.y - c.y) - (a.y - c.y) * (point.x - c.x)); + /** + * Snap a date to a rounded value. + * The snap intervals are dependent on the current scale and step. + * @param {Date} date the date to be snapped. + * @return {Date} snappedDate + */ + DataStep.prototype.snap = function(date) { - // each of the three signs must be either equal to each other or zero - return (as == 0 || bs == 0 || as == bs) && - (bs == 0 || cs == 0 || bs == cs) && - (as == 0 || cs == 0 || as == cs); }; /** - * Find a data point close to given screen position (x, y) - * @param {Number} x - * @param {Number} y - * @return {Object | null} The closest data point or null if not close to any data point - * @private + * Check if the current value is a major value (for example when the step + * is DAY, a major value is each first day of the MONTH) + * @return {boolean} true if current date is major, else false. */ - Graph3d.prototype._dataPointFromXY = function (x, y) { - var i, - distMax = 100, // px - dataPoint = null, - closestDataPoint = null, - closestDist = null, - center = new Point2d(x, y); + DataStep.prototype.isMajor = function() { + return (this.current % (this.scale * this.majorSteps[this.stepIndex]) == 0); + }; - if (this.style === Graph3d.STYLE.BAR || - this.style === Graph3d.STYLE.BARCOLOR || - this.style === Graph3d.STYLE.BARSIZE) { - // the data points are ordered from far away to closest - for (i = this.dataPoints.length - 1; i >= 0; i--) { - dataPoint = this.dataPoints[i]; - var surfaces = dataPoint.surfaces; - if (surfaces) { - for (var s = surfaces.length - 1; s >= 0; s--) { - // split each surface in two triangles, and see if the center point is inside one of these - var surface = surfaces[s]; - var corners = surface.corners; - var triangle1 = [corners[0].screen, corners[1].screen, corners[2].screen]; - var triangle2 = [corners[2].screen, corners[3].screen, corners[0].screen]; - if (this._insideTriangle(center, triangle1) || - this._insideTriangle(center, triangle2)) { - // return immediately at the first hit - return dataPoint; - } - } - } - } - } - else { - // find the closest data point, using distance to the center of the point on 2d screen - for (i = 0; i < this.dataPoints.length; i++) { - dataPoint = this.dataPoints[i]; - var point = dataPoint.screen; - if (point) { - var distX = Math.abs(x - point.x); - var distY = Math.abs(y - point.y); - var dist = Math.sqrt(distX * distX + distY * distY); + module.exports = DataStep; - if ((closestDist === null || dist < closestDist) && dist < distMax) { - closestDist = dist; - closestDataPoint = dataPoint; - } - } - } - } +/***/ }, +/* 15 */ +/***/ function(module, exports, __webpack_require__) { - return closestDataPoint; - }; + var util = __webpack_require__(1); + var hammerUtil = __webpack_require__(43); + var moment = __webpack_require__(40); + var Component = __webpack_require__(18); /** - * Display a tooltip for given data point - * @param {Object} dataPoint - * @private + * @constructor Range + * A Range controls a numeric range with a start and end value. + * The Range adjusts the range based on mouse events or programmatic changes, + * and triggers events when the range is changing or has been changed. + * @param {{dom: Object, domProps: Object, emitter: Emitter}} body + * @param {Object} [options] See description at Range.setOptions */ - Graph3d.prototype._showTooltip = function (dataPoint) { - var content, line, dot; + function Range(body, options) { + var now = moment().hours(0).minutes(0).seconds(0).milliseconds(0); + this.start = now.clone().add('days', -3).valueOf(); // Number + this.end = now.clone().add('days', 4).valueOf(); // Number - if (!this.tooltip) { - content = document.createElement('div'); - content.style.position = 'absolute'; - content.style.padding = '10px'; - content.style.border = '1px solid #4d4d4d'; - content.style.color = '#1a1a1a'; - content.style.background = 'rgba(255,255,255,0.7)'; - content.style.borderRadius = '2px'; - content.style.boxShadow = '5px 5px 10px rgba(128,128,128,0.5)'; + this.body = body; - line = document.createElement('div'); - line.style.position = 'absolute'; - line.style.height = '40px'; - line.style.width = '0'; - line.style.borderLeft = '1px solid #4d4d4d'; + // default options + this.defaultOptions = { + start: null, + end: null, + direction: 'horizontal', // 'horizontal' or 'vertical' + moveable: true, + zoomable: true, + min: null, + max: null, + zoomMin: 10, // milliseconds + zoomMax: 1000 * 60 * 60 * 24 * 365 * 10000 // milliseconds + }; + this.options = util.extend({}, this.defaultOptions); - dot = document.createElement('div'); - dot.style.position = 'absolute'; - dot.style.height = '0'; - dot.style.width = '0'; - dot.style.border = '5px solid #4d4d4d'; - dot.style.borderRadius = '5px'; + this.props = { + touch: {} + }; - this.tooltip = { - dataPoint: null, - dom: { - content: content, - line: line, - dot: dot - } - }; - } - else { - content = this.tooltip.dom.content; - line = this.tooltip.dom.line; - dot = this.tooltip.dom.dot; - } - - this._hideTooltip(); + // drag listeners for dragging + this.body.emitter.on('dragstart', this._onDragStart.bind(this)); + this.body.emitter.on('drag', this._onDrag.bind(this)); + this.body.emitter.on('dragend', this._onDragEnd.bind(this)); - this.tooltip.dataPoint = dataPoint; - if (typeof this.showTooltip === 'function') { - content.innerHTML = this.showTooltip(dataPoint.point); - } - else { - content.innerHTML = '' + - '' + - '' + - '' + - '
x:' + dataPoint.point.x + '
y:' + dataPoint.point.y + '
z:' + dataPoint.point.z + '
'; - } + // ignore dragging when holding + this.body.emitter.on('hold', this._onHold.bind(this)); - content.style.left = '0'; - content.style.top = '0'; - this.frame.appendChild(content); - this.frame.appendChild(line); - this.frame.appendChild(dot); + // mouse wheel for zooming + this.body.emitter.on('mousewheel', this._onMouseWheel.bind(this)); + this.body.emitter.on('DOMMouseScroll', this._onMouseWheel.bind(this)); // For FF - // calculate sizes - var contentWidth = content.offsetWidth; - var contentHeight = content.offsetHeight; - var lineHeight = line.offsetHeight; - var dotWidth = dot.offsetWidth; - var dotHeight = dot.offsetHeight; + // pinch to zoom + this.body.emitter.on('touch', this._onTouch.bind(this)); + this.body.emitter.on('pinch', this._onPinch.bind(this)); - var left = dataPoint.screen.x - contentWidth / 2; - left = Math.min(Math.max(left, 10), this.frame.clientWidth - 10 - contentWidth); + this.setOptions(options); + } - line.style.left = dataPoint.screen.x + 'px'; - line.style.top = (dataPoint.screen.y - lineHeight) + 'px'; - content.style.left = left + 'px'; - content.style.top = (dataPoint.screen.y - lineHeight - contentHeight) + 'px'; - dot.style.left = (dataPoint.screen.x - dotWidth / 2) + 'px'; - dot.style.top = (dataPoint.screen.y - dotHeight / 2) + 'px'; - }; + Range.prototype = new Component(); /** - * Hide the tooltip when displayed - * @private + * Set options for the range controller + * @param {Object} options Available options: + * {Number | Date | String} start Start date for the range + * {Number | Date | String} end End date for the range + * {Number} min Minimum value for start + * {Number} max Maximum value for end + * {Number} zoomMin Set a minimum value for + * (end - start). + * {Number} zoomMax Set a maximum value for + * (end - start). + * {Boolean} moveable Enable moving of the range + * by dragging. True by default + * {Boolean} zoomable Enable zooming of the range + * by pinching/scrolling. True by default */ - Graph3d.prototype._hideTooltip = function () { - if (this.tooltip) { - this.tooltip.dataPoint = null; + Range.prototype.setOptions = function (options) { + if (options) { + // copy the options that we know + var fields = ['direction', 'min', 'max', 'zoomMin', 'zoomMax', 'moveable', 'zoomable']; + util.selectiveExtend(fields, this.options, options); - for (var prop in this.tooltip.dom) { - if (this.tooltip.dom.hasOwnProperty(prop)) { - var elem = this.tooltip.dom[prop]; - if (elem && elem.parentNode) { - elem.parentNode.removeChild(elem); - } - } + if ('start' in options || 'end' in options) { + // apply a new range. both start and end are optional + this.setRange(options.start, options.end); } } }; - /**--------------------------------------------------------------------------**/ - - - /** - * Get the horizontal mouse position from a mouse event - * @param {Event} event - * @return {Number} mouse x - */ - getMouseX = function(event) { - if ('clientX' in event) return event.clientX; - return event.targetTouches[0] && event.targetTouches[0].clientX || 0; - }; - - /** - * Get the vertical mouse position from a mouse event - * @param {Event} event - * @return {Number} mouse y - */ - getMouseY = function(event) { - if ('clientY' in event) return event.clientY; - return event.targetTouches[0] && event.targetTouches[0].clientY || 0; - }; - - module.exports = Graph3d; - - -/***/ }, -/* 10 */ -/***/ function(module, exports, __webpack_require__) { - - - /** - * Expose `Emitter`. - */ - - module.exports = Emitter; - - /** - * Initialize a new `Emitter`. - * - * @api public - */ - - function Emitter(obj) { - if (obj) return mixin(obj); - }; - /** - * Mixin the emitter properties. - * - * @param {Object} obj - * @return {Object} - * @api private + * Test whether direction has a valid value + * @param {String} direction 'horizontal' or 'vertical' */ - - function mixin(obj) { - for (var key in Emitter.prototype) { - obj[key] = Emitter.prototype[key]; + function validateDirection (direction) { + if (direction != 'horizontal' && direction != 'vertical') { + throw new TypeError('Unknown direction "' + direction + '". ' + + 'Choose "horizontal" or "vertical".'); } - return obj; } /** - * Listen on the given `event` with `fn`. - * - * @param {String} event - * @param {Function} fn - * @return {Emitter} - * @api public + * Set a new start and end range + * @param {Number} [start] + * @param {Number} [end] */ - - Emitter.prototype.on = - Emitter.prototype.addEventListener = function(event, fn){ - this._callbacks = this._callbacks || {}; - (this._callbacks[event] = this._callbacks[event] || []) - .push(fn); - return this; + Range.prototype.setRange = function(start, end) { + var changed = this._applyRange(start, end); + if (changed) { + var params = { + start: new Date(this.start), + end: new Date(this.end) + }; + this.body.emitter.emit('rangechange', params); + this.body.emitter.emit('rangechanged', params); + } }; /** - * Adds an `event` listener that will be invoked a single - * time then automatically removed. - * - * @param {String} event - * @param {Function} fn - * @return {Emitter} - * @api public + * Set a new start and end range. This method is the same as setRange, but + * does not trigger a range change and range changed event, and it returns + * true when the range is changed + * @param {Number} [start] + * @param {Number} [end] + * @return {Boolean} changed + * @private */ + Range.prototype._applyRange = function(start, end) { + var newStart = (start != null) ? util.convert(start, 'Date').valueOf() : this.start, + newEnd = (end != null) ? util.convert(end, 'Date').valueOf() : this.end, + max = (this.options.max != null) ? util.convert(this.options.max, 'Date').valueOf() : null, + min = (this.options.min != null) ? util.convert(this.options.min, 'Date').valueOf() : null, + diff; - Emitter.prototype.once = function(event, fn){ - var self = this; - this._callbacks = this._callbacks || {}; - - function on() { - self.off(event, on); - fn.apply(this, arguments); + // check for valid number + if (isNaN(newStart) || newStart === null) { + throw new Error('Invalid start "' + start + '"'); + } + if (isNaN(newEnd) || newEnd === null) { + throw new Error('Invalid end "' + end + '"'); } - on.fn = fn; - this.on(event, on); - return this; - }; - - /** - * Remove the given callback for `event` or all - * registered callbacks. - * - * @param {String} event - * @param {Function} fn - * @return {Emitter} - * @api public - */ + // prevent start < end + if (newEnd < newStart) { + newEnd = newStart; + } - Emitter.prototype.off = - Emitter.prototype.removeListener = - Emitter.prototype.removeAllListeners = - Emitter.prototype.removeEventListener = function(event, fn){ - this._callbacks = this._callbacks || {}; + // prevent start < min + if (min !== null) { + if (newStart < min) { + diff = (min - newStart); + newStart += diff; + newEnd += diff; - // all - if (0 == arguments.length) { - this._callbacks = {}; - return this; + // prevent end > max + if (max != null) { + if (newEnd > max) { + newEnd = max; + } + } + } } - // specific event - var callbacks = this._callbacks[event]; - if (!callbacks) return this; + // prevent end > max + if (max !== null) { + if (newEnd > max) { + diff = (newEnd - max); + newStart -= diff; + newEnd -= diff; - // remove all handlers - if (1 == arguments.length) { - delete this._callbacks[event]; - return this; + // prevent start < min + if (min != null) { + if (newStart < min) { + newStart = min; + } + } + } } - // remove specific handler - var cb; - for (var i = 0; i < callbacks.length; i++) { - cb = callbacks[i]; - if (cb === fn || cb.fn === fn) { - callbacks.splice(i, 1); - break; + // prevent (end-start) < zoomMin + if (this.options.zoomMin !== null) { + var zoomMin = parseFloat(this.options.zoomMin); + if (zoomMin < 0) { + zoomMin = 0; + } + if ((newEnd - newStart) < zoomMin) { + if ((this.end - this.start) === zoomMin) { + // ignore this action, we are already zoomed to the minimum + newStart = this.start; + newEnd = this.end; + } + else { + // zoom to the minimum + diff = (zoomMin - (newEnd - newStart)); + newStart -= diff / 2; + newEnd += diff / 2; + } } } - return this; - }; - - /** - * Emit `event` with the given args. - * - * @param {String} event - * @param {Mixed} ... - * @return {Emitter} - */ - - Emitter.prototype.emit = function(event){ - this._callbacks = this._callbacks || {}; - var args = [].slice.call(arguments, 1) - , callbacks = this._callbacks[event]; - if (callbacks) { - callbacks = callbacks.slice(0); - for (var i = 0, len = callbacks.length; i < len; ++i) { - callbacks[i].apply(this, args); + // prevent (end-start) > zoomMax + if (this.options.zoomMax !== null) { + var zoomMax = parseFloat(this.options.zoomMax); + if (zoomMax < 0) { + zoomMax = 0; + } + if ((newEnd - newStart) > zoomMax) { + if ((this.end - this.start) === zoomMax) { + // ignore this action, we are already zoomed to the maximum + newStart = this.start; + newEnd = this.end; + } + else { + // zoom to the maximum + diff = ((newEnd - newStart) - zoomMax); + newStart += diff / 2; + newEnd -= diff / 2; + } } } - return this; - }; + var changed = (this.start != newStart || this.end != newEnd); - /** - * Return array of callbacks for `event`. - * - * @param {String} event - * @return {Array} - * @api public - */ + this.start = newStart; + this.end = newEnd; - Emitter.prototype.listeners = function(event){ - this._callbacks = this._callbacks || {}; - return this._callbacks[event] || []; + return changed; }; /** - * Check if this emitter has `event` handlers. - * - * @param {String} event - * @return {Boolean} - * @api public + * Retrieve the current range. + * @return {Object} An object with start and end properties */ - - Emitter.prototype.hasListeners = function(event){ - return !! this.listeners(event).length; + Range.prototype.getRange = function() { + return { + start: this.start, + end: this.end + }; }; - -/***/ }, -/* 11 */ -/***/ function(module, exports, __webpack_require__) { - /** - * @prototype Point3d - * @param {Number} [x] - * @param {Number} [y] - * @param {Number} [z] + * Calculate the conversion offset and scale for current range, based on + * the provided width + * @param {Number} width + * @returns {{offset: number, scale: number}} conversion */ - function Point3d(x, y, z) { - this.x = x !== undefined ? x : 0; - this.y = y !== undefined ? y : 0; - this.z = z !== undefined ? z : 0; + Range.prototype.conversion = function (width) { + return Range.conversion(this.start, this.end, width); }; /** - * Subtract the two provided points, returns a-b - * @param {Point3d} a - * @param {Point3d} b - * @return {Point3d} a-b + * Static method to calculate the conversion offset and scale for a range, + * based on the provided start, end, and width + * @param {Number} start + * @param {Number} end + * @param {Number} width + * @returns {{offset: number, scale: number}} conversion */ - Point3d.subtract = function(a, b) { - var sub = new Point3d(); - sub.x = a.x - b.x; - sub.y = a.y - b.y; - sub.z = a.z - b.z; - return sub; + Range.conversion = function (start, end, width) { + if (width != 0 && (end - start != 0)) { + return { + offset: start, + scale: width / (end - start) + } + } + else { + return { + offset: 0, + scale: 1 + }; + } }; /** - * Add the two provided points, returns a+b - * @param {Point3d} a - * @param {Point3d} b - * @return {Point3d} a+b + * Start dragging horizontally or vertically + * @param {Event} event + * @private */ - Point3d.add = function(a, b) { - var sum = new Point3d(); - sum.x = a.x + b.x; - sum.y = a.y + b.y; - sum.z = a.z + b.z; - return sum; + Range.prototype._onDragStart = function(event) { + // only allow dragging when configured as movable + if (!this.options.moveable) return; + + // refuse to drag when we where pinching to prevent the timeline make a jump + // when releasing the fingers in opposite order from the touch screen + if (!this.props.touch.allowDragging) return; + + this.props.touch.start = this.start; + this.props.touch.end = this.end; + + if (this.body.dom.root) { + this.body.dom.root.style.cursor = 'move'; + } }; /** - * Calculate the average of two 3d points - * @param {Point3d} a - * @param {Point3d} b - * @return {Point3d} The average, (a+b)/2 + * Perform dragging operation + * @param {Event} event + * @private */ - Point3d.avg = function(a, b) { - return new Point3d( - (a.x + b.x) / 2, - (a.y + b.y) / 2, - (a.z + b.z) / 2 - ); + Range.prototype._onDrag = function (event) { + // only allow dragging when configured as movable + if (!this.options.moveable) return; + var direction = this.options.direction; + validateDirection(direction); + // refuse to drag when we where pinching to prevent the timeline make a jump + // when releasing the fingers in opposite order from the touch screen + if (!this.props.touch.allowDragging) return; + var delta = (direction == 'horizontal') ? event.gesture.deltaX : event.gesture.deltaY, + interval = (this.props.touch.end - this.props.touch.start), + width = (direction == 'horizontal') ? this.body.domProps.center.width : this.body.domProps.center.height, + diffRange = -delta / width * interval; + this._applyRange(this.props.touch.start + diffRange, this.props.touch.end + diffRange); + this.body.emitter.emit('rangechange', { + start: new Date(this.start), + end: new Date(this.end) + }); }; /** - * Calculate the cross product of the two provided points, returns axb - * Documentation: http://en.wikipedia.org/wiki/Cross_product - * @param {Point3d} a - * @param {Point3d} b - * @return {Point3d} cross product axb + * Stop dragging operation + * @param {event} event + * @private */ - Point3d.crossProduct = function(a, b) { - var crossproduct = new Point3d(); + Range.prototype._onDragEnd = function (event) { + // only allow dragging when configured as movable + if (!this.options.moveable) return; - crossproduct.x = a.y * b.z - a.z * b.y; - crossproduct.y = a.z * b.x - a.x * b.z; - crossproduct.z = a.x * b.y - a.y * b.x; + // refuse to drag when we where pinching to prevent the timeline make a jump + // when releasing the fingers in opposite order from the touch screen + if (!this.props.touch.allowDragging) return; - return crossproduct; - }; + if (this.body.dom.root) { + this.body.dom.root.style.cursor = 'auto'; + } + // fire a rangechanged event + this.body.emitter.emit('rangechanged', { + start: new Date(this.start), + end: new Date(this.end) + }); + }; /** - * Rtrieve the length of the vector (or the distance from this point to the origin - * @return {Number} length + * Event handler for mouse wheel event, used to zoom + * Code from http://adomas.org/javascript-mouse-wheel/ + * @param {Event} event + * @private */ - Point3d.prototype.length = function() { - return Math.sqrt( - this.x * this.x + - this.y * this.y + - this.z * this.z - ); - }; + Range.prototype._onMouseWheel = function(event) { + // only allow zooming when configured as zoomable and moveable + if (!(this.options.zoomable && this.options.moveable)) return; - module.exports = Point3d; + // retrieve delta + var delta = 0; + if (event.wheelDelta) { /* IE/Opera. */ + delta = event.wheelDelta / 120; + } else if (event.detail) { /* Mozilla case. */ + // In Mozilla, sign of delta is different than in IE. + // Also, delta is multiple of 3. + delta = -event.detail / 3; + } + // If delta is nonzero, handle it. + // Basically, delta is now positive if wheel was scrolled up, + // and negative, if wheel was scrolled down. + if (delta) { + // perform the zoom action. Delta is normally 1 or -1 -/***/ }, -/* 12 */ -/***/ function(module, exports, __webpack_require__) { + // adjust a negative delta such that zooming in with delta 0.1 + // equals zooming out with a delta -0.1 + var scale; + if (delta < 0) { + scale = 1 - (delta / 5); + } + else { + scale = 1 / (1 + (delta / 5)) ; + } + + // calculate center, the date to zoom around + var gesture = hammerUtil.fakeGesture(this, event), + pointer = getPointer(gesture.center, this.body.dom.center), + pointerDate = this._pointerToDate(pointer); + + this.zoom(scale, pointerDate); + } + + // Prevent default actions caused by mouse wheel + // (else the page and timeline both zoom and scroll) + event.preventDefault(); + }; /** - * @prototype Point2d - * @param {Number} [x] - * @param {Number} [y] + * Start of a touch gesture + * @private */ - Point2d = function (x, y) { - this.x = x !== undefined ? x : 0; - this.y = y !== undefined ? y : 0; + Range.prototype._onTouch = function (event) { + this.props.touch.start = this.start; + this.props.touch.end = this.end; + this.props.touch.allowDragging = true; + this.props.touch.center = null; }; - module.exports = Point2d; + /** + * On start of a hold gesture + * @private + */ + Range.prototype._onHold = function () { + this.props.touch.allowDragging = false; + }; + /** + * Handle pinch event + * @param {Event} event + * @private + */ + Range.prototype._onPinch = function (event) { + // only allow zooming when configured as zoomable and moveable + if (!(this.options.zoomable && this.options.moveable)) return; -/***/ }, -/* 13 */ -/***/ function(module, exports, __webpack_require__) { + this.props.touch.allowDragging = false; - var Point3d = __webpack_require__(11); + if (event.gesture.touches.length > 1) { + if (!this.props.touch.center) { + this.props.touch.center = getPointer(event.gesture.center, this.body.dom.center); + } - /** - * @class Camera - * The camera is mounted on a (virtual) camera arm. The camera arm can rotate - * The camera is always looking in the direction of the origin of the arm. - * This way, the camera always rotates around one fixed point, the location - * of the camera arm. - * - * Documentation: - * http://en.wikipedia.org/wiki/3D_projection - */ - Camera = function () { - this.armLocation = new Point3d(); - this.armRotation = {}; - this.armRotation.horizontal = 0; - this.armRotation.vertical = 0; - this.armLength = 1.7; + var scale = 1 / event.gesture.scale, + initDate = this._pointerToDate(this.props.touch.center); - this.cameraLocation = new Point3d(); - this.cameraRotation = new Point3d(0.5*Math.PI, 0, 0); + // calculate new start and end + var newStart = parseInt(initDate + (this.props.touch.start - initDate) * scale); + var newEnd = parseInt(initDate + (this.props.touch.end - initDate) * scale); - this.calculateCameraOrientation(); + // apply new range + this.setRange(newStart, newEnd); + } }; /** - * Set the location (origin) of the arm - * @param {Number} x Normalized value of x - * @param {Number} y Normalized value of y - * @param {Number} z Normalized value of z + * Helper function to calculate the center date for zooming + * @param {{x: Number, y: Number}} pointer + * @return {number} date + * @private */ - Camera.prototype.setArmLocation = function(x, y, z) { - this.armLocation.x = x; - this.armLocation.y = y; - this.armLocation.z = z; + Range.prototype._pointerToDate = function (pointer) { + var conversion; + var direction = this.options.direction; - this.calculateCameraOrientation(); + validateDirection(direction); + + if (direction == 'horizontal') { + var width = this.body.domProps.center.width; + conversion = this.conversion(width); + return pointer.x / conversion.scale + conversion.offset; + } + else { + var height = this.body.domProps.center.height; + conversion = this.conversion(height); + return pointer.y / conversion.scale + conversion.offset; + } }; /** - * Set the rotation of the camera arm - * @param {Number} horizontal The horizontal rotation, between 0 and 2*PI. - * Optional, can be left undefined. - * @param {Number} vertical The vertical rotation, between 0 and 0.5*PI - * if vertical=0.5*PI, the graph is shown from the - * top. Optional, can be left undefined. + * Get the pointer location relative to the location of the dom element + * @param {{pageX: Number, pageY: Number}} touch + * @param {Element} element HTML DOM element + * @return {{x: Number, y: Number}} pointer + * @private */ - Camera.prototype.setArmRotation = function(horizontal, vertical) { - if (horizontal !== undefined) { - this.armRotation.horizontal = horizontal; - } + function getPointer (touch, element) { + return { + x: touch.pageX - util.getAbsoluteLeft(element), + y: touch.pageY - util.getAbsoluteTop(element) + }; + } - if (vertical !== undefined) { - this.armRotation.vertical = vertical; - if (this.armRotation.vertical < 0) this.armRotation.vertical = 0; - if (this.armRotation.vertical > 0.5*Math.PI) this.armRotation.vertical = 0.5*Math.PI; + /** + * Zoom the range the given scale in or out. Start and end date will + * be adjusted, and the timeline will be redrawn. You can optionally give a + * date around which to zoom. + * For example, try scale = 0.9 or 1.1 + * @param {Number} scale Scaling factor. Values above 1 will zoom out, + * values below 1 will zoom in. + * @param {Number} [center] Value representing a date around which will + * be zoomed. + */ + Range.prototype.zoom = function(scale, center) { + // if centerDate is not provided, take it half between start Date and end Date + if (center == null) { + center = (this.start + this.end) / 2; } - if (horizontal !== undefined || vertical !== undefined) { - this.calculateCameraOrientation(); - } + // calculate new start and end + var newStart = center + (this.start - center) * scale; + var newEnd = center + (this.end - center) * scale; + + this.setRange(newStart, newEnd); }; /** - * Retrieve the current arm rotation - * @return {object} An object with parameters horizontal and vertical + * Move the range with a given delta to the left or right. Start and end + * value will be adjusted. For example, try delta = 0.1 or -0.1 + * @param {Number} delta Moving amount. Positive value will move right, + * negative value will move left */ - Camera.prototype.getArmRotation = function() { - var rot = {}; - rot.horizontal = this.armRotation.horizontal; - rot.vertical = this.armRotation.vertical; + Range.prototype.move = function(delta) { + // zoom start Date and end Date relative to the centerDate + var diff = (this.end - this.start); - return rot; + // apply new values + var newStart = this.start + diff * delta; + var newEnd = this.end + diff * delta; + + // TODO: reckon with min and max range + + this.start = newStart; + this.end = newEnd; }; /** - * Set the (normalized) length of the camera arm. - * @param {Number} length A length between 0.71 and 5.0 + * Move the range to a new center point + * @param {Number} moveTo New center point of the range */ - Camera.prototype.setArmLength = function(length) { - if (length === undefined) - return; + Range.prototype.moveTo = function(moveTo) { + var center = (this.start + this.end) / 2; - this.armLength = length; + var diff = center - moveTo; - // Radius must be larger than the corner of the graph, - // which has a distance of sqrt(0.5^2+0.5^2) = 0.71 from the center of the - // graph - if (this.armLength < 0.71) this.armLength = 0.71; - if (this.armLength > 5.0) this.armLength = 5.0; + // calculate new start and end + var newStart = this.start - diff; + var newEnd = this.end - diff; - this.calculateCameraOrientation(); + this.setRange(newStart, newEnd); }; - /** - * Retrieve the arm length - * @return {Number} length - */ - Camera.prototype.getArmLength = function() { - return this.armLength; - }; + module.exports = Range; + + +/***/ }, +/* 16 */ +/***/ function(module, exports, __webpack_require__) { + + // Utility functions for ordering and stacking of items + var EPSILON = 0.001; // used when checking collisions, to prevent round-off errors /** - * Retrieve the camera location - * @return {Point3d} cameraLocation + * Order items by their start data + * @param {Item[]} items */ - Camera.prototype.getCameraLocation = function() { - return this.cameraLocation; + exports.orderByStart = function(items) { + items.sort(function (a, b) { + return a.data.start - b.data.start; + }); }; /** - * Retrieve the camera rotation - * @return {Point3d} cameraRotation - */ - Camera.prototype.getCameraRotation = function() { - return this.cameraRotation; - }; - - /** - * Calculate the location and rotation of the camera based on the - * position and orientation of the camera arm + * Order items by their end date. If they have no end date, their start date + * is used. + * @param {Item[]} items */ - Camera.prototype.calculateCameraOrientation = function() { - // calculate location of the camera - this.cameraLocation.x = this.armLocation.x - this.armLength * Math.sin(this.armRotation.horizontal) * Math.cos(this.armRotation.vertical); - this.cameraLocation.y = this.armLocation.y - this.armLength * Math.cos(this.armRotation.horizontal) * Math.cos(this.armRotation.vertical); - this.cameraLocation.z = this.armLocation.z + this.armLength * Math.sin(this.armRotation.vertical); + exports.orderByEnd = function(items) { + items.sort(function (a, b) { + var aTime = ('end' in a.data) ? a.data.end : a.data.start, + bTime = ('end' in b.data) ? b.data.end : b.data.start; - // calculate rotation of the camera - this.cameraRotation.x = Math.PI/2 - this.armRotation.vertical; - this.cameraRotation.y = 0; - this.cameraRotation.z = -this.armRotation.horizontal; + return aTime - bTime; + }); }; - module.exports = Camera; - -/***/ }, -/* 14 */ -/***/ function(module, exports, __webpack_require__) { - - var DataView = __webpack_require__(8); - /** - * @class Filter - * - * @param {DataSet} data The google data table - * @param {Number} column The index of the column to be filtered - * @param {Graph} graph The graph + * Adjust vertical positions of the items such that they don't overlap each + * other. + * @param {Item[]} items + * All visible items + * @param {{item: {horizontal: number, vertical: number}, axis: number}} margin + * Margins between items and between items and the axis. + * @param {boolean} [force=false] + * If true, all items will be repositioned. If false (default), only + * items having a top===null will be re-stacked */ - function Filter (data, column, graph) { - this.data = data; - this.column = column; - this.graph = graph; // the parent graph - - this.index = undefined; - this.value = undefined; - - // read all distinct values and select the first one - this.values = graph.getDistinctValues(data.get(), this.column); - - // sort both numeric and string values correctly - this.values.sort(function (a, b) { - return a > b ? 1 : a < b ? -1 : 0; - }); + exports.stack = function(items, margin, force) { + var i, iMax; - if (this.values.length > 0) { - this.selectValue(0); + if (force) { + // reset top position of all items + for (i = 0, iMax = items.length; i < iMax; i++) { + items[i].top = null; + } } - // create an array with the filtered datapoints. this will be loaded afterwards - this.dataPoints = []; + // calculate new, non-overlapping positions + for (i = 0, iMax = items.length; i < iMax; i++) { + var item = items[i]; + if (item.top === null) { + // initialize top position + item.top = margin.axis; - this.loaded = false; - this.onLoadCallback = undefined; + do { + // TODO: optimize checking for overlap. when there is a gap without items, + // you only need to check for items from the next item on, not from zero + var collidingItem = null; + for (var j = 0, jj = items.length; j < jj; j++) { + var other = items[j]; + if (other.top !== null && other !== item && exports.collision(item, other, margin.item)) { + collidingItem = other; + break; + } + } - if (graph.animationPreload) { - this.loaded = false; - this.loadInBackground(); - } - else { - this.loaded = true; + if (collidingItem != null) { + // There is a collision. Reposition the items above the colliding element + item.top = collidingItem.top + collidingItem.height + margin.item.vertical; + } + } while (collidingItem); + } } }; - /** - * Return the label - * @return {string} label + * Adjust vertical positions of the items without stacking them + * @param {Item[]} items + * All visible items + * @param {{item: {horizontal: number, vertical: number}, axis: number}} margin + * Margins between items and between items and the axis. */ - Filter.prototype.isLoaded = function() { - return this.loaded; - }; + exports.nostack = function(items, margin) { + var i, iMax; + // reset top position of all items + for (i = 0, iMax = items.length; i < iMax; i++) { + items[i].top = margin.axis; + } + }; /** - * Return the loaded progress - * @return {Number} percentage between 0 and 100 + * Test if the two provided items collide + * The items must have parameters left, width, top, and height. + * @param {Item} a The first item + * @param {Item} b The second item + * @param {{horizontal: number, vertical: number}} margin + * An object containing a horizontal and vertical + * minimum required margin. + * @return {boolean} true if a and b collide, else false */ - Filter.prototype.getLoadedProgress = function() { - var len = this.values.length; + exports.collision = function(a, b, margin) { + return ((a.left - margin.horizontal + EPSILON) < (b.left + b.width) && + (a.left + a.width + margin.horizontal - EPSILON) > b.left && + (a.top - margin.vertical + EPSILON) < (b.top + b.height) && + (a.top + a.height + margin.vertical - EPSILON) > b.top); + }; - var i = 0; - while (this.dataPoints[i]) { - i++; - } - return Math.round(i / len * 100); - }; +/***/ }, +/* 17 */ +/***/ function(module, exports, __webpack_require__) { + var moment = __webpack_require__(40); /** - * Return the label - * @return {string} label + * @constructor TimeStep + * The class TimeStep is an iterator for dates. You provide a start date and an + * end date. The class itself determines the best scale (step size) based on the + * provided start Date, end Date, and minimumStep. + * + * If minimumStep is provided, the step size is chosen as close as possible + * to the minimumStep but larger than minimumStep. If minimumStep is not + * provided, the scale is set to 1 DAY. + * The minimumStep should correspond with the onscreen size of about 6 characters + * + * Alternatively, you can set a scale by hand. + * After creation, you can initialize the class by executing first(). Then you + * can iterate from the start date to the end date via next(). You can check if + * the end date is reached with the function hasNext(). After each step, you can + * retrieve the current date via getCurrent(). + * The TimeStep has scales ranging from milliseconds, seconds, minutes, hours, + * days, to years. + * + * Version: 1.2 + * + * @param {Date} [start] The start date, for example new Date(2010, 9, 21) + * or new Date(2010, 9, 21, 23, 45, 00) + * @param {Date} [end] The end date + * @param {Number} [minimumStep] Optional. Minimum step size in milliseconds */ - Filter.prototype.getLabel = function() { - return this.graph.filterLabel; - }; + function TimeStep(start, end, minimumStep) { + // variables + this.current = new Date(); + this._start = new Date(); + this._end = new Date(); + this.autoScale = true; + this.scale = TimeStep.SCALE.DAY; + this.step = 1; - /** - * Return the columnIndex of the filter - * @return {Number} columnIndex - */ - Filter.prototype.getColumn = function() { - return this.column; + // initialize the range + this.setRange(start, end, minimumStep); + } + + /// enum scale + TimeStep.SCALE = { + MILLISECOND: 1, + SECOND: 2, + MINUTE: 3, + HOUR: 4, + DAY: 5, + WEEKDAY: 6, + MONTH: 7, + YEAR: 8 }; + /** - * Return the currently selected value. Returns undefined if there is no selection - * @return {*} value + * Set a new range + * If minimumStep is provided, the step size is chosen as close as possible + * to the minimumStep but larger than minimumStep. If minimumStep is not + * provided, the scale is set to 1 DAY. + * The minimumStep should correspond with the onscreen size of about 6 characters + * @param {Date} [start] The start date and time. + * @param {Date} [end] The end date and time. + * @param {int} [minimumStep] Optional. Minimum step size in milliseconds */ - Filter.prototype.getSelectedValue = function() { - if (this.index === undefined) - return undefined; + TimeStep.prototype.setRange = function(start, end, minimumStep) { + if (!(start instanceof Date) || !(end instanceof Date)) { + throw "No legal start or end date in method setRange"; + } - return this.values[this.index]; - }; + this._start = (start != undefined) ? new Date(start.valueOf()) : new Date(); + this._end = (end != undefined) ? new Date(end.valueOf()) : new Date(); - /** - * Retrieve all values of the filter - * @return {Array} values - */ - Filter.prototype.getValues = function() { - return this.values; + if (this.autoScale) { + this.setMinimumStep(minimumStep); + } }; /** - * Retrieve one value of the filter - * @param {Number} index - * @return {*} value + * Set the range iterator to the start date. */ - Filter.prototype.getValue = function(index) { - if (index >= this.values.length) - throw 'Error: index out of range'; - - return this.values[index]; + TimeStep.prototype.first = function() { + this.current = new Date(this._start.valueOf()); + this.roundToMinor(); }; - /** - * Retrieve the (filtered) dataPoints for the currently selected filter index - * @param {Number} [index] (optional) - * @return {Array} dataPoints + * Round the current date to the first minor date value + * This must be executed once when the current date is set to start Date */ - Filter.prototype._getDataPoints = function(index) { - if (index === undefined) - index = this.index; - - if (index === undefined) - return []; - - var dataPoints; - if (this.dataPoints[index]) { - dataPoints = this.dataPoints[index]; + TimeStep.prototype.roundToMinor = function() { + // round to floor + // IMPORTANT: we have no breaks in this switch! (this is no bug) + //noinspection FallthroughInSwitchStatementJS + switch (this.scale) { + case TimeStep.SCALE.YEAR: + this.current.setFullYear(this.step * Math.floor(this.current.getFullYear() / this.step)); + this.current.setMonth(0); + case TimeStep.SCALE.MONTH: this.current.setDate(1); + case TimeStep.SCALE.DAY: // intentional fall through + case TimeStep.SCALE.WEEKDAY: this.current.setHours(0); + case TimeStep.SCALE.HOUR: this.current.setMinutes(0); + case TimeStep.SCALE.MINUTE: this.current.setSeconds(0); + case TimeStep.SCALE.SECOND: this.current.setMilliseconds(0); + //case TimeStep.SCALE.MILLISECOND: // nothing to do for milliseconds } - else { - var f = {}; - f.column = this.column; - f.value = this.values[index]; - var dataView = new DataView(this.data,{filter: function (item) {return (item[f.column] == f.value);}}).get(); - dataPoints = this.graph._getDataPoints(dataView); - - this.dataPoints[index] = dataPoints; + if (this.step != 1) { + // round down to the first minor value that is a multiple of the current step size + switch (this.scale) { + case TimeStep.SCALE.MILLISECOND: this.current.setMilliseconds(this.current.getMilliseconds() - this.current.getMilliseconds() % this.step); break; + case TimeStep.SCALE.SECOND: this.current.setSeconds(this.current.getSeconds() - this.current.getSeconds() % this.step); break; + case TimeStep.SCALE.MINUTE: this.current.setMinutes(this.current.getMinutes() - this.current.getMinutes() % this.step); break; + case TimeStep.SCALE.HOUR: this.current.setHours(this.current.getHours() - this.current.getHours() % this.step); break; + case TimeStep.SCALE.WEEKDAY: // intentional fall through + case TimeStep.SCALE.DAY: this.current.setDate((this.current.getDate()-1) - (this.current.getDate()-1) % this.step + 1); break; + case TimeStep.SCALE.MONTH: this.current.setMonth(this.current.getMonth() - this.current.getMonth() % this.step); break; + case TimeStep.SCALE.YEAR: this.current.setFullYear(this.current.getFullYear() - this.current.getFullYear() % this.step); break; + default: break; + } } - - return dataPoints; - }; - - - - /** - * Set a callback function when the filter is fully loaded. - */ - Filter.prototype.setOnLoadCallback = function(callback) { - this.onLoadCallback = callback; }; - /** - * Add a value to the list with available values for this filter - * No double entries will be created. - * @param {Number} index + * Check if the there is a next step + * @return {boolean} true if the current date has not passed the end date */ - Filter.prototype.selectValue = function(index) { - if (index >= this.values.length) - throw 'Error: index out of range'; - - this.index = index; - this.value = this.values[index]; + TimeStep.prototype.hasNext = function () { + return (this.current.valueOf() <= this._end.valueOf()); }; /** - * Load all filtered rows in the background one by one - * Start this method without providing an index! + * Do the next step */ - Filter.prototype.loadInBackground = function(index) { - if (index === undefined) - index = 0; - - var frame = this.graph.frame; + TimeStep.prototype.next = function() { + var prev = this.current.valueOf(); - if (index < this.values.length) { - var dataPointsTemp = this._getDataPoints(index); - //this.graph.redrawInfo(); // TODO: not neat + // Two cases, needed to prevent issues with switching daylight savings + // (end of March and end of October) + if (this.current.getMonth() < 6) { + switch (this.scale) { + case TimeStep.SCALE.MILLISECOND: - // create a progress box - if (frame.progress === undefined) { - frame.progress = document.createElement('DIV'); - frame.progress.style.position = 'absolute'; - frame.progress.style.color = 'gray'; - frame.appendChild(frame.progress); + this.current = new Date(this.current.valueOf() + this.step); break; + case TimeStep.SCALE.SECOND: this.current = new Date(this.current.valueOf() + this.step * 1000); break; + case TimeStep.SCALE.MINUTE: this.current = new Date(this.current.valueOf() + this.step * 1000 * 60); break; + case TimeStep.SCALE.HOUR: + this.current = new Date(this.current.valueOf() + this.step * 1000 * 60 * 60); + // in case of skipping an hour for daylight savings, adjust the hour again (else you get: 0h 5h 9h ... instead of 0h 4h 8h ...) + var h = this.current.getHours(); + this.current.setHours(h - (h % this.step)); + break; + case TimeStep.SCALE.WEEKDAY: // intentional fall through + case TimeStep.SCALE.DAY: this.current.setDate(this.current.getDate() + this.step); break; + case TimeStep.SCALE.MONTH: this.current.setMonth(this.current.getMonth() + this.step); break; + case TimeStep.SCALE.YEAR: this.current.setFullYear(this.current.getFullYear() + this.step); break; + default: break; } - var progress = this.getLoadedProgress(); - frame.progress.innerHTML = 'Loading animation... ' + progress + '%'; - // TODO: this is no nice solution... - frame.progress.style.bottom = 60 + 'px'; // TODO: use height of slider - frame.progress.style.left = 10 + 'px'; - - var me = this; - setTimeout(function() {me.loadInBackground(index+1);}, 10); - this.loaded = false; } else { - this.loaded = true; + switch (this.scale) { + case TimeStep.SCALE.MILLISECOND: this.current = new Date(this.current.valueOf() + this.step); break; + case TimeStep.SCALE.SECOND: this.current.setSeconds(this.current.getSeconds() + this.step); break; + case TimeStep.SCALE.MINUTE: this.current.setMinutes(this.current.getMinutes() + this.step); break; + case TimeStep.SCALE.HOUR: this.current.setHours(this.current.getHours() + this.step); break; + case TimeStep.SCALE.WEEKDAY: // intentional fall through + case TimeStep.SCALE.DAY: this.current.setDate(this.current.getDate() + this.step); break; + case TimeStep.SCALE.MONTH: this.current.setMonth(this.current.getMonth() + this.step); break; + case TimeStep.SCALE.YEAR: this.current.setFullYear(this.current.getFullYear() + this.step); break; + default: break; + } + } - // remove the progress box - if (frame.progress !== undefined) { - frame.removeChild(frame.progress); - frame.progress = undefined; + if (this.step != 1) { + // round down to the correct major value + switch (this.scale) { + case TimeStep.SCALE.MILLISECOND: if(this.current.getMilliseconds() < this.step) this.current.setMilliseconds(0); break; + case TimeStep.SCALE.SECOND: if(this.current.getSeconds() < this.step) this.current.setSeconds(0); break; + case TimeStep.SCALE.MINUTE: if(this.current.getMinutes() < this.step) this.current.setMinutes(0); break; + case TimeStep.SCALE.HOUR: if(this.current.getHours() < this.step) this.current.setHours(0); break; + case TimeStep.SCALE.WEEKDAY: // intentional fall through + case TimeStep.SCALE.DAY: if(this.current.getDate() < this.step+1) this.current.setDate(1); break; + case TimeStep.SCALE.MONTH: if(this.current.getMonth() < this.step) this.current.setMonth(0); break; + case TimeStep.SCALE.YEAR: break; // nothing to do for year + default: break; } + } - if (this.onLoadCallback) - this.onLoadCallback(); + // safety mechanism: if current time is still unchanged, move to the end + if (this.current.valueOf() == prev) { + this.current = new Date(this._end.valueOf()); } }; - module.exports = Filter; - - -/***/ }, -/* 15 */ -/***/ function(module, exports, __webpack_require__) { - var util = __webpack_require__(1); + /** + * Get the current datetime + * @return {Date} current The current date + */ + TimeStep.prototype.getCurrent = function() { + return this.current; + }; /** - * @constructor Slider + * Set a custom scale. Autoscaling will be disabled. + * For example setScale(SCALE.MINUTES, 5) will result + * in minor steps of 5 minutes, and major steps of an hour. * - * An html slider control with start/stop/prev/next buttons - * @param {Element} container The element where the slider will be created - * @param {Object} options Available options: - * {boolean} visible If true (default) the - * slider is visible. + * @param {TimeStep.SCALE} newScale + * A scale. Choose from SCALE.MILLISECOND, + * SCALE.SECOND, SCALE.MINUTE, SCALE.HOUR, + * SCALE.WEEKDAY, SCALE.DAY, SCALE.MONTH, + * SCALE.YEAR. + * @param {Number} newStep A step size, by default 1. Choose for + * example 1, 2, 5, or 10. */ - function Slider(container, options) { - if (container === undefined) { - throw 'Error: No container element defined'; - } - this.container = container; - this.visible = (options && options.visible != undefined) ? options.visible : true; - - if (this.visible) { - this.frame = document.createElement('DIV'); - //this.frame.style.backgroundColor = '#E5E5E5'; - this.frame.style.width = '100%'; - this.frame.style.position = 'relative'; - this.container.appendChild(this.frame); - - this.frame.prev = document.createElement('INPUT'); - this.frame.prev.type = 'BUTTON'; - this.frame.prev.value = 'Prev'; - this.frame.appendChild(this.frame.prev); - - this.frame.play = document.createElement('INPUT'); - this.frame.play.type = 'BUTTON'; - this.frame.play.value = 'Play'; - this.frame.appendChild(this.frame.play); - - this.frame.next = document.createElement('INPUT'); - this.frame.next.type = 'BUTTON'; - this.frame.next.value = 'Next'; - this.frame.appendChild(this.frame.next); - - this.frame.bar = document.createElement('INPUT'); - this.frame.bar.type = 'BUTTON'; - this.frame.bar.style.position = 'absolute'; - this.frame.bar.style.border = '1px solid red'; - this.frame.bar.style.width = '100px'; - this.frame.bar.style.height = '6px'; - this.frame.bar.style.borderRadius = '2px'; - this.frame.bar.style.MozBorderRadius = '2px'; - this.frame.bar.style.border = '1px solid #7F7F7F'; - this.frame.bar.style.backgroundColor = '#E5E5E5'; - this.frame.appendChild(this.frame.bar); - - this.frame.slide = document.createElement('INPUT'); - this.frame.slide.type = 'BUTTON'; - this.frame.slide.style.margin = '0px'; - this.frame.slide.value = ' '; - this.frame.slide.style.position = 'relative'; - this.frame.slide.style.left = '-100px'; - this.frame.appendChild(this.frame.slide); + TimeStep.prototype.setScale = function(newScale, newStep) { + this.scale = newScale; - // create events - var me = this; - this.frame.slide.onmousedown = function (event) {me._onMouseDown(event);}; - this.frame.prev.onclick = function (event) {me.prev(event);}; - this.frame.play.onclick = function (event) {me.togglePlay(event);}; - this.frame.next.onclick = function (event) {me.next(event);}; + if (newStep > 0) { + this.step = newStep; } - this.onChangeCallback = undefined; + this.autoScale = false; + }; - this.values = []; - this.index = undefined; + /** + * Enable or disable autoscaling + * @param {boolean} enable If true, autoascaling is set true + */ + TimeStep.prototype.setAutoScale = function (enable) { + this.autoScale = enable; + }; - this.playTimeout = undefined; - this.playInterval = 1000; // milliseconds - this.playLoop = true; - } /** - * Select the previous index + * Automatically determine the scale that bests fits the provided minimum step + * @param {Number} [minimumStep] The minimum step size in milliseconds */ - Slider.prototype.prev = function() { - var index = this.getIndex(); - if (index > 0) { - index--; - this.setIndex(index); + TimeStep.prototype.setMinimumStep = function(minimumStep) { + if (minimumStep == undefined) { + return; } - }; - /** - * Select the next index - */ - Slider.prototype.next = function() { - var index = this.getIndex(); - if (index < this.values.length - 1) { - index++; - this.setIndex(index); - } + var stepYear = (1000 * 60 * 60 * 24 * 30 * 12); + var stepMonth = (1000 * 60 * 60 * 24 * 30); + var stepDay = (1000 * 60 * 60 * 24); + var stepHour = (1000 * 60 * 60); + var stepMinute = (1000 * 60); + var stepSecond = (1000); + var stepMillisecond= (1); + + // find the smallest step that is larger than the provided minimumStep + if (stepYear*1000 > minimumStep) {this.scale = TimeStep.SCALE.YEAR; this.step = 1000;} + if (stepYear*500 > minimumStep) {this.scale = TimeStep.SCALE.YEAR; this.step = 500;} + if (stepYear*100 > minimumStep) {this.scale = TimeStep.SCALE.YEAR; this.step = 100;} + if (stepYear*50 > minimumStep) {this.scale = TimeStep.SCALE.YEAR; this.step = 50;} + if (stepYear*10 > minimumStep) {this.scale = TimeStep.SCALE.YEAR; this.step = 10;} + if (stepYear*5 > minimumStep) {this.scale = TimeStep.SCALE.YEAR; this.step = 5;} + if (stepYear > minimumStep) {this.scale = TimeStep.SCALE.YEAR; this.step = 1;} + if (stepMonth*3 > minimumStep) {this.scale = TimeStep.SCALE.MONTH; this.step = 3;} + if (stepMonth > minimumStep) {this.scale = TimeStep.SCALE.MONTH; this.step = 1;} + if (stepDay*5 > minimumStep) {this.scale = TimeStep.SCALE.DAY; this.step = 5;} + if (stepDay*2 > minimumStep) {this.scale = TimeStep.SCALE.DAY; this.step = 2;} + if (stepDay > minimumStep) {this.scale = TimeStep.SCALE.DAY; this.step = 1;} + if (stepDay/2 > minimumStep) {this.scale = TimeStep.SCALE.WEEKDAY; this.step = 1;} + if (stepHour*4 > minimumStep) {this.scale = TimeStep.SCALE.HOUR; this.step = 4;} + if (stepHour > minimumStep) {this.scale = TimeStep.SCALE.HOUR; this.step = 1;} + if (stepMinute*15 > minimumStep) {this.scale = TimeStep.SCALE.MINUTE; this.step = 15;} + if (stepMinute*10 > minimumStep) {this.scale = TimeStep.SCALE.MINUTE; this.step = 10;} + if (stepMinute*5 > minimumStep) {this.scale = TimeStep.SCALE.MINUTE; this.step = 5;} + if (stepMinute > minimumStep) {this.scale = TimeStep.SCALE.MINUTE; this.step = 1;} + if (stepSecond*15 > minimumStep) {this.scale = TimeStep.SCALE.SECOND; this.step = 15;} + if (stepSecond*10 > minimumStep) {this.scale = TimeStep.SCALE.SECOND; this.step = 10;} + if (stepSecond*5 > minimumStep) {this.scale = TimeStep.SCALE.SECOND; this.step = 5;} + if (stepSecond > minimumStep) {this.scale = TimeStep.SCALE.SECOND; this.step = 1;} + if (stepMillisecond*200 > minimumStep) {this.scale = TimeStep.SCALE.MILLISECOND; this.step = 200;} + if (stepMillisecond*100 > minimumStep) {this.scale = TimeStep.SCALE.MILLISECOND; this.step = 100;} + if (stepMillisecond*50 > minimumStep) {this.scale = TimeStep.SCALE.MILLISECOND; this.step = 50;} + if (stepMillisecond*10 > minimumStep) {this.scale = TimeStep.SCALE.MILLISECOND; this.step = 10;} + if (stepMillisecond*5 > minimumStep) {this.scale = TimeStep.SCALE.MILLISECOND; this.step = 5;} + if (stepMillisecond > minimumStep) {this.scale = TimeStep.SCALE.MILLISECOND; this.step = 1;} }; /** - * Select the next index + * Snap a date to a rounded value. + * The snap intervals are dependent on the current scale and step. + * @param {Date} date the date to be snapped. + * @return {Date} snappedDate */ - Slider.prototype.playNext = function() { - var start = new Date(); + TimeStep.prototype.snap = function(date) { + var clone = new Date(date.valueOf()); - var index = this.getIndex(); - if (index < this.values.length - 1) { - index++; - this.setIndex(index); - } - else if (this.playLoop) { - // jump to the start - index = 0; - this.setIndex(index); + if (this.scale == TimeStep.SCALE.YEAR) { + var year = clone.getFullYear() + Math.round(clone.getMonth() / 12); + clone.setFullYear(Math.round(year / this.step) * this.step); + clone.setMonth(0); + clone.setDate(0); + clone.setHours(0); + clone.setMinutes(0); + clone.setSeconds(0); + clone.setMilliseconds(0); } + else if (this.scale == TimeStep.SCALE.MONTH) { + if (clone.getDate() > 15) { + clone.setDate(1); + clone.setMonth(clone.getMonth() + 1); + // important: first set Date to 1, after that change the month. + } + else { + clone.setDate(1); + } - var end = new Date(); - var diff = (end - start); - - // calculate how much time it to to set the index and to execute the callback - // function. - var interval = Math.max(this.playInterval - diff, 0); - // document.title = diff // TODO: cleanup - - var me = this; - this.playTimeout = setTimeout(function() {me.playNext();}, interval); + clone.setHours(0); + clone.setMinutes(0); + clone.setSeconds(0); + clone.setMilliseconds(0); + } + else if (this.scale == TimeStep.SCALE.DAY) { + //noinspection FallthroughInSwitchStatementJS + switch (this.step) { + case 5: + case 2: + clone.setHours(Math.round(clone.getHours() / 24) * 24); break; + default: + clone.setHours(Math.round(clone.getHours() / 12) * 12); break; + } + clone.setMinutes(0); + clone.setSeconds(0); + clone.setMilliseconds(0); + } + else if (this.scale == TimeStep.SCALE.WEEKDAY) { + //noinspection FallthroughInSwitchStatementJS + switch (this.step) { + case 5: + case 2: + clone.setHours(Math.round(clone.getHours() / 12) * 12); break; + default: + clone.setHours(Math.round(clone.getHours() / 6) * 6); break; + } + clone.setMinutes(0); + clone.setSeconds(0); + clone.setMilliseconds(0); + } + else if (this.scale == TimeStep.SCALE.HOUR) { + switch (this.step) { + case 4: + clone.setMinutes(Math.round(clone.getMinutes() / 60) * 60); break; + default: + clone.setMinutes(Math.round(clone.getMinutes() / 30) * 30); break; + } + clone.setSeconds(0); + clone.setMilliseconds(0); + } else if (this.scale == TimeStep.SCALE.MINUTE) { + //noinspection FallthroughInSwitchStatementJS + switch (this.step) { + case 15: + case 10: + clone.setMinutes(Math.round(clone.getMinutes() / 5) * 5); + clone.setSeconds(0); + break; + case 5: + clone.setSeconds(Math.round(clone.getSeconds() / 60) * 60); break; + default: + clone.setSeconds(Math.round(clone.getSeconds() / 30) * 30); break; + } + clone.setMilliseconds(0); + } + else if (this.scale == TimeStep.SCALE.SECOND) { + //noinspection FallthroughInSwitchStatementJS + switch (this.step) { + case 15: + case 10: + clone.setSeconds(Math.round(clone.getSeconds() / 5) * 5); + clone.setMilliseconds(0); + break; + case 5: + clone.setMilliseconds(Math.round(clone.getMilliseconds() / 1000) * 1000); break; + default: + clone.setMilliseconds(Math.round(clone.getMilliseconds() / 500) * 500); break; + } + } + else if (this.scale == TimeStep.SCALE.MILLISECOND) { + var step = this.step > 5 ? this.step / 2 : 1; + clone.setMilliseconds(Math.round(clone.getMilliseconds() / step) * step); + } + + return clone; }; /** - * Toggle start or stop playing + * Check if the current value is a major value (for example when the step + * is DAY, a major value is each first day of the MONTH) + * @return {boolean} true if current date is major, else false. */ - Slider.prototype.togglePlay = function() { - if (this.playTimeout === undefined) { - this.play(); - } else { - this.stop(); + TimeStep.prototype.isMajor = function() { + switch (this.scale) { + case TimeStep.SCALE.MILLISECOND: + return (this.current.getMilliseconds() == 0); + case TimeStep.SCALE.SECOND: + return (this.current.getSeconds() == 0); + case TimeStep.SCALE.MINUTE: + return (this.current.getHours() == 0) && (this.current.getMinutes() == 0); + // Note: this is no bug. Major label is equal for both minute and hour scale + case TimeStep.SCALE.HOUR: + return (this.current.getHours() == 0); + case TimeStep.SCALE.WEEKDAY: // intentional fall through + case TimeStep.SCALE.DAY: + return (this.current.getDate() == 1); + case TimeStep.SCALE.MONTH: + return (this.current.getMonth() == 0); + case TimeStep.SCALE.YEAR: + return false; + default: + return false; } }; + /** - * Start playing + * Returns formatted text for the minor axislabel, depending on the current + * date and the scale. For example when scale is MINUTE, the current time is + * formatted as "hh:mm". + * @param {Date} [date] custom date. if not provided, current date is taken */ - Slider.prototype.play = function() { - // Test whether already playing - if (this.playTimeout) return; - - this.playNext(); + TimeStep.prototype.getLabelMinor = function(date) { + if (date == undefined) { + date = this.current; + } - if (this.frame) { - this.frame.play.value = 'Stop'; + switch (this.scale) { + case TimeStep.SCALE.MILLISECOND: return moment(date).format('SSS'); + case TimeStep.SCALE.SECOND: return moment(date).format('s'); + case TimeStep.SCALE.MINUTE: return moment(date).format('HH:mm'); + case TimeStep.SCALE.HOUR: return moment(date).format('HH:mm'); + case TimeStep.SCALE.WEEKDAY: return moment(date).format('ddd D'); + case TimeStep.SCALE.DAY: return moment(date).format('D'); + case TimeStep.SCALE.MONTH: return moment(date).format('MMM'); + case TimeStep.SCALE.YEAR: return moment(date).format('YYYY'); + default: return ''; } }; + /** - * Stop playing + * Returns formatted text for the major axis label, depending on the current + * date and the scale. For example when scale is MINUTE, the major scale is + * hours, and the hour will be formatted as "hh". + * @param {Date} [date] custom date. if not provided, current date is taken */ - Slider.prototype.stop = function() { - clearInterval(this.playTimeout); - this.playTimeout = undefined; - - if (this.frame) { - this.frame.play.value = 'Play'; + TimeStep.prototype.getLabelMajor = function(date) { + if (date == undefined) { + date = this.current; } - }; - /** - * Set a callback function which will be triggered when the value of the - * slider bar has changed. - */ - Slider.prototype.setOnChangeCallback = function(callback) { - this.onChangeCallback = callback; + //noinspection FallthroughInSwitchStatementJS + switch (this.scale) { + case TimeStep.SCALE.MILLISECOND:return moment(date).format('HH:mm:ss'); + case TimeStep.SCALE.SECOND: return moment(date).format('D MMMM HH:mm'); + case TimeStep.SCALE.MINUTE: + case TimeStep.SCALE.HOUR: return moment(date).format('ddd D MMMM'); + case TimeStep.SCALE.WEEKDAY: + case TimeStep.SCALE.DAY: return moment(date).format('MMMM YYYY'); + case TimeStep.SCALE.MONTH: return moment(date).format('YYYY'); + case TimeStep.SCALE.YEAR: return ''; + default: return ''; + } }; + module.exports = TimeStep; + + +/***/ }, +/* 18 */ +/***/ function(module, exports, __webpack_require__) { + /** - * Set the interval for playing the list - * @param {Number} interval The interval in milliseconds + * Prototype for visual components + * @param {{dom: Object, domProps: Object, emitter: Emitter, range: Range}} [body] + * @param {Object} [options] */ - Slider.prototype.setPlayInterval = function(interval) { - this.playInterval = interval; - }; + function Component (body, options) { + this.options = null; + this.props = null; + } /** - * Retrieve the current play interval - * @return {Number} interval The interval in milliseconds + * Set options for the component. The new options will be merged into the + * current options. + * @param {Object} options */ - Slider.prototype.getPlayInterval = function(interval) { - return this.playInterval; + Component.prototype.setOptions = function(options) { + if (options) { + util.extend(this.options, options); + } }; /** - * Set looping on or off - * @pararm {boolean} doLoop If true, the slider will jump to the start when - * the end is passed, and will jump to the end - * when the start is passed. + * Repaint the component + * @return {boolean} Returns true if the component is resized */ - Slider.prototype.setPlayLoop = function(doLoop) { - this.playLoop = doLoop; + Component.prototype.redraw = function() { + // should be implemented by the component + return false; }; - /** - * Execute the onchange callback function + * Destroy the component. Cleanup DOM and event listeners */ - Slider.prototype.onChange = function() { - if (this.onChangeCallback !== undefined) { - this.onChangeCallback(); - } + Component.prototype.destroy = function() { + // should be implemented by the component }; /** - * redraw the slider on the correct place + * Test whether the component is resized since the last time _isResized() was + * called. + * @return {Boolean} Returns true if the component is resized + * @protected */ - Slider.prototype.redraw = function() { - if (this.frame) { - // resize the bar - this.frame.bar.style.top = (this.frame.clientHeight/2 - - this.frame.bar.offsetHeight/2) + 'px'; - this.frame.bar.style.width = (this.frame.clientWidth - - this.frame.prev.clientWidth - - this.frame.play.clientWidth - - this.frame.next.clientWidth - 30) + 'px'; + Component.prototype._isResized = function() { + var resized = (this.props._previousWidth !== this.props.width || + this.props._previousHeight !== this.props.height); - // position the slider button - var left = this.indexToLeft(this.index); - this.frame.slide.style.left = (left) + 'px'; - } + this.props._previousWidth = this.props.width; + this.props._previousHeight = this.props.height; + + return resized; }; + module.exports = Component; + + +/***/ }, +/* 19 */ +/***/ function(module, exports, __webpack_require__) { + + var util = __webpack_require__(1); + var Component = __webpack_require__(18); /** - * Set the list with values for the slider - * @param {Array} values A javascript array with values (any type) + * A current time bar + * @param {{range: Range, dom: Object, domProps: Object}} body + * @param {Object} [options] Available parameters: + * {Boolean} [showCurrentTime] + * @constructor CurrentTime + * @extends Component */ - Slider.prototype.setValues = function(values) { - this.values = values; + function CurrentTime (body, options) { + this.body = body; - if (this.values.length > 0) - this.setIndex(0); - else - this.index = undefined; - }; + // default options + this.defaultOptions = { + showCurrentTime: true + }; + this.options = util.extend({}, this.defaultOptions); + + this._create(); + + this.setOptions(options); + } + + CurrentTime.prototype = new Component(); /** - * Select a value by its index - * @param {Number} index + * Create the HTML DOM for the current time bar + * @private */ - Slider.prototype.setIndex = function(index) { - if (index < this.values.length) { - this.index = index; + CurrentTime.prototype._create = function() { + var bar = document.createElement('div'); + bar.className = 'currenttime'; + bar.style.position = 'absolute'; + bar.style.top = '0px'; + bar.style.height = '100%'; - this.redraw(); - this.onChange(); - } - else { - throw 'Error: index out of range'; - } + this.bar = bar; }; /** - * retrieve the index of the currently selected vaue - * @return {Number} index + * Destroy the CurrentTime bar */ - Slider.prototype.getIndex = function() { - return this.index; - }; + CurrentTime.prototype.destroy = function () { + this.options.showCurrentTime = false; + this.redraw(); // will remove the bar from the DOM and stop refreshing + this.body = null; + }; /** - * retrieve the currently selected value - * @return {*} value + * Set options for the component. Options will be merged in current options. + * @param {Object} options Available parameters: + * {boolean} [showCurrentTime] */ - Slider.prototype.get = function() { - return this.values[this.index]; + CurrentTime.prototype.setOptions = function(options) { + if (options) { + // copy all options that we know + util.selectiveExtend(['showCurrentTime'], this.options, options); + } }; + /** + * Repaint the component + * @return {boolean} Returns true if the component is resized + */ + CurrentTime.prototype.redraw = function() { + if (this.options.showCurrentTime) { + 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); - Slider.prototype._onMouseDown = function(event) { - // only react on left mouse button down - var leftButtonDown = event.which ? (event.which === 1) : (event.button === 1); - if (!leftButtonDown) return; + this.start(); + } - this.startClientX = event.clientX; - this.startSlideX = parseFloat(this.frame.slide.style.left); + var now = new Date(); + var x = this.body.util.toScreen(now); - this.frame.style.cursor = 'move'; + this.bar.style.left = x + 'px'; + this.bar.title = 'Current time: ' + now; + } + else { + // remove the line from the DOM + if (this.bar.parentNode) { + this.bar.parentNode.removeChild(this.bar); + } + this.stop(); + } - // add event listeners to handle moving the contents - // we store the function onmousemove and onmouseup in the graph, so we can - // remove the eventlisteners lateron in the function mouseUp() - var me = this; - this.onmousemove = function (event) {me._onMouseMove(event);}; - this.onmouseup = function (event) {me._onMouseUp(event);}; - util.addEventListener(document, 'mousemove', this.onmousemove); - util.addEventListener(document, 'mouseup', this.onmouseup); - util.preventDefault(event); + return false; }; + /** + * Start auto refreshing the current time bar + */ + CurrentTime.prototype.start = function() { + var me = this; - Slider.prototype.leftToIndex = function (left) { - var width = parseFloat(this.frame.bar.style.width) - - this.frame.slide.clientWidth - 10; - var x = left - 3; + function update () { + me.stop(); - var index = Math.round(x / width * (this.values.length-1)); - if (index < 0) index = 0; - if (index > this.values.length-1) index = this.values.length-1; + // determine interval to refresh + var scale = me.body.range.conversion(me.body.domProps.center.width).scale; + var interval = 1 / scale / 10; + if (interval < 30) interval = 30; + if (interval > 1000) interval = 1000; - return index; - }; + me.redraw(); - Slider.prototype.indexToLeft = function (index) { - var width = parseFloat(this.frame.bar.style.width) - - this.frame.slide.clientWidth - 10; + // start a timer to adjust for the new time + me.currentTimeTimer = setTimeout(update, interval); + } - var x = index / (this.values.length-1) * width; - var left = x + 3; + update(); + }; - return left; + /** + * Stop auto refreshing the current time bar + */ + CurrentTime.prototype.stop = function() { + if (this.currentTimeTimer !== undefined) { + clearTimeout(this.currentTimeTimer); + delete this.currentTimeTimer; + } }; + module.exports = CurrentTime; - Slider.prototype._onMouseMove = function (event) { - var diff = event.clientX - this.startClientX; - var x = this.startSlideX + diff; - - var index = this.leftToIndex(x); - - this.setIndex(index); +/***/ }, +/* 20 */ +/***/ function(module, exports, __webpack_require__) { - util.preventDefault(); - }; + var Hammer = __webpack_require__(41); + var util = __webpack_require__(1); + var Component = __webpack_require__(18); + /** + * A custom time bar + * @param {{range: Range, dom: Object}} body + * @param {Object} [options] Available parameters: + * {Boolean} [showCustomTime] + * @constructor CustomTime + * @extends Component + */ - Slider.prototype._onMouseUp = function (event) { - this.frame.style.cursor = 'auto'; + function CustomTime (body, options) { + this.body = body; - // remove event listeners - util.removeEventListener(document, 'mousemove', this.onmousemove); - util.removeEventListener(document, 'mouseup', this.onmouseup); + // default options + this.defaultOptions = { + showCustomTime: false + }; + this.options = util.extend({}, this.defaultOptions); - util.preventDefault(); - }; + this.customTime = new Date(); + this.eventParams = {}; // stores state parameters while dragging the bar - module.exports = Slider; + // create the DOM + this._create(); + this.setOptions(options); + } -/***/ }, -/* 16 */ -/***/ function(module, exports, __webpack_require__) { + CustomTime.prototype = new Component(); /** - * @prototype StepNumber - * The class StepNumber is an iterator for Numbers. You provide a start and end - * value, and a best step size. StepNumber itself rounds to fixed values and - * a finds the step that best fits the provided step. - * - * If prettyStep is true, the step size is chosen as close as possible to the - * provided step, but being a round value like 1, 2, 5, 10, 20, 50, .... - * - * Example usage: - * var step = new StepNumber(0, 10, 2.5, true); - * step.start(); - * while (!step.end()) { - * alert(step.getCurrent()); - * step.next(); - * } - * - * Version: 1.0 - * - * @param {Number} start The start value - * @param {Number} end The end value - * @param {Number} step Optional. Step size. Must be a positive value. - * @param {boolean} prettyStep Optional. If true, the step size is rounded - * To a pretty step size (like 1, 2, 5, 10, 20, 50, ...) + * Set options for the component. Options will be merged in current options. + * @param {Object} options Available parameters: + * {boolean} [showCustomTime] */ - function StepNumber(start, end, step, prettyStep) { - // set default values - this._start = 0; - this._end = 0; - this._step = 1; - this.prettyStep = true; - this.precision = 5; - - this._current = 0; - this.setRange(start, end, step, prettyStep); + CustomTime.prototype.setOptions = function(options) { + if (options) { + // copy all options that we know + util.selectiveExtend(['showCustomTime'], this.options, options); + } }; /** - * Set a new range: start, end and step. - * - * @param {Number} start The start value - * @param {Number} end The end value - * @param {Number} step Optional. Step size. Must be a positive value. - * @param {boolean} prettyStep Optional. If true, the step size is rounded - * To a pretty step size (like 1, 2, 5, 10, 20, 50, ...) + * Create the DOM for the custom time + * @private */ - StepNumber.prototype.setRange = function(start, end, step, prettyStep) { - this._start = start ? start : 0; - this._end = end ? end : 0; + CustomTime.prototype._create = function() { + var bar = document.createElement('div'); + bar.className = 'customtime'; + bar.style.position = 'absolute'; + bar.style.top = '0px'; + bar.style.height = '100%'; + this.bar = bar; - this.setStep(step, prettyStep); + 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 = Hammer(bar, { + prevent_default: true + }); + this.hammer.on('dragstart', this._onDragStart.bind(this)); + this.hammer.on('drag', this._onDrag.bind(this)); + this.hammer.on('dragend', this._onDragEnd.bind(this)); }; /** - * Set a new step size - * @param {Number} step New step size. Must be a positive value - * @param {boolean} prettyStep Optional. If true, the provided step is rounded - * to a pretty step size (like 1, 2, 5, 10, 20, 50, ...) + * Destroy the CustomTime bar */ - StepNumber.prototype.setStep = function(step, prettyStep) { - if (step === undefined || step <= 0) - return; + CustomTime.prototype.destroy = function () { + this.options.showCustomTime = false; + this.redraw(); // will remove the bar from the DOM - if (prettyStep !== undefined) - this.prettyStep = prettyStep; + this.hammer.enable(false); + this.hammer = null; - if (this.prettyStep === true) - this._step = StepNumber.calculatePrettyStep(step); - else - this._step = step; + this.body = null; }; /** - * Calculate a nice step size, closest to the desired step size. - * Returns a value in one of the ranges 1*10^n, 2*10^n, or 5*10^n, where n is an - * integer Number. For example 1, 2, 5, 10, 20, 50, etc... - * @param {Number} step Desired step size - * @return {Number} Nice step size + * Repaint the component + * @return {boolean} Returns true if the component is resized */ - StepNumber.calculatePrettyStep = function (step) { - var log10 = function (x) {return Math.log(x) / Math.LN10;}; - - // try three steps (multiple of 1, 2, or 5 - var step1 = Math.pow(10, Math.round(log10(step))), - step2 = 2 * Math.pow(10, Math.round(log10(step / 2))), - step5 = 5 * Math.pow(10, Math.round(log10(step / 5))); + CustomTime.prototype.redraw = function () { + if (this.options.showCustomTime) { + 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); + } - // choose the best step (closest to minimum step) - var prettyStep = step1; - if (Math.abs(step2 - step) <= Math.abs(prettyStep - step)) prettyStep = step2; - if (Math.abs(step5 - step) <= Math.abs(prettyStep - step)) prettyStep = step5; + var x = this.body.util.toScreen(this.customTime); - // for safety - if (prettyStep <= 0) { - prettyStep = 1; + this.bar.style.left = x + 'px'; + this.bar.title = 'Time: ' + this.customTime; + } + else { + // remove the line from the DOM + if (this.bar.parentNode) { + this.bar.parentNode.removeChild(this.bar); + } } - return prettyStep; + return false; }; /** - * returns the current value of the step - * @return {Number} current value + * Set custom time. + * @param {Date} time */ - StepNumber.prototype.getCurrent = function () { - return parseFloat(this._current.toPrecision(this.precision)); + CustomTime.prototype.setCustomTime = function(time) { + this.customTime = new Date(time.valueOf()); + this.redraw(); }; /** - * returns the current step size - * @return {Number} current step size + * Retrieve the current custom time. + * @return {Date} customTime */ - StepNumber.prototype.getStep = function () { - return this._step; + CustomTime.prototype.getCustomTime = function() { + return new Date(this.customTime.valueOf()); }; /** - * Set the current value to the largest value smaller than start, which - * is a multiple of the step size + * Start moving horizontally + * @param {Event} event + * @private */ - StepNumber.prototype.start = function() { - this._current = this._start - this._start % this._step; + CustomTime.prototype._onDragStart = function(event) { + this.eventParams.dragging = true; + this.eventParams.customTime = this.customTime; + + event.stopPropagation(); + event.preventDefault(); }; /** - * Do a step, add the step size to the current value + * Perform moving operating. + * @param {Event} event + * @private */ - StepNumber.prototype.next = function () { - this._current += this._step; + CustomTime.prototype._onDrag = function (event) { + if (!this.eventParams.dragging) return; + + var deltaX = event.gesture.deltaX, + x = this.body.util.toScreen(this.eventParams.customTime) + deltaX, + time = this.body.util.toTime(x); + + this.setCustomTime(time); + + // fire a timechange event + this.body.emitter.emit('timechange', { + time: new Date(this.customTime.valueOf()) + }); + + event.stopPropagation(); + event.preventDefault(); }; /** - * Returns true whether the end is reached - * @return {boolean} True if the current value has passed the end value. + * Stop moving operating. + * @param {event} event + * @private */ - StepNumber.prototype.end = function () { - return (this._current > this._end); + CustomTime.prototype._onDragEnd = function (event) { + if (!this.eventParams.dragging) return; + + // fire a timechanged event + this.body.emitter.emit('timechanged', { + time: new Date(this.customTime.valueOf()) + }); + + event.stopPropagation(); + event.preventDefault(); }; - module.exports = StepNumber; + module.exports = CustomTime; /***/ }, -/* 17 */ +/* 21 */ /***/ function(module, exports, __webpack_require__) { - var Emitter = __webpack_require__(10); - var Hammer = __webpack_require__(18); var util = __webpack_require__(1); - var DataSet = __webpack_require__(7); - var DataView = __webpack_require__(8); - var Range = __webpack_require__(20); - var Core = __webpack_require__(23); - var TimeAxis = __webpack_require__(24); - var CurrentTime = __webpack_require__(26); - var CustomTime = __webpack_require__(27); - var ItemSet = __webpack_require__(28); + var DOMutil = __webpack_require__(2); + var Component = __webpack_require__(18); + var DataStep = __webpack_require__(14); /** - * Create a timeline visualization - * @param {HTMLElement} container - * @param {vis.DataSet | Array | google.visualization.DataTable} [items] - * @param {Object} [options] See Timeline.setOptions for the available options. - * @constructor + * A horizontal time axis + * @param {Object} [options] See DataAxis.setOptions for the available + * options. + * @constructor DataAxis + * @extends Component + * @param body */ - function Timeline (container, items, options) { - // mix the core properties in here - for (var coreProp in Core.prototype) { - if (Core.prototype.hasOwnProperty(coreProp) && !Timeline.prototype.hasOwnProperty(coreProp)) { - Timeline.prototype[coreProp] = Core.prototype[coreProp]; - } - } - - if (!(this instanceof Timeline)) { - throw new SyntaxError('Constructor must be called with the new operator'); - } + function DataAxis (body, options, svg) { + this.id = util.randomUUID(); + this.body = body; - var me = this; this.defaultOptions = { - start: null, - end: null, - - autoResize: true, - - orientation: 'bottom', - width: null, - height: null, - maxHeight: null, - minHeight: null + orientation: 'left', // supported: 'left', 'right' + showMinorLabels: true, + showMajorLabels: true, + icons: true, + majorLinesOffset: 7, + minorLinesOffset: 4, + labelOffsetX: 10, + labelOffsetY: 2, + iconWidth: 20, + width: '40px', + visible: true }; - this.options = util.deepExtend({}, this.defaultOptions); - // Create the DOM, props, and emitter - this._create(container); - - // all components listed here will be repainted automatically - this.components = []; - - this.body = { - dom: this.dom, - domProps: this.props, - emitter: { - on: this.on.bind(this), - off: this.off.bind(this), - emit: this.emit.bind(this) - }, - util: { - snap: null, // will be specified after TimeAxis is created - toScreen: me._toScreen.bind(me), - toGlobalScreen: me._toGlobalScreen.bind(me), // this refers to the root.width - toTime: me._toTime.bind(me), - toGlobalTime : me._toGlobalTime.bind(me) - } + this.linegraphSVG = svg; + this.props = {}; + this.DOMelements = { // dynamic elements + lines: {}, + labels: {} }; - // range - this.range = new Range(this.body); - this.components.push(this.range); - this.body.range = this.range; + this.dom = {}; - // time axis - this.timeAxis = new TimeAxis(this.body); - this.components.push(this.timeAxis); - this.body.util.snap = this.timeAxis.snap.bind(this.timeAxis); + this.range = {start:0, end:0}; - // current time bar - this.currentTime = new CurrentTime(this.body); - this.components.push(this.currentTime); + this.options = util.extend({}, this.defaultOptions); + this.conversionFactor = 1; - // custom time bar - // Note: time bar will be attached in this.setOptions when selected - this.customTime = new CustomTime(this.body); - this.components.push(this.customTime); + this.setOptions(options); + this.width = Number(('' + this.options.width).replace("px","")); + this.minWidth = this.width; + this.height = this.linegraphSVG.offsetHeight; - // item set - this.itemSet = new ItemSet(this.body); - this.components.push(this.itemSet); + this.stepPixels = 25; + this.stepPixelsForced = 25; + this.lineOffset = 0; + this.master = true; + this.svgElements = {}; - this.itemsData = null; // DataSet - this.groupsData = null; // DataSet - // apply options - if (options) { - this.setOptions(options); - } + this.groups = {}; + this.amountOfGroups = 0; - // create itemset - if (items) { - this.setItems(items); - } - else { - this.redraw(); - } + // create the HTML DOM + this._create(); } - /** - * Set options. Options will be passed to all components loaded in the Timeline. - * @param {Object} [options] - * {String} orientation - * Vertical orientation for the Timeline, - * can be 'bottom' (default) or 'top'. - * {String | Number} width - * Width for the timeline, a number in pixels or - * a css string like '1000px' or '75%'. '100%' by default. - * {String | Number} height - * Fixed height for the Timeline, a number in pixels or - * a css string like '400px' or '75%'. If undefined, - * The Timeline will automatically size such that - * its contents fit. - * {String | Number} minHeight - * Minimum height for the Timeline, a number in pixels or - * a css string like '400px' or '75%'. - * {String | Number} maxHeight - * Maximum height for the Timeline, a number in pixels or - * a css string like '400px' or '75%'. - * {Number | Date | String} start - * Start date for the visible window - * {Number | Date | String} end - * End date for the visible window - */ - Timeline.prototype.setOptions = function (options) { - if (options) { - // copy the known options - var fields = ['width', 'height', 'minHeight', 'maxHeight', 'autoResize', 'start', 'end', 'orientation']; - util.selectiveExtend(fields, this.options, options); + DataAxis.prototype = new Component(); - // enable/disable autoResize - this._initAutoResize(); - } - // propagate options to all components - this.components.forEach(function (component) { - component.setOptions(options); - }); - // TODO: remove deprecation error one day (deprecated since version 0.8.0) - if (options && options.order) { - throw new Error('Option order is deprecated. There is no replacement for this feature.'); + DataAxis.prototype.addGroup = function(label, graphOptions) { + if (!this.groups.hasOwnProperty(label)) { + this.groups[label] = graphOptions; } - - // redraw everything - this.redraw(); + this.amountOfGroups += 1; }; - /** - * Set items - * @param {vis.DataSet | Array | google.visualization.DataTable | null} items - */ - Timeline.prototype.setItems = function(items) { - var initialLoad = (this.itemsData == null); + DataAxis.prototype.updateGroup = function(label, graphOptions) { + this.groups[label] = graphOptions; + }; - // convert to type DataSet when needed - var newDataSet; - if (!items) { - newDataSet = null; - } - else if (items instanceof DataSet || items instanceof DataView) { - newDataSet = items; - } - else { - // turn an array into a dataset - newDataSet = new DataSet(items, { - type: { - start: 'Date', - end: 'Date' - } - }); + DataAxis.prototype.removeGroup = function(label) { + if (this.groups.hasOwnProperty(label)) { + delete this.groups[label]; + this.amountOfGroups -= 1; } + }; - // set items - this.itemsData = newDataSet; - this.itemSet && this.itemSet.setItems(newDataSet); - if (initialLoad && ('start' in this.options || 'end' in this.options)) { - this.fit(); + DataAxis.prototype.setOptions = function (options) { + if (options) { + var redraw = false; + if (this.options.orientation != options.orientation && options.orientation !== undefined) { + redraw = true; + } + var fields = [ + 'orientation', + 'showMinorLabels', + 'showMajorLabels', + 'icons', + 'majorLinesOffset', + 'minorLinesOffset', + 'labelOffsetX', + 'labelOffsetY', + 'iconWidth', + 'width', + 'visible']; + util.selectiveExtend(fields, this.options, options); - var start = ('start' in this.options) ? util.convert(this.options.start, 'Date') : null; - var end = ('end' in this.options) ? util.convert(this.options.end, 'Date') : null; + this.minWidth = Number(('' + this.options.width).replace("px","")); - this.setWindow(start, end); + if (redraw == true && this.dom.frame) { + this.hide(); + this.show(); + } } }; + /** - * Set groups - * @param {vis.DataSet | Array | google.visualization.DataTable} groups + * Create the HTML DOM for the DataAxis */ - Timeline.prototype.setGroups = function(groups) { - // convert to type DataSet when needed - var newDataSet; - if (!groups) { - newDataSet = null; - } - else if (groups instanceof DataSet || groups instanceof DataView) { - newDataSet = groups; - } - else { - // turn an array into a dataset - newDataSet = new DataSet(groups); - } + DataAxis.prototype._create = function() { + this.dom.frame = document.createElement('div'); + this.dom.frame.style.width = this.options.width; + this.dom.frame.style.height = this.height; - this.groupsData = newDataSet; - this.itemSet.setGroups(newDataSet); - }; - - /** - * Set selected items by their id. Replaces the current selection - * Unknown id's are silently ignored. - * @param {Array} [ids] An array with zero or more id's of the items to be - * selected. If ids is an empty array, all items will be - * unselected. - */ - Timeline.prototype.setSelection = function(ids) { - this.itemSet && this.itemSet.setSelection(ids); - }; + this.dom.lineContainer = document.createElement('div'); + this.dom.lineContainer.style.width = '100%'; + this.dom.lineContainer.style.height = this.height; - /** - * Get the selected items by their id - * @return {Array} ids The ids of the selected items - */ - Timeline.prototype.getSelection = function() { - return this.itemSet && this.itemSet.getSelection() || []; + // create svg element for graph drawing. + this.svg = document.createElementNS('http://www.w3.org/2000/svg',"svg"); + this.svg.style.position = "absolute"; + this.svg.style.top = '0px'; + this.svg.style.height = '100%'; + this.svg.style.width = '100%'; + this.svg.style.display = "block"; + this.dom.frame.appendChild(this.svg); }; + DataAxis.prototype._redrawGroupIcons = function () { + DOMutil.prepareElements(this.svgElements); - /** - * Get the data range of the item set. - * @returns {{min: Date, max: Date}} range A range with a start and end Date. - * When no minimum is found, min==null - * When no maximum is found, max==null - */ - Timeline.prototype.getItemRange = function() { - // calculate min from start filed - var dataset = this.itemsData.getDataSet(), - min = null, - max = null; + var x; + var iconWidth = this.options.iconWidth; + var iconHeight = 15; + var iconOffset = 4; + var y = iconOffset + 0.5 * iconHeight; - if (dataset) { - // calculate the minimum value of the field 'start' - var minItem = dataset.min('start'); - min = minItem ? util.convert(minItem.start, 'Date').valueOf() : null; - // Note: we convert first to Date and then to number because else - // a conversion from ISODate to Number will fail + if (this.options.orientation == 'left') { + x = iconOffset; + } + else { + x = this.width - iconWidth - iconOffset; + } - // calculate maximum value of fields 'start' and 'end' - var maxStartItem = dataset.max('start'); - if (maxStartItem) { - max = util.convert(maxStartItem.start, 'Date').valueOf(); - } - var maxEndItem = dataset.max('end'); - if (maxEndItem) { - if (max == null) { - max = util.convert(maxEndItem.end, 'Date').valueOf(); - } - else { - max = Math.max(max, util.convert(maxEndItem.end, 'Date').valueOf()); + for (var groupId in this.groups) { + if (this.groups.hasOwnProperty(groupId)) { + if (this.groups[groupId].visible == true) { + this.groups[groupId].drawIcon(x, y, this.svgElements, this.svg, iconWidth, iconHeight); + y += iconHeight + iconOffset; } } } - return { - min: (min != null) ? new Date(min) : null, - max: (max != null) ? new Date(max) : null - }; + DOMutil.cleanupElements(this.svgElements); }; - - module.exports = Timeline; - - -/***/ }, -/* 18 */ -/***/ function(module, exports, __webpack_require__) { - - // Only load hammer.js when in a browser environment - // (loading hammer.js in a node.js environment gives errors) - if (typeof window !== 'undefined') { - module.exports = window['Hammer'] || __webpack_require__(19); - } - else { - module.exports = function () { - throw Error('hammer.js is only available in a browser, not in node.js.'); + /** + * Create the HTML DOM for the DataAxis + */ + DataAxis.prototype.show = function() { + if (!this.dom.frame.parentNode) { + if (this.options.orientation == 'left') { + this.body.dom.left.appendChild(this.dom.frame); + } + else { + this.body.dom.right.appendChild(this.dom.frame); + } } - } - - -/***/ }, -/* 19 */ -/***/ function(module, exports, __webpack_require__) { - var __WEBPACK_AMD_DEFINE_RESULT__;/*! Hammer.JS - v1.1.3 - 2014-05-20 - * http://eightmedia.github.io/hammer.js - * - * Copyright (c) 2014 Jorik Tangelder ; - * Licensed under the MIT license */ - - (function(window, undefined) { - 'use strict'; + if (!this.dom.lineContainer.parentNode) { + this.body.dom.backgroundHorizontal.appendChild(this.dom.lineContainer); + } + }; /** - * @main - * @module hammer - * - * @class Hammer - * @static + * Create the HTML DOM for the DataAxis */ + DataAxis.prototype.hide = function() { + if (this.dom.frame.parentNode) { + this.dom.frame.parentNode.removeChild(this.dom.frame); + } - /** - * Hammer, use this to create instances - * ```` - * var hammertime = new Hammer(myElement); - * ```` - * - * @method Hammer - * @param {HTMLElement} element - * @param {Object} [options={}] - * @return {Hammer.Instance} - */ - var Hammer = function Hammer(element, options) { - return new Hammer.Instance(element, options || {}); + if (this.dom.lineContainer.parentNode) { + this.dom.lineContainer.parentNode.removeChild(this.dom.lineContainer); + } }; /** - * version, as defined in package.json - * the value will be set at each build - * @property VERSION - * @final - * @type {String} + * Set a range (start and end) + * @param end + * @param start + * @param end */ - Hammer.VERSION = '1.1.3'; + DataAxis.prototype.setRange = function (start, end) { + this.range.start = start; + this.range.end = end; + }; /** - * default settings. - * more settings are defined per gesture at `/gestures`. Each gesture can be disabled/enabled - * by setting it's name (like `swipe`) to false. - * You can set the defaults for all instances by changing this object before creating an instance. - * @example - * ```` - * Hammer.defaults.drag = false; - * Hammer.defaults.behavior.touchAction = 'pan-y'; - * delete Hammer.defaults.behavior.userSelect; - * ```` - * @property defaults - * @type {Object} + * Repaint the component + * @return {boolean} Returns true if the component is resized */ - Hammer.defaults = { - /** - * this setting object adds styles and attributes to the element to prevent the browser from doing - * its native behavior. The css properties are auto prefixed for the browsers when needed. - * @property defaults.behavior - * @type {Object} - */ - behavior: { - /** - * Disables text selection to improve the dragging gesture. When the value is `none` it also sets - * `onselectstart=false` for IE on the element. Mainly for desktop browsers. - * @property defaults.behavior.userSelect - * @type {String} - * @default 'none' - */ - userSelect: 'none', + DataAxis.prototype.redraw = function () { + var changeCalled = false; + var activeGroups = 0; + for (var groupId in this.groups) { + if (this.groups.hasOwnProperty(groupId)) { + if (this.groups[groupId].visible == true) { + activeGroups++; + } + } + } + if (this.amountOfGroups == 0 || activeGroups == 0) { + this.hide(); + } + else { + this.show(); + this.height = Number(this.linegraphSVG.style.height.replace("px","")); + // svg offsetheight did not work in firefox and explorer... - /** - * Specifies whether and how a given region can be manipulated by the user (for instance, by panning or zooming). - * Used by Chrome 35> and IE10>. By default this makes the element blocking any touch event. - * @property defaults.behavior.touchAction - * @type {String} - * @default: 'pan-y' - */ - touchAction: 'pan-y', + this.dom.lineContainer.style.height = this.height + 'px'; + this.width = this.options.visible == true ? Number(('' + this.options.width).replace("px","")) : 0; - /** - * Disables the default callout shown when you touch and hold a touch target. - * On iOS, when you touch and hold a touch target such as a link, Safari displays - * a callout containing information about the link. This property allows you to disable that callout. - * @property defaults.behavior.touchCallout - * @type {String} - * @default 'none' - */ - touchCallout: 'none', + var props = this.props; + var frame = this.dom.frame; - /** - * Specifies whether zooming is enabled. Used by IE10> - * @property defaults.behavior.contentZooming - * @type {String} - * @default 'none' - */ - contentZooming: 'none', + // update classname + frame.className = 'dataaxis'; - /** - * Specifies that an entire element should be draggable instead of its contents. - * Mainly for desktop browsers. - * @property defaults.behavior.userDrag - * @type {String} - * @default 'none' - */ - userDrag: 'none', + // calculate character width and height + this._calculateCharSize(); - /** - * Overrides the highlight color shown when the user taps a link or a JavaScript - * clickable element in Safari on iPhone. This property obeys the alpha value, if specified. - * - * If you don't specify an alpha value, Safari on iPhone applies a default alpha value - * to the color. To disable tap highlighting, set the alpha value to 0 (invisible). - * If you set the alpha value to 1.0 (opaque), the element is not visible when tapped. - * @property defaults.behavior.tapHighlightColor - * @type {String} - * @default 'rgba(0,0,0,0)' - */ - tapHighlightColor: 'rgba(0,0,0,0)' - } - }; + var orientation = this.options.orientation; + var showMinorLabels = this.options.showMinorLabels; + var showMajorLabels = this.options.showMajorLabels; - /** - * hammer document where the base events are added at - * @property DOCUMENT - * @type {HTMLElement} - * @default window.document - */ - Hammer.DOCUMENT = document; + // determine the width and height of the elemens for the axis + props.minorLabelHeight = showMinorLabels ? props.minorCharHeight : 0; + props.majorLabelHeight = showMajorLabels ? props.majorCharHeight : 0; - /** - * detect support for pointer events - * @property HAS_POINTEREVENTS - * @type {Boolean} - */ - Hammer.HAS_POINTEREVENTS = navigator.pointerEnabled || navigator.msPointerEnabled; + props.minorLineWidth = this.body.dom.backgroundHorizontal.offsetWidth - this.lineOffset - this.width + 2 * this.options.minorLinesOffset; + props.minorLineHeight = 1; + props.majorLineWidth = this.body.dom.backgroundHorizontal.offsetWidth - this.lineOffset - this.width + 2 * this.options.majorLinesOffset; + props.majorLineHeight = 1; - /** - * detect support for touch events - * @property HAS_TOUCHEVENTS - * @type {Boolean} - */ - Hammer.HAS_TOUCHEVENTS = ('ontouchstart' in window); + // take frame offline while updating (is almost twice as fast) + if (orientation == 'left') { + frame.style.top = '0'; + frame.style.left = '0'; + frame.style.bottom = ''; + frame.style.width = this.width + 'px'; + frame.style.height = this.height + "px"; + } + else { // right + frame.style.top = ''; + frame.style.bottom = '0'; + frame.style.left = '0'; + frame.style.width = this.width + 'px'; + frame.style.height = this.height + "px"; + } + changeCalled = this._redrawLabels(); + if (this.options.icons == true) { + this._redrawGroupIcons(); + } + } + return changeCalled; + }; /** - * detect mobile browsers - * @property IS_MOBILE - * @type {Boolean} + * Repaint major and minor text labels and vertical grid lines + * @private */ - Hammer.IS_MOBILE = /mobile|tablet|ip(ad|hone|od)|android|silk/i.test(navigator.userAgent); + DataAxis.prototype._redrawLabels = function () { + DOMutil.prepareElements(this.DOMelements.lines); + DOMutil.prepareElements(this.DOMelements.labels); - /** - * detect if we want to support mouseevents at all - * @property NO_MOUSEEVENTS - * @type {Boolean} - */ - Hammer.NO_MOUSEEVENTS = (Hammer.HAS_TOUCHEVENTS && Hammer.IS_MOBILE) || Hammer.HAS_POINTEREVENTS; + var orientation = this.options['orientation']; - /** - * interval in which Hammer recalculates current velocity/direction/angle in ms - * @property CALCULATE_INTERVAL - * @type {Number} - * @default 25 - */ - Hammer.CALCULATE_INTERVAL = 25; + // calculate range and step (step such that we have space for 7 characters per label) + var minimumStep = this.master ? this.props.majorCharHeight || 10 : this.stepPixelsForced; + var step = new DataStep(this.range.start, this.range.end, minimumStep, this.dom.frame.offsetHeight); + this.step = step; + step.first(); + // get the distance in pixels for a step + var stepPixels = this.dom.frame.offsetHeight / ((step.marginRange / step.step) + 1); + this.stepPixels = stepPixels; - /** - * eventtypes per touchevent (start, move, end) are filled by `Event.determineEventTypes` on `setup` - * the object contains the DOM event names per type (`EVENT_START`, `EVENT_MOVE`, `EVENT_END`) - * @property EVENT_TYPES - * @private - * @writeOnce - * @type {Object} - */ - var EVENT_TYPES = {}; + var amountOfSteps = this.height / stepPixels; + var stepDifference = 0; - /** - * direction strings, for safe comparisons - * @property DIRECTION_DOWN|LEFT|UP|RIGHT - * @final - * @type {String} - * @default 'down' 'left' 'up' 'right' - */ - var DIRECTION_DOWN = Hammer.DIRECTION_DOWN = 'down'; - var DIRECTION_LEFT = Hammer.DIRECTION_LEFT = 'left'; - var DIRECTION_UP = Hammer.DIRECTION_UP = 'up'; - var DIRECTION_RIGHT = Hammer.DIRECTION_RIGHT = 'right'; + if (this.master == false) { + stepPixels = this.stepPixelsForced; + stepDifference = Math.round((this.height / stepPixels) - amountOfSteps); + for (var i = 0; i < 0.5 * stepDifference; i++) { + step.previous(); + } + amountOfSteps = this.height / stepPixels; + } - /** - * pointertype strings, for safe comparisons - * @property POINTER_MOUSE|TOUCH|PEN - * @final - * @type {String} - * @default 'mouse' 'touch' 'pen' - */ - var POINTER_MOUSE = Hammer.POINTER_MOUSE = 'mouse'; - var POINTER_TOUCH = Hammer.POINTER_TOUCH = 'touch'; - var POINTER_PEN = Hammer.POINTER_PEN = 'pen'; - /** - * eventtypes - * @property EVENT_START|MOVE|END|RELEASE|TOUCH - * @final - * @type {String} - * @default 'start' 'change' 'move' 'end' 'release' 'touch' - */ - var EVENT_START = Hammer.EVENT_START = 'start'; - var EVENT_MOVE = Hammer.EVENT_MOVE = 'move'; - var EVENT_END = Hammer.EVENT_END = 'end'; - var EVENT_RELEASE = Hammer.EVENT_RELEASE = 'release'; - var EVENT_TOUCH = Hammer.EVENT_TOUCH = 'touch'; + this.valueAtZero = step.marginEnd; + var marginStartPos = 0; - /** - * if the window events are set... - * @property READY - * @writeOnce - * @type {Boolean} - * @default false - */ - Hammer.READY = false; + // do not draw the first label + var max = 1; + step.next(); - /** - * plugins namespace - * @property plugins - * @type {Object} - */ - Hammer.plugins = Hammer.plugins || {}; + this.maxLabelSize = 0; + var y = 0; + while (max < Math.round(amountOfSteps)) { - /** - * gestures namespace - * see `/gestures` for the definitions - * @property gestures - * @type {Object} - */ - Hammer.gestures = Hammer.gestures || {}; + y = Math.round(max * stepPixels); + marginStartPos = max * stepPixels; + var isMajor = step.isMajor(); - /** - * setup events to detect gestures on the document - * this function is called when creating an new instance - * @private - */ - function setup() { - if(Hammer.READY) { - return; + if (this.options['showMinorLabels'] && isMajor == false || this.master == false && this.options['showMinorLabels'] == true) { + this._redrawLabel(y - 2, step.getCurrent(), orientation, 'yAxis minor', this.props.minorCharHeight); } - // find what eventtypes we add listeners to - Event.determineEventTypes(); + if (isMajor && this.options['showMajorLabels'] && this.master == true || + this.options['showMinorLabels'] == false && this.master == false && isMajor == true) { + if (y >= 0) { + this._redrawLabel(y - 2, step.getCurrent(), orientation, 'yAxis major', this.props.majorCharHeight); + } + this._redrawLine(y, orientation, 'grid horizontal major', this.options.majorLinesOffset, this.props.majorLineWidth); + } + else { + this._redrawLine(y, orientation, 'grid horizontal minor', this.options.minorLinesOffset, this.props.minorLineWidth); + } - // Register all gestures inside Hammer.gestures - Utils.each(Hammer.gestures, function(gesture) { - Detection.register(gesture); - }); + step.next(); + max++; + } - // Add touch events on the document - Event.onTouch(Hammer.DOCUMENT, EVENT_MOVE, Detection.detect); - Event.onTouch(Hammer.DOCUMENT, EVENT_END, Detection.detect); + this.conversionFactor = marginStartPos/((amountOfSteps-1) * step.step); - // Hammer is ready...! - Hammer.READY = true; - } + var offset = this.options.icons == true ? this.options.iconWidth + this.options.labelOffsetX + 15 : this.options.labelOffsetX + 15; + // this will resize the yAxis to accomodate the labels. + if (this.maxLabelSize > (this.width - offset) && this.options.visible == true) { + this.width = this.maxLabelSize + offset; + this.options.width = this.width + "px"; + DOMutil.cleanupElements(this.DOMelements.lines); + DOMutil.cleanupElements(this.DOMelements.labels); + this.redraw(); + return true; + } + // this will resize the yAxis if it is too big for the labels. + else if (this.maxLabelSize < (this.width - offset) && this.options.visible == true && this.width > this.minWidth) { + this.width = Math.max(this.minWidth,this.maxLabelSize + offset); + this.options.width = this.width + "px"; + DOMutil.cleanupElements(this.DOMelements.lines); + DOMutil.cleanupElements(this.DOMelements.labels); + this.redraw(); + return true; + } + else { + DOMutil.cleanupElements(this.DOMelements.lines); + DOMutil.cleanupElements(this.DOMelements.labels); + return false; + } + }; /** - * @module hammer - * - * @class Utils - * @static + * Create a label for the axis at position x + * @private + * @param y + * @param text + * @param orientation + * @param className + * @param characterHeight */ - var Utils = Hammer.utils = { - /** - * extend method, could also be used for cloning when `dest` is an empty object. - * changes the dest object - * @method extend - * @param {Object} dest - * @param {Object} src - * @param {Boolean} [merge=false] do a merge - * @return {Object} dest - */ - extend: function extend(dest, src, merge) { - for(var key in src) { - if(!src.hasOwnProperty(key) || (dest[key] !== undefined && merge)) { - continue; - } - dest[key] = src[key]; - } - return dest; - }, + DataAxis.prototype._redrawLabel = function (y, text, orientation, className, characterHeight) { + // reuse redundant label + var label = DOMutil.getDOMElement('div',this.DOMelements.labels, this.dom.frame); //this.dom.redundant.labels.shift(); + label.className = className; + label.innerHTML = text; + if (orientation == 'left') { + label.style.left = '-' + this.options.labelOffsetX + 'px'; + label.style.textAlign = "right"; + } + else { + label.style.right = '-' + this.options.labelOffsetX + 'px'; + label.style.textAlign = "left"; + } - /** - * simple addEventListener wrapper - * @method on - * @param {HTMLElement} element - * @param {String} type - * @param {Function} handler - */ - on: function on(element, type, handler) { - element.addEventListener(type, handler, false); - }, + label.style.top = y - 0.5 * characterHeight + this.options.labelOffsetY + 'px'; - /** - * simple removeEventListener wrapper - * @method off - * @param {HTMLElement} element - * @param {String} type - * @param {Function} handler - */ - off: function off(element, type, handler) { - element.removeEventListener(type, handler, false); - }, + text += ''; - /** - * forEach over arrays and objects - * @method each - * @param {Object|Array} obj - * @param {Function} iterator - * @param {any} iterator.item - * @param {Number} iterator.index - * @param {Object|Array} iterator.obj the source object - * @param {Object} context value to use as `this` in the iterator - */ - each: function each(obj, iterator, context) { - var i, len; + var largestWidth = Math.max(this.props.majorCharWidth,this.props.minorCharWidth); + if (this.maxLabelSize < text.length * largestWidth) { + this.maxLabelSize = text.length * largestWidth; + } + }; - // native forEach on arrays - if('forEach' in obj) { - obj.forEach(iterator, context); - // arrays - } else if(obj.length !== undefined) { - for(i = 0, len = obj.length; i < len; i++) { - if(iterator.call(context, obj[i], i, obj) === false) { - return; - } - } - // objects - } else { - for(i in obj) { - if(obj.hasOwnProperty(i) && - iterator.call(context, obj[i], i, obj) === false) { - return; - } - } - } - }, + /** + * Create a minor line for the axis at position y + * @param y + * @param orientation + * @param className + * @param offset + * @param width + */ + DataAxis.prototype._redrawLine = function (y, orientation, className, offset, width) { + if (this.master == true) { + var line = DOMutil.getDOMElement('div',this.DOMelements.lines, this.dom.lineContainer);//this.dom.redundant.lines.shift(); + line.className = className; + line.innerHTML = ''; - /** - * find if a string contains the string using indexOf - * @method inStr - * @param {String} src - * @param {String} find - * @return {Boolean} found - */ - inStr: function inStr(src, find) { - return src.indexOf(find) > -1; - }, + if (orientation == 'left') { + line.style.left = (this.width - offset) + 'px'; + } + else { + line.style.right = (this.width - offset) + 'px'; + } - /** - * find if a array contains the object using indexOf or a simple polyfill - * @method inArray - * @param {String} src - * @param {String} find - * @return {Boolean|Number} false when not found, or the index - */ - inArray: function inArray(src, find) { - if(src.indexOf) { - var index = src.indexOf(find); - return (index === -1) ? false : index; - } else { - for(var i = 0, len = src.length; i < len; i++) { - if(src[i] === find) { - return i; - } - } - return false; - } - }, + line.style.width = width + 'px'; + line.style.top = y + 'px'; + } + }; - /** - * convert an array-like object (`arguments`, `touchlist`) to an array - * @method toArray - * @param {Object} obj - * @return {Array} - */ - toArray: function toArray(obj) { - return Array.prototype.slice.call(obj, 0); - }, - /** - * find if a node is in the given parent - * @method hasParent - * @param {HTMLElement} node - * @param {HTMLElement} parent - * @return {Boolean} found - */ - hasParent: function hasParent(node, parent) { - while(node) { - if(node == parent) { - return true; - } - node = node.parentNode; - } - return false; - }, + DataAxis.prototype.convertValue = function (value) { + var invertedValue = this.valueAtZero - value; + var convertedValue = invertedValue * this.conversionFactor; + return convertedValue; // the -2 is to compensate for the borders + }; - /** - * get the center of all the touches - * @method getCenter - * @param {Array} touches - * @return {Object} center contains `pageX`, `pageY`, `clientX` and `clientY` properties - */ - getCenter: function getCenter(touches) { - var pageX = [], - pageY = [], - clientX = [], - clientY = [], - min = Math.min, - max = Math.max; - // no need to loop when only one touch - if(touches.length === 1) { - return { - pageX: touches[0].pageX, - pageY: touches[0].pageY, - clientX: touches[0].clientX, - clientY: touches[0].clientY - }; - } + /** + * Determine the size of text on the axis (both major and minor axis). + * The size is calculated only once and then cached in this.props. + * @private + */ + DataAxis.prototype._calculateCharSize = function () { + // determine the char width and height on the minor axis + if (!('minorCharHeight' in this.props)) { + var textMinor = document.createTextNode('0'); + var measureCharMinor = document.createElement('DIV'); + measureCharMinor.className = 'yAxis minor measure'; + measureCharMinor.appendChild(textMinor); + this.dom.frame.appendChild(measureCharMinor); - Utils.each(touches, function(touch) { - pageX.push(touch.pageX); - pageY.push(touch.pageY); - clientX.push(touch.clientX); - clientY.push(touch.clientY); - }); + this.props.minorCharHeight = measureCharMinor.clientHeight; + this.props.minorCharWidth = measureCharMinor.clientWidth; - return { - pageX: (min.apply(Math, pageX) + max.apply(Math, pageX)) / 2, - pageY: (min.apply(Math, pageY) + max.apply(Math, pageY)) / 2, - clientX: (min.apply(Math, clientX) + max.apply(Math, clientX)) / 2, - clientY: (min.apply(Math, clientY) + max.apply(Math, clientY)) / 2 - }; - }, + this.dom.frame.removeChild(measureCharMinor); + } - /** - * calculate the velocity between two points. unit is in px per ms. - * @method getVelocity - * @param {Number} deltaTime - * @param {Number} deltaX - * @param {Number} deltaY - * @return {Object} velocity `x` and `y` - */ - getVelocity: function getVelocity(deltaTime, deltaX, deltaY) { - return { - x: Math.abs(deltaX / deltaTime) || 0, - y: Math.abs(deltaY / deltaTime) || 0 - }; - }, + if (!('majorCharHeight' in this.props)) { + var textMajor = document.createTextNode('0'); + var measureCharMajor = document.createElement('DIV'); + measureCharMajor.className = 'yAxis major measure'; + measureCharMajor.appendChild(textMajor); + this.dom.frame.appendChild(measureCharMajor); - /** - * calculate the angle between two coordinates - * @method getAngle - * @param {Touch} touch1 - * @param {Touch} touch2 - * @return {Number} angle - */ - getAngle: function getAngle(touch1, touch2) { - var x = touch2.clientX - touch1.clientX, - y = touch2.clientY - touch1.clientY; + this.props.majorCharHeight = measureCharMajor.clientHeight; + this.props.majorCharWidth = measureCharMajor.clientWidth; - return Math.atan2(y, x) * 180 / Math.PI; - }, + this.dom.frame.removeChild(measureCharMajor); + } + }; - /** - * do a small comparision to get the direction between two touches. - * @method getDirection - * @param {Touch} touch1 - * @param {Touch} touch2 - * @return {String} direction matches `DIRECTION_LEFT|RIGHT|UP|DOWN` - */ - getDirection: function getDirection(touch1, touch2) { - var x = Math.abs(touch1.clientX - touch2.clientX), - y = Math.abs(touch1.clientY - touch2.clientY); + /** + * Snap a date to a rounded value. + * The snap intervals are dependent on the current scale and step. + * @param {Date} date the date to be snapped. + * @return {Date} snappedDate + */ + DataAxis.prototype.snap = function(date) { + return this.step.snap(date); + }; - if(x >= y) { - return touch1.clientX - touch2.clientX > 0 ? DIRECTION_LEFT : DIRECTION_RIGHT; - } - return touch1.clientY - touch2.clientY > 0 ? DIRECTION_UP : DIRECTION_DOWN; - }, + module.exports = DataAxis; - /** - * calculate the distance between two touches - * @method getDistance - * @param {Touch}touch1 - * @param {Touch} touch2 - * @return {Number} distance - */ - getDistance: function getDistance(touch1, touch2) { - var x = touch2.clientX - touch1.clientX, - y = touch2.clientY - touch1.clientY; - return Math.sqrt((x * x) + (y * y)); - }, +/***/ }, +/* 22 */ +/***/ function(module, exports, __webpack_require__) { - /** - * calculate the scale factor between two touchLists - * no scale is 1, and goes down to 0 when pinched together, and bigger when pinched out - * @method getScale - * @param {Array} start array of touches - * @param {Array} end array of touches - * @return {Number} scale - */ - getScale: function getScale(start, end) { - // need two fingers... - if(start.length >= 2 && end.length >= 2) { - return this.getDistance(end[0], end[1]) / this.getDistance(start[0], start[1]); - } - return 1; - }, + var util = __webpack_require__(1); + var DOMutil = __webpack_require__(2); - /** - * calculate the rotation degrees between two touchLists - * @method getRotation - * @param {Array} start array of touches - * @param {Array} end array of touches - * @return {Number} rotation - */ - getRotation: function getRotation(start, end) { - // need two fingers - if(start.length >= 2 && end.length >= 2) { - return this.getAngle(end[1], end[0]) - this.getAngle(start[1], start[0]); - } - return 0; - }, + /** + * @constructor Group + * @param {Number | String} groupId + * @param {Object} data + * @param {ItemSet} itemSet + */ + function GraphGroup (group, groupId, options, groupsUsingDefaultStyles) { + this.id = groupId; + var fields = ['sampling','style','sort','yAxisOrientation','barChart','drawPoints','shaded','catmullRom','slots'] + this.options = util.selectiveBridgeObject(fields,options); + this.usingDefaultStyle = group.className === undefined; + this.groupsUsingDefaultStyles = groupsUsingDefaultStyles; + this.zeroPosition = 0; + this.update(group); + if (this.usingDefaultStyle == true) { + this.groupsUsingDefaultStyles[0] += 1; + } + this.itemsData = []; + this.visible = group.visible === undefined ? true : group.visible; + } - /** - * find out if the direction is vertical * - * @method isVertical - * @param {String} direction matches `DIRECTION_UP|DOWN` - * @return {Boolean} is_vertical - */ - isVertical: function isVertical(direction) { - return direction == DIRECTION_UP || direction == DIRECTION_DOWN; - }, + GraphGroup.prototype.setItems = function(items) { + if (items != null) { + this.itemsData = items; + if (this.options.sort == true) { + this.itemsData.sort(function (a,b) {return a.x - b.x;}) + } + } + else { + this.itemsData = []; + } + }; - /** - * set css properties with their prefixes - * @param {HTMLElement} element - * @param {String} prop - * @param {String} value - * @param {Boolean} [toggle=true] - * @return {Boolean} - */ - setPrefixedCss: function setPrefixedCss(element, prop, value, toggle) { - var prefixes = ['', 'Webkit', 'Moz', 'O', 'ms']; - prop = Utils.toCamelCase(prop); + GraphGroup.prototype.setZeroPosition = function(pos) { + this.zeroPosition = pos; + }; - for(var i = 0; i < prefixes.length; i++) { - var p = prop; - // prefixes - if(prefixes[i]) { - p = prefixes[i] + p.slice(0, 1).toUpperCase() + p.slice(1); - } + GraphGroup.prototype.setOptions = function(options) { + if (options !== undefined) { + var fields = ['sampling','style','sort','yAxisOrientation','barChart','slots']; + util.selectiveDeepExtend(fields, this.options, options); - // test the style - if(p in element.style) { - element.style[p] = (toggle == null || toggle) && value || ''; - break; - } - } - }, + util.mergeOptions(this.options, options,'catmullRom'); + util.mergeOptions(this.options, options,'drawPoints'); + util.mergeOptions(this.options, options,'shaded'); - /** - * toggle browser default behavior by setting css properties. - * `userSelect='none'` also sets `element.onselectstart` to false - * `userDrag='none'` also sets `element.ondragstart` to false - * - * @method toggleBehavior - * @param {HtmlElement} element - * @param {Object} props - * @param {Boolean} [toggle=true] - */ - toggleBehavior: function toggleBehavior(element, props, toggle) { - if(!props || !element || !element.style) { - return; + if (options.catmullRom) { + if (typeof options.catmullRom == 'object') { + if (options.catmullRom.parametrization) { + if (options.catmullRom.parametrization == 'uniform') { + this.options.catmullRom.alpha = 0; + } + else if (options.catmullRom.parametrization == 'chordal') { + this.options.catmullRom.alpha = 1.0; + } + else { + this.options.catmullRom.parametrization = 'centripetal'; + this.options.catmullRom.alpha = 0.5; + } } + } + } + } + }; - // set the css properties - Utils.each(props, function(value, prop) { - Utils.setPrefixedCss(element, prop, value, toggle); - }); + GraphGroup.prototype.update = function(group) { + this.group = group; + this.content = group.content || 'graph'; + this.className = group.className || this.className || "graphGroup" + this.groupsUsingDefaultStyles[0] % 10; + this.visible = group.visible === undefined ? true : group.visible; + this.setOptions(group.options); + }; - var falseFn = toggle && function() { - return false; - }; + GraphGroup.prototype.drawIcon = function(x, y, JSONcontainer, SVGcontainer, iconWidth, iconHeight) { + var fillHeight = iconHeight * 0.5; + var path, fillPath; - // also the disable onselectstart - if(props.userSelect == 'none') { - element.onselectstart = falseFn; - } - // and disable ondragstart - if(props.userDrag == 'none') { - element.ondragstart = falseFn; - } - }, + var outline = DOMutil.getSVGElement("rect", JSONcontainer, SVGcontainer); + outline.setAttributeNS(null, "x", x); + outline.setAttributeNS(null, "y", y - fillHeight); + outline.setAttributeNS(null, "width", iconWidth); + outline.setAttributeNS(null, "height", 2*fillHeight); + outline.setAttributeNS(null, "class", "outline"); - /** - * convert a string with underscores to camelCase - * so prevent_default becomes preventDefault - * @param {String} str - * @return {String} camelCaseStr - */ - toCamelCase: function toCamelCase(str) { - return str.replace(/[_-]([a-z])/g, function(s) { - return s[1].toUpperCase(); - }); + if (this.options.style == 'line') { + path = DOMutil.getSVGElement("path", JSONcontainer, SVGcontainer); + path.setAttributeNS(null, "class", this.className); + path.setAttributeNS(null, "d", "M" + x + ","+y+" L" + (x + iconWidth) + ","+y+""); + if (this.options.shaded.enabled == true) { + fillPath = DOMutil.getSVGElement("path", JSONcontainer, SVGcontainer); + if (this.options.shaded.orientation == 'top') { + fillPath.setAttributeNS(null, "d", "M"+x+", " + (y - fillHeight) + + "L"+x+","+y+" L"+ (x + iconWidth) + ","+y+" L"+ (x + iconWidth) + "," + (y - fillHeight)); + } + else { + fillPath.setAttributeNS(null, "d", "M"+x+","+y+" " + + "L"+x+"," + (y + fillHeight) + " " + + "L"+ (x + iconWidth) + "," + (y + fillHeight) + + "L"+ (x + iconWidth) + ","+y); + } + fillPath.setAttributeNS(null, "class", this.className + " iconFill"); } - }; + if (this.options.drawPoints.enabled == true) { + DOMutil.drawPoint(x + 0.5 * iconWidth,y, this, JSONcontainer, SVGcontainer); + } + } + else { + var barWidth = Math.round(0.3 * iconWidth); + var bar1Height = Math.round(0.4 * iconHeight); + var bar2Height = Math.round(0.75 * iconHeight); + + var offset = Math.round((iconWidth - (2 * barWidth))/3); + + DOMutil.drawBar(x + 0.5*barWidth + offset , y + fillHeight - bar1Height - 1, barWidth, bar1Height, this.className + ' bar', JSONcontainer, SVGcontainer); + DOMutil.drawBar(x + 1.5*barWidth + offset + 2, y + fillHeight - bar2Height - 1, barWidth, bar2Height, this.className + ' bar', JSONcontainer, SVGcontainer); + } + }; /** - * @module hammer - */ - /** - * @class Event - * @static + * + * @param iconWidth + * @param iconHeight + * @returns {{icon: HTMLElement, label: (group.content|*|string), orientation: (.options.yAxisOrientation|*)}} */ - var Event = Hammer.event = { - /** - * when touch events have been fired, this is true - * this is used to stop mouse events - * @property prevent_mouseevents - * @private - * @type {Boolean} - */ - preventMouseEvents: false, + GraphGroup.prototype.getLegend = function(iconWidth, iconHeight) { + var svg = document.createElementNS('http://www.w3.org/2000/svg',"svg"); + this.drawIcon(0,0.5*iconHeight,[],svg,iconWidth,iconHeight); + return {icon: svg, label: this.content, orientation:this.options.yAxisOrientation}; + } - /** - * if EVENT_START has been fired - * @property started - * @private - * @type {Boolean} - */ - started: false, + module.exports = GraphGroup; - /** - * when the mouse is hold down, this is true - * @property should_detect - * @private - * @type {Boolean} - */ - shouldDetect: false, - /** - * simple event binder with a hook and support for multiple types - * @method on - * @param {HTMLElement} element - * @param {String} type - * @param {Function} handler - * @param {Function} [hook] - * @param {Object} hook.type - */ - on: function on(element, type, handler, hook) { - var types = type.split(' '); - Utils.each(types, function(type) { - Utils.on(element, type, handler); - hook && hook(type); - }); - }, +/***/ }, +/* 23 */ +/***/ function(module, exports, __webpack_require__) { - /** - * simple event unbinder with a hook and support for multiple types - * @method off - * @param {HTMLElement} element - * @param {String} type - * @param {Function} handler - * @param {Function} [hook] - * @param {Object} hook.type - */ - off: function off(element, type, handler, hook) { - var types = type.split(' '); - Utils.each(types, function(type) { - Utils.off(element, type, handler); - hook && hook(type); - }); - }, + var util = __webpack_require__(1); + var stack = __webpack_require__(16); + var ItemRange = __webpack_require__(31); - /** - * the core touch event handler. - * this finds out if we should to detect gestures - * @method onTouch - * @param {HTMLElement} element - * @param {String} eventType matches `EVENT_START|MOVE|END` - * @param {Function} handler - * @return onTouchHandler {Function} the core event handler - */ - onTouch: function onTouch(element, eventType, handler) { - var self = this; + /** + * @constructor Group + * @param {Number | String} groupId + * @param {Object} data + * @param {ItemSet} itemSet + */ + function Group (groupId, data, itemSet) { + this.groupId = groupId; - var onTouchHandler = function onTouchHandler(ev) { - var srcType = ev.type.toLowerCase(), - isPointer = Hammer.HAS_POINTEREVENTS, - isMouse = Utils.inStr(srcType, 'mouse'), - triggerType; + this.itemSet = itemSet; - // if we are in a mouseevent, but there has been a touchevent triggered in this session - // we want to do nothing. simply break out of the event. - if(isMouse && self.preventMouseEvents) { - return; + this.dom = {}; + this.props = { + label: { + width: 0, + height: 0 + } + }; + this.className = null; - // mousebutton must be down - } else if(isMouse && eventType == EVENT_START && ev.button === 0) { - self.preventMouseEvents = false; - self.shouldDetect = true; - } else if(isPointer && eventType == EVENT_START) { - self.shouldDetect = (ev.buttons === 1 || PointerEvent.matchType(POINTER_TOUCH, ev)); - // just a valid start event, but no mouse - } else if(!isMouse && eventType == EVENT_START) { - self.preventMouseEvents = true; - self.shouldDetect = true; - } + this.items = {}; // items filtered by groupId of this group + this.visibleItems = []; // items currently visible in window + this.orderedItems = { // items sorted by start and by end + byStart: [], + byEnd: [] + }; - // update the pointer event before entering the detection - if(isPointer && eventType != EVENT_END) { - PointerEvent.updatePointer(eventType, ev); - } + this._create(); - // we are in a touch/down state, so allowed detection of gestures - if(self.shouldDetect) { - triggerType = self.doDetect.call(self, ev, eventType, element, handler); - } + this.setData(data); + } - // ...and we are done with the detection - // so reset everything to start each detection totally fresh - if(triggerType == EVENT_END) { - self.preventMouseEvents = false; - self.shouldDetect = false; - PointerEvent.reset(); - // update the pointerevent object after the detection - } + /** + * Create DOM elements for the group + * @private + */ + Group.prototype._create = function() { + var label = document.createElement('div'); + label.className = 'vlabel'; + this.dom.label = label; - if(isPointer && eventType == EVENT_END) { - PointerEvent.updatePointer(eventType, ev); - } - }; + var inner = document.createElement('div'); + inner.className = 'inner'; + label.appendChild(inner); + this.dom.inner = inner; - this.on(element, EVENT_TYPES[eventType], onTouchHandler); - return onTouchHandler; - }, + var foreground = document.createElement('div'); + foreground.className = 'group'; + foreground['timeline-group'] = this; + this.dom.foreground = foreground; - /** - * the core detection method - * this finds out what hammer-touch-events to trigger - * @method doDetect - * @param {Object} ev - * @param {String} eventType matches `EVENT_START|MOVE|END` - * @param {HTMLElement} element - * @param {Function} handler - * @return {String} triggerType matches `EVENT_START|MOVE|END` - */ - doDetect: function doDetect(ev, eventType, element, handler) { - var touchList = this.getTouchList(ev, eventType); - var touchListLength = touchList.length; - var triggerType = eventType; - var triggerChange = touchList.trigger; // used by fakeMultitouch plugin - var changedLength = touchListLength; + this.dom.background = document.createElement('div'); + this.dom.background.className = 'group'; - // at each touchstart-like event we want also want to trigger a TOUCH event... - if(eventType == EVENT_START) { - triggerChange = EVENT_TOUCH; - // ...the same for a touchend-like event - } else if(eventType == EVENT_END) { - triggerChange = EVENT_RELEASE; + this.dom.axis = document.createElement('div'); + this.dom.axis.className = 'group'; - // keep track of how many touches have been removed - changedLength = touchList.length - ((ev.changedTouches) ? ev.changedTouches.length : 1); - } + // create a hidden marker to detect when the Timelines container is attached + // to the DOM, or the style of a parent of the Timeline is changed from + // display:none is changed to visible. + this.dom.marker = document.createElement('div'); + this.dom.marker.style.visibility = 'hidden'; + this.dom.marker.innerHTML = '?'; + this.dom.background.appendChild(this.dom.marker); + }; - // after there are still touches on the screen, - // we just want to trigger a MOVE event. so change the START or END to a MOVE - // but only after detection has been started, the first time we actualy want a START - if(changedLength > 0 && this.started) { - triggerType = EVENT_MOVE; - } + /** + * Set the group data for this group + * @param {Object} data Group data, can contain properties content and className + */ + Group.prototype.setData = function(data) { + // update contents + var content = data && data.content; + if (content instanceof Element) { + this.dom.inner.appendChild(content); + } + else if (content !== undefined && content !== null) { + this.dom.inner.innerHTML = content; + } + else { + this.dom.inner.innerHTML = this.groupId || ''; // groupId can be null + } - // detection has been started, we keep track of this, see above - this.started = true; + // update title + this.dom.label.title = data && data.title || ''; - // generate some event data, some basic information - var evData = this.collectEventData(element, triggerType, touchList, ev); + if (!this.dom.inner.firstChild) { + util.addClassName(this.dom.inner, 'hidden'); + } + else { + util.removeClassName(this.dom.inner, 'hidden'); + } - // trigger the triggerType event before the change (TOUCH, RELEASE) events - // but the END event should be at last - if(eventType != EVENT_END) { - handler.call(Detection, evData); - } + // update className + var className = data && data.className || null; + if (className != this.className) { + if (this.className) { + util.removeClassName(this.dom.label, className); + util.removeClassName(this.dom.foreground, className); + util.removeClassName(this.dom.background, className); + util.removeClassName(this.dom.axis, className); + } + util.addClassName(this.dom.label, className); + util.addClassName(this.dom.foreground, className); + util.addClassName(this.dom.background, className); + util.addClassName(this.dom.axis, className); + } + }; - // trigger a change (TOUCH, RELEASE) event, this means the length of the touches changed - if(triggerChange) { - evData.changedLength = changedLength; - evData.eventType = triggerChange; - - handler.call(Detection, evData); + /** + * Get the width of the group label + * @return {number} width + */ + Group.prototype.getLabelWidth = function() { + return this.props.label.width; + }; - evData.eventType = triggerType; - delete evData.changedLength; - } - // trigger the END event - if(triggerType == EVENT_END) { - handler.call(Detection, evData); + /** + * Repaint this group + * @param {{start: number, end: number}} range + * @param {{item: {horizontal: number, vertical: number}, axis: number}} margin + * @param {boolean} [restack=false] Force restacking of all items + * @return {boolean} Returns true if the group is resized + */ + Group.prototype.redraw = function(range, margin, restack) { + var resized = false; - // ...and we are done with the detection - // so reset everything to start each detection totally fresh - this.started = false; - } + this.visibleItems = this._updateVisibleItems(this.orderedItems, this.visibleItems, range); - return triggerType; - }, + // force recalculation of the height of the items when the marker height changed + // (due to the Timeline being attached to the DOM or changed from display:none to visible) + var markerHeight = this.dom.marker.clientHeight; + if (markerHeight != this.lastMarkerHeight) { + this.lastMarkerHeight = markerHeight; - /** - * we have different events for each device/browser - * determine what we need and set them in the EVENT_TYPES constant - * the `onTouch` method is bind to these properties. - * @method determineEventTypes - * @return {Object} events - */ - determineEventTypes: function determineEventTypes() { - var types; - if(Hammer.HAS_POINTEREVENTS) { - if(window.PointerEvent) { - types = [ - 'pointerdown', - 'pointermove', - 'pointerup pointercancel lostpointercapture' - ]; - } else { - types = [ - 'MSPointerDown', - 'MSPointerMove', - 'MSPointerUp MSPointerCancel MSLostPointerCapture' - ]; - } - } else if(Hammer.NO_MOUSEEVENTS) { - types = [ - 'touchstart', - 'touchmove', - 'touchend touchcancel' - ]; - } else { - types = [ - 'touchstart mousedown', - 'touchmove mousemove', - 'touchend touchcancel mouseup' - ]; - } + util.forEach(this.items, function (item) { + item.dirty = true; + if (item.displayed) item.redraw(); + }); - EVENT_TYPES[EVENT_START] = types[0]; - EVENT_TYPES[EVENT_MOVE] = types[1]; - EVENT_TYPES[EVENT_END] = types[2]; - return EVENT_TYPES; - }, + restack = true; + } - /** - * create touchList depending on the event - * @method getTouchList - * @param {Object} ev - * @param {String} eventType - * @return {Array} touches - */ - getTouchList: function getTouchList(ev, eventType) { - // get the fake pointerEvent touchlist - if(Hammer.HAS_POINTEREVENTS) { - return PointerEvent.getTouchList(); - } + // reposition visible items vertically + if (this.itemSet.options.stack) { // TODO: ugly way to access options... + stack.stack(this.visibleItems, margin, restack); + } + else { // no stacking + stack.nostack(this.visibleItems, margin); + } - // get the touchlist - if(ev.touches) { - if(eventType == EVENT_MOVE) { - return ev.touches; - } + // recalculate the height of the group + var height; + var visibleItems = this.visibleItems; + if (visibleItems.length) { + var min = visibleItems[0].top; + var max = visibleItems[0].top + visibleItems[0].height; + util.forEach(visibleItems, function (item) { + min = Math.min(min, item.top); + max = Math.max(max, (item.top + item.height)); + }); + if (min > margin.axis) { + // there is an empty gap between the lowest item and the axis + var offset = min - margin.axis; + max -= offset; + util.forEach(visibleItems, function (item) { + item.top -= offset; + }); + } + height = max + margin.item.vertical / 2; + } + else { + height = margin.axis + margin.item.vertical; + } + height = Math.max(height, this.props.label.height); - var identifiers = []; - var concat = [].concat(Utils.toArray(ev.touches), Utils.toArray(ev.changedTouches)); - var touchList = []; + // calculate actual size and position + var foreground = this.dom.foreground; + this.top = foreground.offsetTop; + this.left = foreground.offsetLeft; + this.width = foreground.offsetWidth; + resized = util.updateProperty(this, 'height', height) || resized; - Utils.each(concat, function(touch) { - if(Utils.inArray(identifiers, touch.identifier) === false) { - touchList.push(touch); - } - identifiers.push(touch.identifier); - }); + // recalculate size of label + resized = util.updateProperty(this.props.label, 'width', this.dom.inner.clientWidth) || resized; + resized = util.updateProperty(this.props.label, 'height', this.dom.inner.clientHeight) || resized; - return touchList; - } + // apply new height + this.dom.background.style.height = height + 'px'; + this.dom.foreground.style.height = height + 'px'; + this.dom.label.style.height = height + 'px'; - // make fake touchList from mouse position - ev.identifier = 1; - return [ev]; - }, + // update vertical position of items after they are re-stacked and the height of the group is calculated + for (var i = 0, ii = this.visibleItems.length; i < ii; i++) { + var item = this.visibleItems[i]; + item.repositionY(); + } - /** - * collect basic event data - * @method collectEventData - * @param {HTMLElement} element - * @param {String} eventType matches `EVENT_START|MOVE|END` - * @param {Array} touches - * @param {Object} ev - * @return {Object} ev - */ - collectEventData: function collectEventData(element, eventType, touches, ev) { - // find out pointerType - var pointerType = POINTER_TOUCH; - if(Utils.inStr(ev.type, 'mouse') || PointerEvent.matchType(POINTER_MOUSE, ev)) { - pointerType = POINTER_MOUSE; - } else if(PointerEvent.matchType(POINTER_PEN, ev)) { - pointerType = POINTER_PEN; - } + return resized; + }; - return { - center: Utils.getCenter(touches), - timeStamp: Date.now(), - target: ev.target, - touches: touches, - eventType: eventType, - pointerType: pointerType, - srcEvent: ev, + /** + * Show this group: attach to the DOM + */ + Group.prototype.show = function() { + if (!this.dom.label.parentNode) { + this.itemSet.dom.labelSet.appendChild(this.dom.label); + } - /** - * prevent the browser default actions - * mostly used to disable scrolling of the browser - */ - preventDefault: function() { - var srcEvent = this.srcEvent; - srcEvent.preventManipulation && srcEvent.preventManipulation(); - srcEvent.preventDefault && srcEvent.preventDefault(); - }, + if (!this.dom.foreground.parentNode) { + this.itemSet.dom.foreground.appendChild(this.dom.foreground); + } - /** - * stop bubbling the event up to its parents - */ - stopPropagation: function() { - this.srcEvent.stopPropagation(); - }, + if (!this.dom.background.parentNode) { + this.itemSet.dom.background.appendChild(this.dom.background); + } - /** - * immediately stop gesture detection - * might be useful after a swipe was detected - * @return {*} - */ - stopDetect: function() { - return Detection.stopDetect(); - } - }; - } + if (!this.dom.axis.parentNode) { + this.itemSet.dom.axis.appendChild(this.dom.axis); + } }; - /** - * @module hammer - * - * @class PointerEvent - * @static + * Hide this group: remove from the DOM */ - var PointerEvent = Hammer.PointerEvent = { - /** - * holds all pointers, by `identifier` - * @property pointers - * @type {Object} - */ - pointers: {}, + Group.prototype.hide = function() { + var label = this.dom.label; + if (label.parentNode) { + label.parentNode.removeChild(label); + } - /** - * get the pointers as an array - * @method getTouchList - * @return {Array} touchlist - */ - getTouchList: function getTouchList() { - var touchlist = []; - // we can use forEach since pointerEvents only is in IE10 - Utils.each(this.pointers, function(pointer) { - touchlist.push(pointer); - }); - return touchlist; - }, - - /** - * update the position of a pointer - * @method updatePointer - * @param {String} eventType matches `EVENT_START|MOVE|END` - * @param {Object} pointerEvent - */ - updatePointer: function updatePointer(eventType, pointerEvent) { - if(eventType == EVENT_END || (eventType != EVENT_END && pointerEvent.buttons !== 1)) { - delete this.pointers[pointerEvent.pointerId]; - } else { - pointerEvent.identifier = pointerEvent.pointerId; - this.pointers[pointerEvent.pointerId] = pointerEvent; - } - }, + var foreground = this.dom.foreground; + if (foreground.parentNode) { + foreground.parentNode.removeChild(foreground); + } - /** - * check if ev matches pointertype - * @method matchType - * @param {String} pointerType matches `POINTER_MOUSE|TOUCH|PEN` - * @param {PointerEvent} ev - */ - matchType: function matchType(pointerType, ev) { - if(!ev.pointerType) { - return false; - } + var background = this.dom.background; + if (background.parentNode) { + background.parentNode.removeChild(background); + } - var pt = ev.pointerType, - types = {}; + var axis = this.dom.axis; + if (axis.parentNode) { + axis.parentNode.removeChild(axis); + } + }; - types[POINTER_MOUSE] = (pt === (ev.MSPOINTER_TYPE_MOUSE || POINTER_MOUSE)); - types[POINTER_TOUCH] = (pt === (ev.MSPOINTER_TYPE_TOUCH || POINTER_TOUCH)); - types[POINTER_PEN] = (pt === (ev.MSPOINTER_TYPE_PEN || POINTER_PEN)); - return types[pointerType]; - }, + /** + * Add an item to the group + * @param {Item} item + */ + Group.prototype.add = function(item) { + this.items[item.id] = item; + item.setParent(this); - /** - * reset the stored pointers - * @method reset - */ - reset: function resetList() { - this.pointers = {}; - } + if (this.visibleItems.indexOf(item) == -1) { + var range = this.itemSet.body.range; // TODO: not nice accessing the range like this + this._checkIfVisible(item, this.visibleItems, range); + } }; - /** - * @module hammer - * - * @class Detection - * @static + * Remove an item from the group + * @param {Item} item */ - var Detection = Hammer.detection = { - // contains all registred Hammer.gestures in the correct order - gestures: [], + Group.prototype.remove = function(item) { + delete this.items[item.id]; + item.setParent(this.itemSet); - // data of the current Hammer.gesture detection session - current: null, + // remove from visible items + var index = this.visibleItems.indexOf(item); + if (index != -1) this.visibleItems.splice(index, 1); - // the previous Hammer.gesture session data - // is a full clone of the previous gesture.current object - previous: null, + // TODO: also remove from ordered items? + }; - // when this becomes true, no gestures are fired - stopped: false, + /** + * Remove an item from the corresponding DataSet + * @param {Item} item + */ + Group.prototype.removeFromDataSet = function(item) { + this.itemSet.removeItem(item.id); + }; - /** - * start Hammer.gesture detection - * @method startDetect - * @param {Hammer.Instance} inst - * @param {Object} eventData - */ - startDetect: function startDetect(inst, eventData) { - // already busy with a Hammer.gesture detection on an element - if(this.current) { - return; - } + /** + * Reorder the items + */ + Group.prototype.order = function() { + var array = util.toArray(this.items); + this.orderedItems.byStart = array; + this.orderedItems.byEnd = this._constructByEndArray(array); - this.stopped = false; + stack.orderByStart(this.orderedItems.byStart); + stack.orderByEnd(this.orderedItems.byEnd); + }; - // holds current session - this.current = { - inst: inst, // reference to HammerInstance we're working for - startEvent: Utils.extend({}, eventData), // start eventData for distances, timing etc - lastEvent: false, // last eventData - lastCalcEvent: false, // last eventData for calculations. - futureCalcEvent: false, // last eventData for calculations. - lastCalcData: {}, // last lastCalcData - name: '' // current gesture we're in/detected, can be 'tap', 'hold' etc - }; + /** + * Create an array containing all items being a range (having an end date) + * @param {Item[]} array + * @returns {ItemRange[]} + * @private + */ + Group.prototype._constructByEndArray = function(array) { + var endArray = []; - this.detect(eventData); - }, + for (var i = 0; i < array.length; i++) { + if (array[i] instanceof ItemRange) { + endArray.push(array[i]); + } + } + return endArray; + }; - /** - * Hammer.gesture detection - * @method detect - * @param {Object} eventData - * @return {any} - */ - detect: function detect(eventData) { - if(!this.current || this.stopped) { - return; - } + /** + * Update the visible items + * @param {{byStart: Item[], byEnd: Item[]}} orderedItems All items ordered by start date and by end date + * @param {Item[]} visibleItems The previously visible items. + * @param {{start: number, end: number}} range Visible range + * @return {Item[]} visibleItems The new visible items. + * @private + */ + Group.prototype._updateVisibleItems = function(orderedItems, visibleItems, range) { + var initialPosByStart, + newVisibleItems = [], + i; - // extend event data with calculations about scale, distance etc - eventData = this.extendEventData(eventData); + // first check if the items that were in view previously are still in view. + // this handles the case for the ItemRange that is both before and after the current one. + if (visibleItems.length > 0) { + for (i = 0; i < visibleItems.length; i++) { + this._checkIfVisible(visibleItems[i], newVisibleItems, range); + } + } - // hammer instance and instance options - var inst = this.current.inst, - instOptions = inst.options; + // If there were no visible items previously, use binarySearch to find a visible ItemPoint or ItemRange (based on startTime) + if (newVisibleItems.length == 0) { + initialPosByStart = util.binarySearch(orderedItems.byStart, range, 'data','start'); + } + else { + initialPosByStart = orderedItems.byStart.indexOf(newVisibleItems[0]); + } - // call Hammer.gesture handlers - Utils.each(this.gestures, function triggerGesture(gesture) { - // only when the instance options have enabled this gesture - if(!this.stopped && inst.enabled && instOptions[gesture.name]) { - gesture.handler.call(gesture, eventData, inst); - } - }, this); + // use visible search to find a visible ItemRange (only based on endTime) + var initialPosByEnd = util.binarySearch(orderedItems.byEnd, range, 'data','end'); - // store as previous event event - if(this.current) { - this.current.lastEvent = eventData; - } + // if we found a initial ID to use, trace it up and down until we meet an invisible item. + if (initialPosByStart != -1) { + for (i = initialPosByStart; i >= 0; i--) { + if (this._checkIfInvisible(orderedItems.byStart[i], newVisibleItems, range)) {break;} + } + for (i = initialPosByStart + 1; i < orderedItems.byStart.length; i++) { + if (this._checkIfInvisible(orderedItems.byStart[i], newVisibleItems, range)) {break;} + } + } - if(eventData.eventType == EVENT_END) { - this.stopDetect(); - } + // if we found a initial ID to use, trace it up and down until we meet an invisible item. + if (initialPosByEnd != -1) { + for (i = initialPosByEnd; i >= 0; i--) { + if (this._checkIfInvisible(orderedItems.byEnd[i], newVisibleItems, range)) {break;} + } + for (i = initialPosByEnd + 1; i < orderedItems.byEnd.length; i++) { + if (this._checkIfInvisible(orderedItems.byEnd[i], newVisibleItems, range)) {break;} + } + } - return eventData; - }, + return newVisibleItems; + }; - /** - * clear the Hammer.gesture vars - * this is called on endDetect, but can also be used when a final Hammer.gesture has been detected - * to stop other Hammer.gestures from being fired - * @method stopDetect - */ - stopDetect: function stopDetect() { - // clone current data to the store as the previous gesture - // used for the double tap gesture, since this is an other gesture detect session - this.previous = Utils.extend({}, this.current); - // reset the current - this.current = null; - this.stopped = true; - }, - /** - * calculate velocity, angle and direction - * @method getVelocityData - * @param {Object} ev - * @param {Object} center - * @param {Number} deltaTime - * @param {Number} deltaX - * @param {Number} deltaY - */ - getCalculatedData: function getCalculatedData(ev, center, deltaTime, deltaX, deltaY) { - var cur = this.current, - recalc = false, - calcEv = cur.lastCalcEvent, - calcData = cur.lastCalcData; + /** + * this function checks if an item is invisible. If it is NOT we make it visible + * and add it to the global visible items. If it is, return true. + * + * @param {Item} item + * @param {Item[]} visibleItems + * @param {{start:number, end:number}} range + * @returns {boolean} + * @private + */ + Group.prototype._checkIfInvisible = function(item, visibleItems, range) { + if (item.isVisible(range)) { + if (!item.displayed) item.show(); + item.repositionX(); + if (visibleItems.indexOf(item) == -1) { + visibleItems.push(item); + } + return false; + } + else { + if (item.displayed) item.hide(); + return true; + } + }; - if(calcEv && ev.timeStamp - calcEv.timeStamp > Hammer.CALCULATE_INTERVAL) { - center = calcEv.center; - deltaTime = ev.timeStamp - calcEv.timeStamp; - deltaX = ev.center.clientX - calcEv.center.clientX; - deltaY = ev.center.clientY - calcEv.center.clientY; - recalc = true; - } + /** + * this function is very similar to the _checkIfInvisible() but it does not + * return booleans, hides the item if it should not be seen and always adds to + * the visibleItems. + * this one is for brute forcing and hiding. + * + * @param {Item} item + * @param {Array} visibleItems + * @param {{start:number, end:number}} range + * @private + */ + Group.prototype._checkIfVisible = function(item, visibleItems, range) { + if (item.isVisible(range)) { + if (!item.displayed) item.show(); + // reposition item horizontally + item.repositionX(); + visibleItems.push(item); + } + else { + if (item.displayed) item.hide(); + } + }; - if(ev.eventType == EVENT_TOUCH || ev.eventType == EVENT_RELEASE) { - cur.futureCalcEvent = ev; - } + module.exports = Group; - if(!cur.lastCalcEvent || recalc) { - calcData.velocity = Utils.getVelocity(deltaTime, deltaX, deltaY); - calcData.angle = Utils.getAngle(center, ev.center); - calcData.direction = Utils.getDirection(center, ev.center); - cur.lastCalcEvent = cur.futureCalcEvent || ev; - cur.futureCalcEvent = ev; - } +/***/ }, +/* 24 */ +/***/ function(module, exports, __webpack_require__) { - ev.velocityX = calcData.velocity.x; - ev.velocityY = calcData.velocity.y; - ev.interimAngle = calcData.angle; - ev.interimDirection = calcData.direction; + var Hammer = __webpack_require__(41); + var util = __webpack_require__(1); + var DataSet = __webpack_require__(3); + var DataView = __webpack_require__(4); + var Component = __webpack_require__(18); + var Group = __webpack_require__(23); + var ItemBox = __webpack_require__(29); + var ItemPoint = __webpack_require__(30); + var ItemRange = __webpack_require__(31); + + + var UNGROUPED = '__ungrouped__'; // reserved group id for ungrouped items + + /** + * An ItemSet holds a set of items and ranges which can be displayed in a + * range. The width is determined by the parent of the ItemSet, and the height + * is determined by the size of the items. + * @param {{dom: Object, domProps: Object, emitter: Emitter, range: Range}} body + * @param {Object} [options] See ItemSet.setOptions for the available options. + * @constructor ItemSet + * @extends Component + */ + function ItemSet(body, options) { + this.body = body; + + this.defaultOptions = { + type: null, // 'box', 'point', 'range' + orientation: 'bottom', // 'top' or 'bottom' + align: 'center', // alignment of box items + stack: true, + groupOrder: null, + + selectable: true, + editable: { + updateTime: false, + updateGroup: false, + add: false, + remove: false }, - /** - * extend eventData for Hammer.gestures - * @method extendEventData - * @param {Object} ev - * @return {Object} ev - */ - extendEventData: function extendEventData(ev) { - var cur = this.current, - startEv = cur.startEvent, - lastEv = cur.lastEvent || startEv; + onAdd: function (item, callback) { + callback(item); + }, + onUpdate: function (item, callback) { + callback(item); + }, + onMove: function (item, callback) { + callback(item); + }, + onRemove: function (item, callback) { + callback(item); + }, - // update the start touchlist to calculate the scale/rotation - if(ev.eventType == EVENT_TOUCH || ev.eventType == EVENT_RELEASE) { - startEv.touches = []; - Utils.each(ev.touches, function(touch) { - startEv.touches.push({ - clientX: touch.clientX, - clientY: touch.clientY - }); - }); - } + margin: { + item: { + horizontal: 10, + vertical: 10 + }, + axis: 20 + }, + padding: 5 + }; - var deltaTime = ev.timeStamp - startEv.timeStamp, - deltaX = ev.center.clientX - startEv.center.clientX, - deltaY = ev.center.clientY - startEv.center.clientY; + // options is shared by this ItemSet and all its items + this.options = util.extend({}, this.defaultOptions); - this.getCalculatedData(ev, lastEv.center, deltaTime, deltaX, deltaY); + // options for getting items from the DataSet with the correct type + this.itemOptions = { + type: {start: 'Date', end: 'Date'} + }; - Utils.extend(ev, { - startEvent: startEv, + this.conversion = { + toScreen: body.util.toScreen, + toTime: body.util.toTime + }; + this.dom = {}; + this.props = {}; + this.hammer = null; - deltaTime: deltaTime, - deltaX: deltaX, - deltaY: deltaY, + var me = this; + this.itemsData = null; // DataSet + this.groupsData = null; // DataSet - distance: Utils.getDistance(startEv.center, ev.center), - angle: Utils.getAngle(startEv.center, ev.center), - direction: Utils.getDirection(startEv.center, ev.center), - scale: Utils.getScale(startEv.touches, ev.touches), - rotation: Utils.getRotation(startEv.touches, ev.touches) - }); + // listeners for the DataSet of the items + this.itemListeners = { + 'add': function (event, params, senderId) { + me._onAdd(params.items); + }, + 'update': function (event, params, senderId) { + me._onUpdate(params.items); + }, + 'remove': function (event, params, senderId) { + me._onRemove(params.items); + } + }; - return ev; + // listeners for the DataSet of the groups + this.groupListeners = { + 'add': function (event, params, senderId) { + me._onAddGroups(params.items); + }, + 'update': function (event, params, senderId) { + me._onUpdateGroups(params.items); }, + 'remove': function (event, params, senderId) { + me._onRemoveGroups(params.items); + } + }; - /** - * register new gesture - * @method register - * @param {Object} gesture object, see `gestures/` for documentation - * @return {Array} gestures - */ - register: function register(gesture) { - // add an enable gesture options if there is no given - var options = gesture.defaults || {}; - if(options[gesture.name] === undefined) { - options[gesture.name] = true; - } + this.items = {}; // object with an Item for every data item + this.groups = {}; // Group object for every group + this.groupIds = []; - // extend Hammer default options with the Hammer.gesture options - Utils.extend(Hammer.defaults, options, true); + this.selection = []; // list with the ids of all selected nodes + this.stackDirty = true; // if true, all items will be restacked on next redraw - // set its index - gesture.index = gesture.index || 1000; + this.touchParams = {}; // stores properties while dragging + // create the HTML DOM - // add Hammer.gesture to the list - this.gestures.push(gesture); + this._create(); - // sort the list by index - this.gestures.sort(function(a, b) { - if(a.index < b.index) { - return -1; - } - if(a.index > b.index) { - return 1; - } - return 0; - }); + this.setOptions(options); + } - return this.gestures; - } - }; + ItemSet.prototype = new Component(); + // available item types will be registered here + ItemSet.types = { + box: ItemBox, + range: ItemRange, + point: ItemPoint + }; /** - * @module hammer + * Create the HTML DOM for the ItemSet */ + ItemSet.prototype._create = function(){ + var frame = document.createElement('div'); + frame.className = 'itemset'; + frame['timeline-itemset'] = this; + this.dom.frame = frame; - /** - * create new hammer instance - * all methods should return the instance itself, so it is chainable. - * - * @class Instance - * @constructor - * @param {HTMLElement} element - * @param {Object} [options={}] options are merged with `Hammer.defaults` - * @return {Hammer.Instance} - */ - Hammer.Instance = function(element, options) { - var self = this; + // create background panel + var background = document.createElement('div'); + background.className = 'background'; + frame.appendChild(background); + this.dom.background = background; - // setup HammerJS window events and register all gestures - // this also sets up the default options - setup(); + // create foreground panel + var foreground = document.createElement('div'); + foreground.className = 'foreground'; + frame.appendChild(foreground); + this.dom.foreground = foreground; - /** - * @property element - * @type {HTMLElement} - */ - this.element = element; + // create axis panel + var axis = document.createElement('div'); + axis.className = 'axis'; + this.dom.axis = axis; - /** - * @property enabled - * @type {Boolean} - * @protected - */ - this.enabled = true; + // create labelset + var labelSet = document.createElement('div'); + labelSet.className = 'labelset'; + this.dom.labelSet = labelSet; - /** - * options, merged with the defaults - * options with an _ are converted to camelCase - * @property options - * @type {Object} - */ - Utils.each(options, function(value, name) { - delete options[name]; - options[Utils.toCamelCase(name)] = value; - }); + // create ungrouped Group + this._updateUngrouped(); - this.options = Utils.extend(Utils.extend({}, Hammer.defaults), options || {}); + // attach event listeners + // Note: we bind to the centerContainer for the case where the height + // of the center container is larger than of the ItemSet, so we + // can click in the empty area to create a new item or deselect an item. + this.hammer = Hammer(this.body.dom.centerContainer, { + prevent_default: true + }); - // add some css to the element to prevent the browser from doing its native behavoir - if(this.options.behavior) { - Utils.toggleBehavior(this.element, this.options.behavior, true); - } + // drag items when selected + this.hammer.on('touch', this._onTouch.bind(this)); + this.hammer.on('dragstart', this._onDragStart.bind(this)); + this.hammer.on('drag', this._onDrag.bind(this)); + this.hammer.on('dragend', this._onDragEnd.bind(this)); - /** - * event start handler on the element to start the detection - * @property eventStartHandler - * @type {Object} - */ - this.eventStartHandler = Event.onTouch(element, EVENT_START, function(ev) { - if(self.enabled && ev.eventType == EVENT_START) { - Detection.startDetect(self, ev); - } else if(ev.eventType == EVENT_TOUCH) { - Detection.detect(ev); - } - }); + // single select (or unselect) when tapping an item + this.hammer.on('tap', this._onSelectItem.bind(this)); - /** - * keep a list of user event handlers which needs to be removed when calling 'dispose' - * @property eventHandlers - * @type {Array} - */ - this.eventHandlers = []; - }; + // multi select when holding mouse/touch, or on ctrl+click + this.hammer.on('hold', this._onMultiSelectItem.bind(this)); - Hammer.Instance.prototype = { - /** - * bind events to the instance - * @method on - * @chainable - * @param {String} gestures multiple gestures by splitting with a space - * @param {Function} handler - * @param {Object} handler.ev event object - */ - on: function onEvent(gestures, handler) { - var self = this; - Event.on(self.element, gestures, handler, function(type) { - self.eventHandlers.push({ gesture: type, handler: handler }); - }); - return self; - }, + // add item on doubletap + this.hammer.on('doubletap', this._onAddItem.bind(this)); - /** - * unbind events to the instance - * @method off - * @chainable - * @param {String} gestures - * @param {Function} handler - */ - off: function offEvent(gestures, handler) { - var self = this; + // attach to the DOM + this.show(); + }; - Event.off(self.element, gestures, handler, function(type) { - var index = Utils.inArray({ gesture: type, handler: handler }); - if(index !== false) { - self.eventHandlers.splice(index, 1); - } - }); - return self; - }, + /** + * Set options for the ItemSet. Existing options will be extended/overwritten. + * @param {Object} [options] The following options are available: + * {String} type + * Default type for the items. Choose from 'box' + * (default), 'point', or 'range'. The default + * Style can be overwritten by individual items. + * {String} align + * Alignment for the items, only applicable for + * ItemBox. Choose 'center' (default), 'left', or + * 'right'. + * {String} orientation + * Orientation of the item set. Choose 'top' or + * 'bottom' (default). + * {Function} groupOrder + * A sorting function for ordering groups + * {Boolean} stack + * If true (deafult), items will be stacked on + * top of each other. + * {Number} margin.axis + * Margin between the axis and the items in pixels. + * Default is 20. + * {Number} margin.item.horizontal + * Horizontal margin between items in pixels. + * Default is 10. + * {Number} margin.item.vertical + * Vertical Margin between items in pixels. + * Default is 10. + * {Number} margin.item + * Margin between items in pixels in both horizontal + * and vertical direction. Default is 10. + * {Number} margin + * Set margin for both axis and items in pixels. + * {Number} padding + * Padding of the contents of an item in pixels. + * Must correspond with the items css. Default is 5. + * {Boolean} selectable + * If true (default), items can be selected. + * {Boolean} editable + * Set all editable options to true or false + * {Boolean} editable.updateTime + * Allow dragging an item to an other moment in time + * {Boolean} editable.updateGroup + * Allow dragging an item to an other group + * {Boolean} editable.add + * Allow creating new items on double tap + * {Boolean} editable.remove + * Allow removing items by clicking the delete button + * top right of a selected item. + * {Function(item: Item, callback: Function)} onAdd + * Callback function triggered when an item is about to be added: + * when the user double taps an empty space in the Timeline. + * {Function(item: Item, callback: Function)} onUpdate + * Callback function fired when an item is about to be updated. + * This function typically has to show a dialog where the user + * change the item. If not implemented, nothing happens. + * {Function(item: Item, callback: Function)} onMove + * Fired when an item has been moved. If not implemented, + * the move action will be accepted. + * {Function(item: Item, callback: Function)} onRemove + * Fired when an item is about to be deleted. + * If not implemented, the item will be always removed. + */ + ItemSet.prototype.setOptions = function(options) { + if (options) { + // copy all options that we know + var fields = ['type', 'align', 'orientation', 'padding', 'stack', 'selectable', 'groupOrder']; + util.selectiveExtend(fields, this.options, options); - /** - * trigger gesture event - * @method trigger - * @chainable - * @param {String} gesture - * @param {Object} [eventData] - */ - trigger: function triggerEvent(gesture, eventData) { - // optional - if(!eventData) { - eventData = {}; + if ('margin' in options) { + if (typeof options.margin === 'number') { + this.options.margin.axis = options.margin; + this.options.margin.item.horizontal = options.margin; + this.options.margin.item.vertical = options.margin; + } + else if (typeof options.margin === 'object') { + util.selectiveExtend(['axis'], this.options.margin, options.margin); + if ('item' in options.margin) { + if (typeof options.margin.item === 'number') { + this.options.margin.item.horizontal = options.margin.item; + this.options.margin.item.vertical = options.margin.item; + } + else if (typeof options.margin.item === 'object') { + util.selectiveExtend(['horizontal', 'vertical'], this.options.margin.item, options.margin.item); + } } + } + } - // create DOM event - var event = Hammer.DOCUMENT.createEvent('Event'); - event.initEvent(gesture, true, true); - event.gesture = eventData; - - // trigger on the target if it is in the instance element, - // this is for event delegation tricks - var element = this.element; - if(Utils.hasParent(eventData.target, element)) { - element = eventData.target; - } + if ('editable' in options) { + if (typeof options.editable === 'boolean') { + this.options.editable.updateTime = options.editable; + this.options.editable.updateGroup = options.editable; + this.options.editable.add = options.editable; + this.options.editable.remove = options.editable; + } + else if (typeof options.editable === 'object') { + util.selectiveExtend(['updateTime', 'updateGroup', 'add', 'remove'], this.options.editable, options.editable); + } + } - element.dispatchEvent(event); - return this; - }, - - /** - * enable of disable hammer.js detection - * @method enable - * @chainable - * @param {Boolean} state - */ - enable: function enable(state) { - this.enabled = state; - return this; - }, - - /** - * dispose this hammer instance - * @method dispose - * @return {Null} - */ - dispose: function dispose() { - var i, eh; - - // undo all changes made by stop_browser_behavior - Utils.toggleBehavior(this.element, this.options.behavior, false); - - // unbind all custom event handlers - for(i = -1; (eh = this.eventHandlers[++i]);) { - Utils.off(this.element, eh.gesture, eh.handler); + // callback functions + var addCallback = (function (name) { + if (name in options) { + var fn = options[name]; + if (!(fn instanceof Function)) { + throw new Error('option ' + name + ' must be a function ' + name + '(item, callback)'); } + this.options[name] = fn; + } + }).bind(this); + ['onAdd', 'onUpdate', 'onRemove', 'onMove'].forEach(addCallback); - this.eventHandlers = []; - - // unbind the start event listener - Event.off(this.element, EVENT_TYPES[EVENT_START], this.eventStartHandler); - - return null; - } + // force the itemSet to refresh: options like orientation and margins may be changed + this.markDirty(); + } }; - - /** - * @module gestures - */ /** - * Move with x fingers (default 1) around on the page. - * Preventing the default browser behavior is a good way to improve feel and working. - * ```` - * hammertime.on("drag", function(ev) { - * console.log(ev); - * ev.gesture.preventDefault(); - * }); - * ```` - * - * @class Drag - * @static + * Mark the ItemSet dirty so it will refresh everything with next redraw */ + ItemSet.prototype.markDirty = function() { + this.groupIds = []; + this.stackDirty = true; + }; + /** - * @event drag - * @param {Object} ev + * Destroy the ItemSet */ + ItemSet.prototype.destroy = function() { + this.hide(); + this.setItems(null); + this.setGroups(null); + + this.hammer = null; + + this.body = null; + this.conversion = null; + }; + /** - * @event dragstart - * @param {Object} ev + * Hide the component from the DOM */ + ItemSet.prototype.hide = function() { + // remove the frame containing the items + if (this.dom.frame.parentNode) { + this.dom.frame.parentNode.removeChild(this.dom.frame); + } + + // remove the axis with dots + if (this.dom.axis.parentNode) { + this.dom.axis.parentNode.removeChild(this.dom.axis); + } + + // remove the labelset containing all group labels + if (this.dom.labelSet.parentNode) { + this.dom.labelSet.parentNode.removeChild(this.dom.labelSet); + } + }; + /** - * @event dragend - * @param {Object} ev + * Show the component in the DOM (when not already visible). + * @return {Boolean} changed */ + ItemSet.prototype.show = function() { + // show frame containing the items + if (!this.dom.frame.parentNode) { + this.body.dom.center.appendChild(this.dom.frame); + } + + // show axis with dots + if (!this.dom.axis.parentNode) { + this.body.dom.backgroundVertical.appendChild(this.dom.axis); + } + + // show labelset containing labels + if (!this.dom.labelSet.parentNode) { + this.body.dom.left.appendChild(this.dom.labelSet); + } + }; + /** - * @event drapleft - * @param {Object} ev + * Set selected items by their id. Replaces the current selection + * Unknown id's are silently ignored. + * @param {Array} [ids] An array with zero or more id's of the items to be + * selected. If ids is an empty array, all items will be + * unselected. */ + ItemSet.prototype.setSelection = function(ids) { + var i, ii, id, item; + + if (ids) { + if (!Array.isArray(ids)) { + throw new TypeError('Array expected'); + } + + // unselect currently selected items + for (i = 0, ii = this.selection.length; i < ii; i++) { + id = this.selection[i]; + item = this.items[id]; + if (item) item.unselect(); + } + + // select items + this.selection = []; + for (i = 0, ii = ids.length; i < ii; i++) { + id = ids[i]; + item = this.items[id]; + if (item) { + this.selection.push(id); + item.select(); + } + } + } + }; + /** - * @event dragright - * @param {Object} ev + * Get the selected items by their id + * @return {Array} ids The ids of the selected items */ + ItemSet.prototype.getSelection = function() { + return this.selection.concat([]); + }; + /** - * @event dragup - * @param {Object} ev + * Get the id's of the currently visible items. + * @returns {Array} The ids of the visible items */ + ItemSet.prototype.getVisibleItems = function() { + var range = this.body.range.getRange(); + var left = this.body.util.toScreen(range.start); + var right = this.body.util.toScreen(range.end); + + var ids = []; + for (var groupId in this.groups) { + if (this.groups.hasOwnProperty(groupId)) { + var group = this.groups[groupId]; + var rawVisibleItems = group.visibleItems; + + // filter the "raw" set with visibleItems into a set which is really + // visible by pixels + for (var i = 0; i < rawVisibleItems.length; i++) { + var item = rawVisibleItems[i]; + // TODO: also check whether visible vertically + if ((item.left < right) && (item.left + item.width > left)) { + ids.push(item.id); + } + } + } + } + + return ids; + }; + /** - * @event dragdown - * @param {Object} ev + * Deselect a selected item + * @param {String | Number} id + * @private */ + ItemSet.prototype._deselect = function(id) { + var selection = this.selection; + for (var i = 0, ii = selection.length; i < ii; i++) { + if (selection[i] == id) { // non-strict comparison! + selection.splice(i, 1); + break; + } + } + }; /** - * @param {String} name + * Repaint the component + * @return {boolean} Returns true if the component is resized */ - (function(name) { - var triggered = false; - - function dragGesture(ev, inst) { - var cur = Detection.current; - - // max touches - if(inst.options.dragMaxTouches > 0 && - ev.touches.length > inst.options.dragMaxTouches) { - return; - } + ItemSet.prototype.redraw = function() { + var margin = this.options.margin, + range = this.body.range, + asSize = util.option.asSize, + options = this.options, + orientation = options.orientation, + resized = false, + frame = this.dom.frame, + editable = options.editable.updateTime || options.editable.updateGroup; - switch(ev.eventType) { - case EVENT_START: - triggered = false; - break; + // update class name + frame.className = 'itemset' + (editable ? ' editable' : ''); - case EVENT_MOVE: - // when the distance we moved is too small we skip this gesture - // or we can be already in dragging - if(ev.distance < inst.options.dragMinDistance && - cur.name != name) { - return; - } + // reorder the groups (if needed) + resized = this._orderGroups() || resized; - var startCenter = cur.startEvent.center; + // check whether zoomed (in that case we need to re-stack everything) + // TODO: would be nicer to get this as a trigger from Range + var visibleInterval = range.end - range.start; + var zoomed = (visibleInterval != this.lastVisibleInterval) || (this.props.width != this.props.lastWidth); + if (zoomed) this.stackDirty = true; + this.lastVisibleInterval = visibleInterval; + this.props.lastWidth = this.props.width; - // we are dragging! - if(cur.name != name) { - cur.name = name; - if(inst.options.dragDistanceCorrection && ev.distance > 0) { - // When a drag is triggered, set the event center to dragMinDistance pixels from the original event center. - // Without this correction, the dragged distance would jumpstart at dragMinDistance pixels instead of at 0. - // It might be useful to save the original start point somewhere - var factor = Math.abs(inst.options.dragMinDistance / ev.distance); - startCenter.pageX += ev.deltaX * factor; - startCenter.pageY += ev.deltaY * factor; - startCenter.clientX += ev.deltaX * factor; - startCenter.clientY += ev.deltaY * factor; + // redraw all groups + var restack = this.stackDirty, + firstGroup = this._firstGroup(), + firstMargin = { + item: margin.item, + axis: margin.axis + }, + nonFirstMargin = { + item: margin.item, + axis: margin.item.vertical / 2 + }, + height = 0, + minHeight = margin.axis + margin.item.vertical; + util.forEach(this.groups, function (group) { + var groupMargin = (group == firstGroup) ? firstMargin : nonFirstMargin; + var groupResized = group.redraw(range, groupMargin, restack); + resized = groupResized || resized; + height += group.height; + }); + height = Math.max(height, minHeight); + this.stackDirty = false; - // recalculate event data using new start point - ev = Detection.extendEventData(ev); - } - } + // update frame height + frame.style.height = asSize(height); - // lock drag to axis? - if(cur.lastEvent.dragLockToAxis || - ( inst.options.dragLockToAxis && - inst.options.dragLockMinDistance <= ev.distance - )) { - ev.dragLockToAxis = true; - } + // calculate actual size and position + this.props.top = frame.offsetTop; + this.props.left = frame.offsetLeft; + this.props.width = frame.offsetWidth; + this.props.height = height; - // keep direction on the axis that the drag gesture started on - var lastDirection = cur.lastEvent.direction; - if(ev.dragLockToAxis && lastDirection !== ev.direction) { - if(Utils.isVertical(lastDirection)) { - ev.direction = (ev.deltaY < 0) ? DIRECTION_UP : DIRECTION_DOWN; - } else { - ev.direction = (ev.deltaX < 0) ? DIRECTION_LEFT : DIRECTION_RIGHT; - } - } + // reposition axis + this.dom.axis.style.top = asSize((orientation == 'top') ? + (this.body.domProps.top.height + this.body.domProps.border.top) : + (this.body.domProps.top.height + this.body.domProps.centerContainer.height)); + this.dom.axis.style.left = this.body.domProps.border.left + 'px'; - // first time, trigger dragstart event - if(!triggered) { - inst.trigger(name + 'start', ev); - triggered = true; - } + // check if this component is resized + resized = this._isResized() || resized; - // trigger events - inst.trigger(name, ev); - inst.trigger(name + ev.direction, ev); + return resized; + }; - var isVertical = Utils.isVertical(ev.direction); + /** + * Get the first group, aligned with the axis + * @return {Group | null} firstGroup + * @private + */ + ItemSet.prototype._firstGroup = function() { + var firstGroupIndex = (this.options.orientation == 'top') ? 0 : (this.groupIds.length - 1); + var firstGroupId = this.groupIds[firstGroupIndex]; + var firstGroup = this.groups[firstGroupId] || this.groups[UNGROUPED]; - // block the browser events - if((inst.options.dragBlockVertical && isVertical) || - (inst.options.dragBlockHorizontal && !isVertical)) { - ev.preventDefault(); - } - break; + return firstGroup || null; + }; - case EVENT_RELEASE: - if(triggered && ev.changedLength <= inst.options.dragMaxTouches) { - inst.trigger(name + 'end', ev); - triggered = false; - } - break; + /** + * Create or delete the group holding all ungrouped items. This group is used when + * there are no groups specified. + * @protected + */ + ItemSet.prototype._updateUngrouped = function() { + var ungrouped = this.groups[UNGROUPED]; - case EVENT_END: - triggered = false; - break; - } + if (this.groupsData) { + // remove the group holding all ungrouped items + if (ungrouped) { + ungrouped.hide(); + delete this.groups[UNGROUPED]; } + } + else { + // create a group holding all (unfiltered) items + if (!ungrouped) { + var id = null; + var data = null; + ungrouped = new Group(id, data, this); + this.groups[UNGROUPED] = ungrouped; - Hammer.gestures.Drag = { - name: name, - index: 50, - handler: dragGesture, - defaults: { - /** - * minimal movement that have to be made before the drag event gets triggered - * @property dragMinDistance - * @type {Number} - * @default 10 - */ - dragMinDistance: 10, - - /** - * Set dragDistanceCorrection to true to make the starting point of the drag - * be calculated from where the drag was triggered, not from where the touch started. - * Useful to avoid a jerk-starting drag, which can make fine-adjustments - * through dragging difficult, and be visually unappealing. - * @property dragDistanceCorrection - * @type {Boolean} - * @default true - */ - dragDistanceCorrection: true, - - /** - * set 0 for unlimited, but this can conflict with transform - * @property dragMaxTouches - * @type {Number} - * @default 1 - */ - dragMaxTouches: 1, - - /** - * prevent default browser behavior when dragging occurs - * be careful with it, it makes the element a blocking element - * when you are using the drag gesture, it is a good practice to set this true - * @property dragBlockHorizontal - * @type {Boolean} - * @default false - */ - dragBlockHorizontal: false, - - /** - * same as `dragBlockHorizontal`, but for vertical movement - * @property dragBlockVertical - * @type {Boolean} - * @default false - */ - dragBlockVertical: false, - - /** - * dragLockToAxis keeps the drag gesture on the axis that it started on, - * It disallows vertical directions if the initial direction was horizontal, and vice versa. - * @property dragLockToAxis - * @type {Boolean} - * @default false - */ - dragLockToAxis: false, - - /** - * drag lock only kicks in when distance > dragLockMinDistance - * This way, locking occurs only when the distance has become large enough to reliably determine the direction - * @property dragLockMinDistance - * @type {Number} - * @default 25 - */ - dragLockMinDistance: 25 + for (var itemId in this.items) { + if (this.items.hasOwnProperty(itemId)) { + ungrouped.add(this.items[itemId]); } - }; - })('drag'); + } - /** - * @module gestures - */ - /** - * trigger a simple gesture event, so you can do anything in your handler. - * only usable if you know what your doing... - * - * @class Gesture - * @static - */ - /** - * @event gesture - * @param {Object} ev - */ - Hammer.gestures.Gesture = { - name: 'gesture', - index: 1337, - handler: function releaseGesture(ev, inst) { - inst.trigger(this.name, ev); + ungrouped.show(); } + } }; /** - * @module gestures - */ - /** - * Touch stays at the same place for x time - * - * @class Hold - * @static - */ - /** - * @event hold - * @param {Object} ev + * Get the element for the labelset + * @return {HTMLElement} labelSet */ + ItemSet.prototype.getLabelSet = function() { + return this.dom.labelSet; + }; /** - * @param {String} name + * Set items + * @param {vis.DataSet | null} items */ - (function(name) { - var timer; + ItemSet.prototype.setItems = function(items) { + var me = this, + ids, + oldItemsData = this.itemsData; - function holdGesture(ev, inst) { - var options = inst.options, - current = Detection.current; + // replace the dataset + if (!items) { + this.itemsData = null; + } + else if (items instanceof DataSet || items instanceof DataView) { + this.itemsData = items; + } + else { + throw new TypeError('Data must be an instance of DataSet or DataView'); + } - switch(ev.eventType) { - case EVENT_START: - clearTimeout(timer); - - // set the gesture so we can check in the timeout if it still is - current.name = name; - - // set timer and if after the timeout it still is hold, - // we trigger the hold event - timer = setTimeout(function() { - if(current && current.name == name) { - inst.trigger(name, ev); - } - }, options.holdTimeout); - break; + if (oldItemsData) { + // unsubscribe from old dataset + util.forEach(this.itemListeners, function (callback, event) { + oldItemsData.off(event, callback); + }); - case EVENT_MOVE: - if(ev.distance > options.holdThreshold) { - clearTimeout(timer); - } - break; + // remove all drawn items + ids = oldItemsData.getIds(); + this._onRemove(ids); + } - case EVENT_RELEASE: - clearTimeout(timer); - break; - } - } + if (this.itemsData) { + // subscribe to new dataset + var id = this.id; + util.forEach(this.itemListeners, function (callback, event) { + me.itemsData.on(event, callback, id); + }); - Hammer.gestures.Hold = { - name: name, - index: 10, - defaults: { - /** - * @property holdTimeout - * @type {Number} - * @default 500 - */ - holdTimeout: 500, + // add all new items + ids = this.itemsData.getIds(); + this._onAdd(ids); - /** - * movement allowed while holding - * @property holdThreshold - * @type {Number} - * @default 2 - */ - holdThreshold: 2 - }, - handler: holdGesture - }; - })('hold'); + // update the group holding all ungrouped items + this._updateUngrouped(); + } + }; /** - * @module gestures - */ - /** - * when a touch is being released from the page - * - * @class Release - * @static - */ - /** - * @event release - * @param {Object} ev + * Get the current items + * @returns {vis.DataSet | null} */ - Hammer.gestures.Release = { - name: 'release', - index: Infinity, - handler: function releaseGesture(ev, inst) { - if(ev.eventType == EVENT_RELEASE) { - inst.trigger(this.name, ev); - } - } + ItemSet.prototype.getItems = function() { + return this.itemsData; }; /** - * @module gestures - */ - /** - * triggers swipe events when the end velocity is above the threshold - * for best usage, set `preventDefault` (on the drag gesture) to `true` - * ```` - * hammertime.on("dragleft swipeleft", function(ev) { - * console.log(ev); - * ev.gesture.preventDefault(); - * }); - * ```` - * - * @class Swipe - * @static - */ - /** - * @event swipe - * @param {Object} ev - */ - /** - * @event swipeleft - * @param {Object} ev - */ - /** - * @event swiperight - * @param {Object} ev - */ - /** - * @event swipeup - * @param {Object} ev - */ - /** - * @event swipedown - * @param {Object} ev + * Set groups + * @param {vis.DataSet} groups */ - Hammer.gestures.Swipe = { - name: 'swipe', - index: 40, - defaults: { - /** - * @property swipeMinTouches - * @type {Number} - * @default 1 - */ - swipeMinTouches: 1, + ItemSet.prototype.setGroups = function(groups) { + var me = this, + ids; - /** - * @property swipeMaxTouches - * @type {Number} - * @default 1 - */ - swipeMaxTouches: 1, + // unsubscribe from current dataset + if (this.groupsData) { + util.forEach(this.groupListeners, function (callback, event) { + me.groupsData.unsubscribe(event, callback); + }); - /** - * horizontal swipe velocity - * @property swipeVelocityX - * @type {Number} - * @default 0.6 - */ - swipeVelocityX: 0.6, + // remove all drawn groups + ids = this.groupsData.getIds(); + this.groupsData = null; + this._onRemoveGroups(ids); // note: this will cause a redraw + } - /** - * vertical swipe velocity - * @property swipeVelocityY - * @type {Number} - * @default 0.6 - */ - swipeVelocityY: 0.6 - }, + // replace the dataset + if (!groups) { + this.groupsData = null; + } + else if (groups instanceof DataSet || groups instanceof DataView) { + this.groupsData = groups; + } + else { + throw new TypeError('Data must be an instance of DataSet or DataView'); + } - handler: function swipeGesture(ev, inst) { - if(ev.eventType == EVENT_RELEASE) { - var touches = ev.touches.length, - options = inst.options; + if (this.groupsData) { + // subscribe to new dataset + var id = this.id; + util.forEach(this.groupListeners, function (callback, event) { + me.groupsData.on(event, callback, id); + }); - // max touches - if(touches < options.swipeMinTouches || - touches > options.swipeMaxTouches) { - return; - } + // draw all ms + ids = this.groupsData.getIds(); + this._onAddGroups(ids); + } - // when the distance we moved is too small we skip this gesture - // or we can be already in dragging - if(ev.velocityX > options.swipeVelocityX || - ev.velocityY > options.swipeVelocityY) { - // trigger swipe events - inst.trigger(this.name, ev); - inst.trigger(this.name + ev.direction, ev); - } - } - } + // update the group holding all ungrouped items + this._updateUngrouped(); + + // update the order of all items in each group + this._order(); + + this.body.emitter.emit('change'); }; /** - * @module gestures - */ - /** - * Single tap and a double tap on a place - * - * @class Tap - * @static - */ - /** - * @event tap - * @param {Object} ev - */ - /** - * @event doubletap - * @param {Object} ev + * Get the current groups + * @returns {vis.DataSet | null} groups */ + ItemSet.prototype.getGroups = function() { + return this.groupsData; + }; /** - * @param {String} name + * Remove an item by its id + * @param {String | Number} id */ - (function(name) { - var hasMoved = false; - - function tapGesture(ev, inst) { - var options = inst.options, - current = Detection.current, - prev = Detection.previous, - sincePrev, - didDoubleTap; + ItemSet.prototype.removeItem = function(id) { + var item = this.itemsData.get(id), + dataset = this.itemsData.getDataSet(); - switch(ev.eventType) { - case EVENT_START: - hasMoved = false; - break; + if (item) { + // confirm deletion + this.options.onRemove(item, function (item) { + if (item) { + // remove by id here, it is possible that an item has no id defined + // itself, so better not delete by the item itself + dataset.remove(id); + } + }); + } + }; - case EVENT_MOVE: - hasMoved = hasMoved || (ev.distance > options.tapMaxDistance); - break; + /** + * Handle updated items + * @param {Number[]} ids + * @protected + */ + ItemSet.prototype._onUpdate = function(ids) { + var me = this; - case EVENT_END: - if(!Utils.inStr(ev.srcEvent.type, 'cancel') && ev.deltaTime < options.tapMaxTime && !hasMoved) { - // previous gesture, for the double tap since these are two different gesture detections - sincePrev = prev && prev.lastEvent && ev.timeStamp - prev.lastEvent.timeStamp; - didDoubleTap = false; + ids.forEach(function (id) { + var itemData = me.itemsData.get(id, me.itemOptions), + item = me.items[id], + type = itemData.type || me.options.type || (itemData.end ? 'range' : 'box'); - // check if double tap - if(prev && prev.name == name && - (sincePrev && sincePrev < options.doubleTapInterval) && - ev.distance < options.doubleTapDistance) { - inst.trigger('doubletap', ev); - didDoubleTap = true; - } + var constructor = ItemSet.types[type]; - // do a single tap - if(!didDoubleTap || options.tapAlways) { - current.name = name; - inst.trigger(current.name, ev); - } - } - break; - } + if (item) { + // update item + if (!constructor || !(item instanceof constructor)) { + // item type has changed, delete the item and recreate it + me._removeItem(item); + item = null; + } + else { + me._updateItem(item, itemData); + } } - Hammer.gestures.Tap = { - name: name, - index: 100, - handler: tapGesture, - defaults: { - /** - * max time of a tap, this is for the slow tappers - * @property tapMaxTime - * @type {Number} - * @default 250 - */ - tapMaxTime: 250, + if (!item) { + // create item + if (constructor) { + item = new constructor(itemData, me.conversion, me.options); + item.id = id; // TODO: not so nice setting id afterwards + me._addItem(item); + } + else if (type == 'rangeoverflow') { + // TODO: deprecated since version 2.1.0 (or 3.0.0?). cleanup some day + throw new TypeError('Item type "rangeoverflow" is deprecated. Use css styling instead: ' + + '.vis.timeline .item.range .content {overflow: visible;}'); + } + else { + throw new TypeError('Unknown item type "' + type + '"'); + } + } + }); - /** - * max distance of movement of a tap, this is for the slow tappers - * @property tapMaxDistance - * @type {Number} - * @default 10 - */ - tapMaxDistance: 10, + this._order(); + this.stackDirty = true; // force re-stacking of all items next redraw + this.body.emitter.emit('change'); + }; - /** - * always trigger the `tap` event, even while double-tapping - * @property tapAlways - * @type {Boolean} - * @default true - */ - tapAlways: true, + /** + * Handle added items + * @param {Number[]} ids + * @protected + */ + ItemSet.prototype._onAdd = ItemSet.prototype._onUpdate; - /** - * max distance between two taps - * @property doubleTapDistance - * @type {Number} - * @default 20 - */ - doubleTapDistance: 20, + /** + * Handle removed items + * @param {Number[]} ids + * @protected + */ + ItemSet.prototype._onRemove = function(ids) { + var count = 0; + var me = this; + ids.forEach(function (id) { + var item = me.items[id]; + if (item) { + count++; + me._removeItem(item); + } + }); - /** - * max time between two taps - * @property doubleTapInterval - * @type {Number} - * @default 300 - */ - doubleTapInterval: 300 - } - }; - })('tap'); + if (count) { + // update order + this._order(); + this.stackDirty = true; // force re-stacking of all items next redraw + this.body.emitter.emit('change'); + } + }; /** - * @module gestures + * Update the order of item in all groups + * @private */ + ItemSet.prototype._order = function() { + // reorder the items in all groups + // TODO: optimization: only reorder groups affected by the changed items + util.forEach(this.groups, function (group) { + group.order(); + }); + }; + /** - * when a touch is being touched at the page - * - * @class Touch - * @static + * Handle updated groups + * @param {Number[]} ids + * @private */ + ItemSet.prototype._onUpdateGroups = function(ids) { + this._onAddGroups(ids); + }; + /** - * @event touch - * @param {Object} ev + * Handle changed groups + * @param {Number[]} ids + * @private */ - Hammer.gestures.Touch = { - name: 'touch', - index: -Infinity, - defaults: { - /** - * call preventDefault at touchstart, and makes the element blocking by disabling the scrolling of the page, - * but it improves gestures like transforming and dragging. - * be careful with using this, it can be very annoying for users to be stuck on the page - * @property preventDefault - * @type {Boolean} - * @default false - */ - preventDefault: false, + ItemSet.prototype._onAddGroups = function(ids) { + var me = this; - /** - * disable mouse events, so only touch (or pen!) input triggers events - * @property preventMouse - * @type {Boolean} - * @default false - */ - preventMouse: false - }, - handler: function touchGesture(ev, inst) { - if(inst.options.preventMouse && ev.pointerType == POINTER_MOUSE) { - ev.stopDetect(); - return; - } + ids.forEach(function (id) { + var groupData = me.groupsData.get(id); + var group = me.groups[id]; - if(inst.options.preventDefault) { - ev.preventDefault(); - } + if (!group) { + // check for reserved ids + if (id == UNGROUPED) { + throw new Error('Illegal group id. ' + id + ' is a reserved id.'); + } - if(ev.eventType == EVENT_TOUCH) { - inst.trigger('touch', ev); + var groupOptions = Object.create(me.options); + util.extend(groupOptions, { + height: null + }); + + group = new Group(id, groupData, me); + me.groups[id] = group; + + // add items with this groupId to the new group + for (var itemId in me.items) { + if (me.items.hasOwnProperty(itemId)) { + var item = me.items[itemId]; + if (item.data.group == id) { + group.add(item); + } } + } + + group.order(); + group.show(); + } + else { + // update group + group.setData(groupData); } + }); + + this.body.emitter.emit('change'); }; /** - * @module gestures - */ - /** - * User want to scale or rotate with 2 fingers - * Preventing the default browser behavior is a good way to improve feel and working. This can be done with the - * `preventDefault` option. - * - * @class Transform - * @static + * Handle removed groups + * @param {Number[]} ids + * @private */ - /** - * @event transform - * @param {Object} ev - */ - /** - * @event transformstart - * @param {Object} ev - */ - /** - * @event transformend - * @param {Object} ev - */ - /** - * @event pinchin - * @param {Object} ev - */ - /** - * @event pinchout - * @param {Object} ev - */ - /** - * @event rotate - * @param {Object} ev - */ - - /** - * @param {String} name - */ - (function(name) { - var triggered = false; - - function transformGesture(ev, inst) { - switch(ev.eventType) { - case EVENT_START: - triggered = false; - break; - - case EVENT_MOVE: - // at least multitouch - if(ev.touches.length < 2) { - return; - } - - var scaleThreshold = Math.abs(1 - ev.scale); - var rotationThreshold = Math.abs(ev.rotation); + ItemSet.prototype._onRemoveGroups = function(ids) { + var groups = this.groups; + ids.forEach(function (id) { + var group = groups[id]; - // when the distance we moved is too small we skip this gesture - // or we can be already in dragging - if(scaleThreshold < inst.options.transformMinScale && - rotationThreshold < inst.options.transformMinRotation) { - return; - } + if (group) { + group.hide(); + delete groups[id]; + } + }); - // we are transforming! - Detection.current.name = name; + this.markDirty(); - // first time, trigger dragstart event - if(!triggered) { - inst.trigger(name + 'start', ev); - triggered = true; - } + this.body.emitter.emit('change'); + }; - inst.trigger(name, ev); // basic transform event + /** + * Reorder the groups if needed + * @return {boolean} changed + * @private + */ + ItemSet.prototype._orderGroups = function () { + if (this.groupsData) { + // reorder the groups + var groupIds = this.groupsData.getIds({ + order: this.options.groupOrder + }); - // trigger rotate event - if(rotationThreshold > inst.options.transformMinRotation) { - inst.trigger('rotate', ev); - } + var changed = !util.equalArray(groupIds, this.groupIds); + if (changed) { + // hide all groups, removes them from the DOM + var groups = this.groups; + groupIds.forEach(function (groupId) { + groups[groupId].hide(); + }); - // trigger pinch event - if(scaleThreshold > inst.options.transformMinScale) { - inst.trigger('pinch', ev); - inst.trigger('pinch' + (ev.scale < 1 ? 'in' : 'out'), ev); - } - break; + // show the groups again, attach them to the DOM in correct order + groupIds.forEach(function (groupId) { + groups[groupId].show(); + }); - case EVENT_RELEASE: - if(triggered && ev.changedLength < 2) { - inst.trigger(name + 'end', ev); - triggered = false; - } - break; - } + this.groupIds = groupIds; } - Hammer.gestures.Transform = { - name: name, - index: 45, - defaults: { - /** - * minimal scale factor, no scale is 1, zoomin is to 0 and zoomout until higher then 1 - * @property transformMinScale - * @type {Number} - * @default 0.01 - */ - transformMinScale: 0.01, + return changed; + } + else { + return false; + } + }; - /** - * rotation in degrees - * @property transformMinRotation - * @type {Number} - * @default 1 - */ - transformMinRotation: 1 - }, + /** + * Add a new item + * @param {Item} item + * @private + */ + ItemSet.prototype._addItem = function(item) { + this.items[item.id] = item; - handler: transformGesture - }; - })('transform'); + // add to group + var groupId = this.groupsData ? item.data.group : UNGROUPED; + var group = this.groups[groupId]; + if (group) group.add(item); + }; /** - * @module hammer + * Update an existing item + * @param {Item} item + * @param {Object} itemData + * @private */ + ItemSet.prototype._updateItem = function(item, itemData) { + var oldGroupId = item.data.group; - // AMD export - if(true) { - !(__WEBPACK_AMD_DEFINE_RESULT__ = (function() { - return Hammer; - }.call(exports, __webpack_require__, exports, module)), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); - // commonjs export - } else if(typeof module !== 'undefined' && module.exports) { - module.exports = Hammer; - // browser export - } else { - window.Hammer = Hammer; - } - - })(window); + item.data = itemData; + if (item.displayed) { + item.redraw(); + } -/***/ }, -/* 20 */ -/***/ function(module, exports, __webpack_require__) { + // update group + if (oldGroupId != item.data.group) { + var oldGroup = this.groups[oldGroupId]; + if (oldGroup) oldGroup.remove(item); - var util = __webpack_require__(1); - var hammerUtil = __webpack_require__(21); - var moment = __webpack_require__(2); - var Component = __webpack_require__(22); + var groupId = this.groupsData ? item.data.group : UNGROUPED; + var group = this.groups[groupId]; + if (group) group.add(item); + } + }; /** - * @constructor Range - * A Range controls a numeric range with a start and end value. - * The Range adjusts the range based on mouse events or programmatic changes, - * and triggers events when the range is changing or has been changed. - * @param {{dom: Object, domProps: Object, emitter: Emitter}} body - * @param {Object} [options] See description at Range.setOptions + * Delete an item from the ItemSet: remove it from the DOM, from the map + * with items, and from the map with visible items, and from the selection + * @param {Item} item + * @private */ - function Range(body, options) { - var now = moment().hours(0).minutes(0).seconds(0).milliseconds(0); - this.start = now.clone().add('days', -3).valueOf(); // Number - this.end = now.clone().add('days', 4).valueOf(); // Number - - this.body = body; + ItemSet.prototype._removeItem = function(item) { + // remove from DOM + item.hide(); - // default options - this.defaultOptions = { - start: null, - end: null, - direction: 'horizontal', // 'horizontal' or 'vertical' - moveable: true, - zoomable: true, - min: null, - max: null, - zoomMin: 10, // milliseconds - zoomMax: 1000 * 60 * 60 * 24 * 365 * 10000 // milliseconds - }; - this.options = util.extend({}, this.defaultOptions); + // remove from items + delete this.items[item.id]; - this.props = { - touch: {} - }; + // remove from selection + var index = this.selection.indexOf(item.id); + if (index != -1) this.selection.splice(index, 1); - // drag listeners for dragging - this.body.emitter.on('dragstart', this._onDragStart.bind(this)); - this.body.emitter.on('drag', this._onDrag.bind(this)); - this.body.emitter.on('dragend', this._onDragEnd.bind(this)); + // remove from group + var groupId = this.groupsData ? item.data.group : UNGROUPED; + var group = this.groups[groupId]; + if (group) group.remove(item); + }; - // ignore dragging when holding - this.body.emitter.on('hold', this._onHold.bind(this)); + /** + * Create an array containing all items being a range (having an end date) + * @param array + * @returns {Array} + * @private + */ + ItemSet.prototype._constructByEndArray = function(array) { + var endArray = []; - // mouse wheel for zooming - this.body.emitter.on('mousewheel', this._onMouseWheel.bind(this)); - this.body.emitter.on('DOMMouseScroll', this._onMouseWheel.bind(this)); // For FF - - // pinch to zoom - this.body.emitter.on('touch', this._onTouch.bind(this)); - this.body.emitter.on('pinch', this._onPinch.bind(this)); - - this.setOptions(options); - } - - Range.prototype = new Component(); + for (var i = 0; i < array.length; i++) { + if (array[i] instanceof ItemRange) { + endArray.push(array[i]); + } + } + return endArray; + }; /** - * Set options for the range controller - * @param {Object} options Available options: - * {Number | Date | String} start Start date for the range - * {Number | Date | String} end End date for the range - * {Number} min Minimum value for start - * {Number} max Maximum value for end - * {Number} zoomMin Set a minimum value for - * (end - start). - * {Number} zoomMax Set a maximum value for - * (end - start). - * {Boolean} moveable Enable moving of the range - * by dragging. True by default - * {Boolean} zoomable Enable zooming of the range - * by pinching/scrolling. True by default + * Register the clicked item on touch, before dragStart is initiated. + * + * dragStart is initiated from a mousemove event, which can have left the item + * already resulting in an item == null + * + * @param {Event} event + * @private */ - Range.prototype.setOptions = function (options) { - if (options) { - // copy the options that we know - var fields = ['direction', 'min', 'max', 'zoomMin', 'zoomMax', 'moveable', 'zoomable']; - util.selectiveExtend(fields, this.options, options); - - if ('start' in options || 'end' in options) { - // apply a new range. both start and end are optional - this.setRange(options.start, options.end); - } - } + ItemSet.prototype._onTouch = function (event) { + // store the touched item, used in _onDragStart + this.touchParams.item = ItemSet.itemFromTarget(event); }; /** - * Test whether direction has a valid value - * @param {String} direction 'horizontal' or 'vertical' + * Start dragging the selected events + * @param {Event} event + * @private */ - function validateDirection (direction) { - if (direction != 'horizontal' && direction != 'vertical') { - throw new TypeError('Unknown direction "' + direction + '". ' + - 'Choose "horizontal" or "vertical".'); + ItemSet.prototype._onDragStart = function (event) { + if (!this.options.editable.updateTime && !this.options.editable.updateGroup) { + return; } - } - /** - * Set a new start and end range - * @param {Number} [start] - * @param {Number} [end] - */ - Range.prototype.setRange = function(start, end) { - var changed = this._applyRange(start, end); - if (changed) { - var params = { - start: new Date(this.start), - end: new Date(this.end) - }; - this.body.emitter.emit('rangechange', params); - this.body.emitter.emit('rangechanged', params); - } - }; + var item = this.touchParams.item || null, + me = this, + props; - /** - * Set a new start and end range. This method is the same as setRange, but - * does not trigger a range change and range changed event, and it returns - * true when the range is changed - * @param {Number} [start] - * @param {Number} [end] - * @return {Boolean} changed - * @private - */ - Range.prototype._applyRange = function(start, end) { - var newStart = (start != null) ? util.convert(start, 'Date').valueOf() : this.start, - newEnd = (end != null) ? util.convert(end, 'Date').valueOf() : this.end, - max = (this.options.max != null) ? util.convert(this.options.max, 'Date').valueOf() : null, - min = (this.options.min != null) ? util.convert(this.options.min, 'Date').valueOf() : null, - diff; + if (item && item.selected) { + var dragLeftItem = event.target.dragLeftItem; + var dragRightItem = event.target.dragRightItem; - // check for valid number - if (isNaN(newStart) || newStart === null) { - throw new Error('Invalid start "' + start + '"'); - } - if (isNaN(newEnd) || newEnd === null) { - throw new Error('Invalid end "' + end + '"'); - } + if (dragLeftItem) { + props = { + item: dragLeftItem + }; - // prevent start < end - if (newEnd < newStart) { - newEnd = newStart; - } + if (me.options.editable.updateTime) { + props.start = item.data.start.valueOf(); + } + if (me.options.editable.updateGroup) { + if ('group' in item.data) props.group = item.data.group; + } - // prevent start < min - if (min !== null) { - if (newStart < min) { - diff = (min - newStart); - newStart += diff; - newEnd += diff; + this.touchParams.itemProps = [props]; + } + else if (dragRightItem) { + props = { + item: dragRightItem + }; - // prevent end > max - if (max != null) { - if (newEnd > max) { - newEnd = max; - } + if (me.options.editable.updateTime) { + props.end = item.data.end.valueOf(); + } + if (me.options.editable.updateGroup) { + if ('group' in item.data) props.group = item.data.group; } - } - } - // prevent end > max - if (max !== null) { - if (newEnd > max) { - diff = (newEnd - max); - newStart -= diff; - newEnd -= diff; + this.touchParams.itemProps = [props]; + } + else { + this.touchParams.itemProps = this.getSelection().map(function (id) { + var item = me.items[id]; + var props = { + item: item + }; - // prevent start < min - if (min != null) { - if (newStart < min) { - newStart = min; + if (me.options.editable.updateTime) { + if ('start' in item.data) props.start = item.data.start.valueOf(); + if ('end' in item.data) props.end = item.data.end.valueOf(); } - } + if (me.options.editable.updateGroup) { + if ('group' in item.data) props.group = item.data.group; + } + + return props; + }); } + + event.stopPropagation(); } + }; - // prevent (end-start) < zoomMin - if (this.options.zoomMin !== null) { - var zoomMin = parseFloat(this.options.zoomMin); - if (zoomMin < 0) { - zoomMin = 0; - } - if ((newEnd - newStart) < zoomMin) { - if ((this.end - this.start) === zoomMin) { - // ignore this action, we are already zoomed to the minimum - newStart = this.start; - newEnd = this.end; - } - else { - // zoom to the minimum - diff = (zoomMin - (newEnd - newStart)); - newStart -= diff / 2; - newEnd += diff / 2; + /** + * Drag selected items + * @param {Event} event + * @private + */ + ItemSet.prototype._onDrag = function (event) { + if (this.touchParams.itemProps) { + var range = this.body.range, + snap = this.body.util.snap || null, + deltaX = event.gesture.deltaX, + scale = (this.props.width / (range.end - range.start)), + offset = deltaX / scale; + + // move + this.touchParams.itemProps.forEach(function (props) { + if ('start' in props) { + var start = new Date(props.start + offset); + props.item.data.start = snap ? snap(start) : start; } - } - } - // prevent (end-start) > zoomMax - if (this.options.zoomMax !== null) { - var zoomMax = parseFloat(this.options.zoomMax); - if (zoomMax < 0) { - zoomMax = 0; - } - if ((newEnd - newStart) > zoomMax) { - if ((this.end - this.start) === zoomMax) { - // ignore this action, we are already zoomed to the maximum - newStart = this.start; - newEnd = this.end; + if ('end' in props) { + var end = new Date(props.end + offset); + props.item.data.end = snap ? snap(end) : end; } - else { - // zoom to the maximum - diff = ((newEnd - newStart) - zoomMax); - newStart += diff / 2; - newEnd -= diff / 2; + + if ('group' in props) { + // drag from one group to another + var group = ItemSet.groupFromTarget(event); + _moveToGroup(props.item, group); } - } - } + }); - var changed = (this.start != newStart || this.end != newEnd); + // TODO: implement onMoving handler - this.start = newStart; - this.end = newEnd; + this.stackDirty = true; // force re-stacking of all items next redraw + this.body.emitter.emit('change'); - return changed; + event.stopPropagation(); + } }; /** - * Retrieve the current range. - * @return {Object} An object with start and end properties + * Move an item to another group + * @param {Item} item + * @param {Group} group + * @private */ - Range.prototype.getRange = function() { - return { - start: this.start, - end: this.end - }; - }; - - /** - * Calculate the conversion offset and scale for current range, based on - * the provided width - * @param {Number} width - * @returns {{offset: number, scale: number}} conversion - */ - Range.prototype.conversion = function (width) { - return Range.conversion(this.start, this.end, width); - }; + function _moveToGroup (item, group) { + if (group && group.groupId != item.data.group) { + var oldGroup = item.parent; + oldGroup.remove(item); + oldGroup.order(); + group.add(item); + group.order(); - /** - * Static method to calculate the conversion offset and scale for a range, - * based on the provided start, end, and width - * @param {Number} start - * @param {Number} end - * @param {Number} width - * @returns {{offset: number, scale: number}} conversion - */ - Range.conversion = function (start, end, width) { - if (width != 0 && (end - start != 0)) { - return { - offset: start, - scale: width / (end - start) - } - } - else { - return { - offset: 0, - scale: 1 - }; + item.data.group = group.groupId; } - }; + } /** - * Start dragging horizontally or vertically + * End of dragging selected items * @param {Event} event * @private */ - Range.prototype._onDragStart = function(event) { - // only allow dragging when configured as movable - if (!this.options.moveable) return; + ItemSet.prototype._onDragEnd = function (event) { + if (this.touchParams.itemProps) { + // prepare a change set for the changed items + var changes = [], + me = this, + dataset = this.itemsData.getDataSet(); - // refuse to drag when we where pinching to prevent the timeline make a jump - // when releasing the fingers in opposite order from the touch screen - if (!this.props.touch.allowDragging) return; + var itemProps = this.touchParams.itemProps ; + this.touchParams.itemProps = null; + itemProps.forEach(function (props) { + var id = props.item.id, + itemData = me.itemsData.get(id, me.itemOptions); - this.props.touch.start = this.start; - this.props.touch.end = this.end; + var changed = false; + if ('start' in props.item.data) { + changed = (props.start != props.item.data.start.valueOf()); + itemData.start = util.convert(props.item.data.start, + dataset._options.type && dataset._options.type.start || 'Date'); + } + if ('end' in props.item.data) { + changed = changed || (props.end != props.item.data.end.valueOf()); + itemData.end = util.convert(props.item.data.end, + dataset._options.type && dataset._options.type.end || 'Date'); + } + if ('group' in props.item.data) { + changed = changed || (props.group != props.item.data.group); + itemData.group = props.item.data.group; + } - if (this.body.dom.root) { - this.body.dom.root.style.cursor = 'move'; + // only apply changes when start or end is actually changed + if (changed) { + me.options.onMove(itemData, function (itemData) { + if (itemData) { + // apply changes + itemData[dataset._fieldId] = id; // ensure the item contains its id (can be undefined) + changes.push(itemData); + } + else { + // restore original values + if ('start' in props) props.item.data.start = props.start; + if ('end' in props) props.item.data.end = props.end; + if ('group' in props && props.item.data.group != props.group) { + var group = me.groups[props.group]; + _moveToGroup(props.item, group); + } + + me.stackDirty = true; // force re-stacking of all items next redraw + me.body.emitter.emit('change'); + } + }); + } + }); + + // apply the changes to the data (if there are changes) + if (changes.length) { + dataset.update(changes); + } + + event.stopPropagation(); } }; /** - * Perform dragging operation + * Handle selecting/deselecting an item when tapping it * @param {Event} event * @private */ - Range.prototype._onDrag = function (event) { - // only allow dragging when configured as movable - if (!this.options.moveable) return; - var direction = this.options.direction; - validateDirection(direction); - // refuse to drag when we where pinching to prevent the timeline make a jump - // when releasing the fingers in opposite order from the touch screen - if (!this.props.touch.allowDragging) return; - var delta = (direction == 'horizontal') ? event.gesture.deltaX : event.gesture.deltaY, - interval = (this.props.touch.end - this.props.touch.start), - width = (direction == 'horizontal') ? this.body.domProps.center.width : this.body.domProps.center.height, - diffRange = -delta / width * interval; - this._applyRange(this.props.touch.start + diffRange, this.props.touch.end + diffRange); - this.body.emitter.emit('rangechange', { - start: new Date(this.start), - end: new Date(this.end) - }); - }; + ItemSet.prototype._onSelectItem = function (event) { + if (!this.options.selectable) return; - /** - * Stop dragging operation - * @param {event} event - * @private - */ - Range.prototype._onDragEnd = function (event) { - // only allow dragging when configured as movable - if (!this.options.moveable) return; + var ctrlKey = event.gesture.srcEvent && event.gesture.srcEvent.ctrlKey; + var shiftKey = event.gesture.srcEvent && event.gesture.srcEvent.shiftKey; + if (ctrlKey || shiftKey) { + this._onMultiSelectItem(event); + return; + } - // refuse to drag when we where pinching to prevent the timeline make a jump - // when releasing the fingers in opposite order from the touch screen - if (!this.props.touch.allowDragging) return; + var oldSelection = this.getSelection(); - if (this.body.dom.root) { - this.body.dom.root.style.cursor = 'auto'; + var item = ItemSet.itemFromTarget(event); + var selection = item ? [item.id] : []; + this.setSelection(selection); + + var newSelection = this.getSelection(); + + // emit a select event, + // except when old selection is empty and new selection is still empty + if (newSelection.length > 0 || oldSelection.length > 0) { + this.body.emitter.emit('select', { + items: this.getSelection() + }); } - // fire a rangechanged event - this.body.emitter.emit('rangechanged', { - start: new Date(this.start), - end: new Date(this.end) - }); + event.stopPropagation(); }; /** - * Event handler for mouse wheel event, used to zoom - * Code from http://adomas.org/javascript-mouse-wheel/ - * @param {Event} event + * Handle creation and updates of an item on double tap + * @param event * @private */ - Range.prototype._onMouseWheel = function(event) { - // only allow zooming when configured as zoomable and moveable - if (!(this.options.zoomable && this.options.moveable)) return; + ItemSet.prototype._onAddItem = function (event) { + if (!this.options.selectable) return; + if (!this.options.editable.add) return; - // retrieve delta - var delta = 0; - if (event.wheelDelta) { /* IE/Opera. */ - delta = event.wheelDelta / 120; - } else if (event.detail) { /* Mozilla case. */ - // In Mozilla, sign of delta is different than in IE. - // Also, delta is multiple of 3. - delta = -event.detail / 3; - } + var me = this, + snap = this.body.util.snap || null, + item = ItemSet.itemFromTarget(event); - // If delta is nonzero, handle it. - // Basically, delta is now positive if wheel was scrolled up, - // and negative, if wheel was scrolled down. - if (delta) { - // perform the zoom action. Delta is normally 1 or -1 + if (item) { + // update item - // adjust a negative delta such that zooming in with delta 0.1 - // equals zooming out with a delta -0.1 - var scale; - if (delta < 0) { - scale = 1 - (delta / 5); - } - else { - scale = 1 / (1 + (delta / 5)) ; + // execute async handler to update the item (or cancel it) + var itemData = me.itemsData.get(item.id); // get a clone of the data from the dataset + this.options.onUpdate(itemData, function (itemData) { + if (itemData) { + me.itemsData.update(itemData); + } + }); + } + else { + // add item + var xAbs = util.getAbsoluteLeft(this.dom.frame); + var x = event.gesture.center.pageX - xAbs; + var start = this.body.util.toTime(x); + var newItem = { + start: snap ? snap(start) : start, + content: 'new item' + }; + + // when default type is a range, add a default end date to the new item + if (this.options.type === 'range') { + var end = this.body.util.toTime(x + this.props.width / 5); + newItem.end = snap ? snap(end) : end; } - // calculate center, the date to zoom around - var gesture = hammerUtil.fakeGesture(this, event), - pointer = getPointer(gesture.center, this.body.dom.center), - pointerDate = this._pointerToDate(pointer); + newItem[this.itemsData.fieldId] = util.randomUUID(); - this.zoom(scale, pointerDate); - } + var group = ItemSet.groupFromTarget(event); + if (group) { + newItem.group = group.groupId; + } - // Prevent default actions caused by mouse wheel - // (else the page and timeline both zoom and scroll) - event.preventDefault(); + // execute async handler to customize (or cancel) adding an item + this.options.onAdd(newItem, function (item) { + if (item) { + me.itemsData.add(newItem); + // TODO: need to trigger a redraw? + } + }); + } }; /** - * Start of a touch gesture + * Handle selecting/deselecting multiple items when holding an item + * @param {Event} event * @private */ - Range.prototype._onTouch = function (event) { - this.props.touch.start = this.start; - this.props.touch.end = this.end; - this.props.touch.allowDragging = true; - this.props.touch.center = null; - }; - - /** - * On start of a hold gesture - * @private - */ - Range.prototype._onHold = function () { - this.props.touch.allowDragging = false; - }; - - /** - * Handle pinch event - * @param {Event} event - * @private - */ - Range.prototype._onPinch = function (event) { - // only allow zooming when configured as zoomable and moveable - if (!(this.options.zoomable && this.options.moveable)) return; + ItemSet.prototype._onMultiSelectItem = function (event) { + if (!this.options.selectable) return; - this.props.touch.allowDragging = false; + var selection, + item = ItemSet.itemFromTarget(event); - if (event.gesture.touches.length > 1) { - if (!this.props.touch.center) { - this.props.touch.center = getPointer(event.gesture.center, this.body.dom.center); + if (item) { + // multi select items + selection = this.getSelection(); // current selection + var index = selection.indexOf(item.id); + if (index == -1) { + // item is not yet selected -> select it + selection.push(item.id); } + else { + // item is already selected -> deselect it + selection.splice(index, 1); + } + this.setSelection(selection); - var scale = 1 / event.gesture.scale, - initDate = this._pointerToDate(this.props.touch.center); - - // calculate new start and end - var newStart = parseInt(initDate + (this.props.touch.start - initDate) * scale); - var newEnd = parseInt(initDate + (this.props.touch.end - initDate) * scale); - - // apply new range - this.setRange(newStart, newEnd); - } - }; - - /** - * Helper function to calculate the center date for zooming - * @param {{x: Number, y: Number}} pointer - * @return {number} date - * @private - */ - Range.prototype._pointerToDate = function (pointer) { - var conversion; - var direction = this.options.direction; - - validateDirection(direction); + this.body.emitter.emit('select', { + items: this.getSelection() + }); - if (direction == 'horizontal') { - var width = this.body.domProps.center.width; - conversion = this.conversion(width); - return pointer.x / conversion.scale + conversion.offset; - } - else { - var height = this.body.domProps.center.height; - conversion = this.conversion(height); - return pointer.y / conversion.scale + conversion.offset; + event.stopPropagation(); } }; /** - * Get the pointer location relative to the location of the dom element - * @param {{pageX: Number, pageY: Number}} touch - * @param {Element} element HTML DOM element - * @return {{x: Number, y: Number}} pointer - * @private - */ - function getPointer (touch, element) { - return { - x: touch.pageX - util.getAbsoluteLeft(element), - y: touch.pageY - util.getAbsoluteTop(element) - }; - } - - /** - * Zoom the range the given scale in or out. Start and end date will - * be adjusted, and the timeline will be redrawn. You can optionally give a - * date around which to zoom. - * For example, try scale = 0.9 or 1.1 - * @param {Number} scale Scaling factor. Values above 1 will zoom out, - * values below 1 will zoom in. - * @param {Number} [center] Value representing a date around which will - * be zoomed. + * Find an item from an event target: + * searches for the attribute 'timeline-item' in the event target's element tree + * @param {Event} event + * @return {Item | null} item */ - Range.prototype.zoom = function(scale, center) { - // if centerDate is not provided, take it half between start Date and end Date - if (center == null) { - center = (this.start + this.end) / 2; + ItemSet.itemFromTarget = function(event) { + var target = event.target; + while (target) { + if (target.hasOwnProperty('timeline-item')) { + return target['timeline-item']; + } + target = target.parentNode; } - // calculate new start and end - var newStart = center + (this.start - center) * scale; - var newEnd = center + (this.end - center) * scale; - - this.setRange(newStart, newEnd); + return null; }; /** - * Move the range with a given delta to the left or right. Start and end - * value will be adjusted. For example, try delta = 0.1 or -0.1 - * @param {Number} delta Moving amount. Positive value will move right, - * negative value will move left + * Find the Group from an event target: + * searches for the attribute 'timeline-group' in the event target's element tree + * @param {Event} event + * @return {Group | null} group */ - Range.prototype.move = function(delta) { - // zoom start Date and end Date relative to the centerDate - var diff = (this.end - this.start); - - // apply new values - var newStart = this.start + diff * delta; - var newEnd = this.end + diff * delta; - - // TODO: reckon with min and max range + ItemSet.groupFromTarget = function(event) { + var target = event.target; + while (target) { + if (target.hasOwnProperty('timeline-group')) { + return target['timeline-group']; + } + target = target.parentNode; + } - this.start = newStart; - this.end = newEnd; + return null; }; /** - * Move the range to a new center point - * @param {Number} moveTo New center point of the range + * Find the ItemSet from an event target: + * searches for the attribute 'timeline-itemset' in the event target's element tree + * @param {Event} event + * @return {ItemSet | null} item */ - Range.prototype.moveTo = function(moveTo) { - var center = (this.start + this.end) / 2; - - var diff = center - moveTo; - - // calculate new start and end - var newStart = this.start - diff; - var newEnd = this.end - diff; + ItemSet.itemSetFromTarget = function(event) { + var target = event.target; + while (target) { + if (target.hasOwnProperty('timeline-itemset')) { + return target['timeline-itemset']; + } + target = target.parentNode; + } - this.setRange(newStart, newEnd); + return null; }; - module.exports = Range; + module.exports = ItemSet; /***/ }, -/* 21 */ +/* 25 */ /***/ function(module, exports, __webpack_require__) { - var Hammer = __webpack_require__(18); + var util = __webpack_require__(1); + var DOMutil = __webpack_require__(2); + var Component = __webpack_require__(18); /** - * Fake a hammer.js gesture. Event can be a ScrollEvent or MouseMoveEvent - * @param {Element} element - * @param {Event} event + * Legend for Graph2d */ - exports.fakeGesture = function(element, event) { - var eventType = null; - - // for hammer.js 1.0.5 - // var gesture = Hammer.event.collectEventData(this, eventType, event); - - // for hammer.js 1.0.6+ - var touches = Hammer.event.getTouchList(event, eventType); - var gesture = Hammer.event.collectEventData(this, eventType, touches, event); - - // on IE in standards mode, no touches are recognized by hammer.js, - // resulting in NaN values for center.pageX and center.pageY - if (isNaN(gesture.center.pageX)) { - gesture.center.pageX = event.pageX; - } - if (isNaN(gesture.center.pageY)) { - gesture.center.pageY = event.pageY; + function Legend(body, options, side) { + this.body = body; + this.defaultOptions = { + enabled: true, + icons: true, + iconSize: 20, + iconSpacing: 6, + left: { + visible: true, + position: 'top-left' // top/bottom - left,center,right + }, + right: { + visible: true, + position: 'top-left' // top/bottom - left,center,right + } } + this.side = side; + this.options = util.extend({},this.defaultOptions); - return gesture; - }; + this.svgElements = {}; + this.dom = {}; + this.groups = {}; + this.amountOfGroups = 0; + this._create(); + this.setOptions(options); + } -/***/ }, -/* 22 */ -/***/ function(module, exports, __webpack_require__) { + Legend.prototype = new Component(); - /** - * Prototype for visual components - * @param {{dom: Object, domProps: Object, emitter: Emitter, range: Range}} [body] - * @param {Object} [options] - */ - function Component (body, options) { - this.options = null; - this.props = null; - } - /** - * Set options for the component. The new options will be merged into the - * current options. - * @param {Object} options - */ - Component.prototype.setOptions = function(options) { - if (options) { - util.extend(this.options, options); + Legend.prototype.addGroup = function(label, graphOptions) { + if (!this.groups.hasOwnProperty(label)) { + this.groups[label] = graphOptions; } + this.amountOfGroups += 1; }; - /** - * Repaint the component - * @return {boolean} Returns true if the component is resized - */ - Component.prototype.redraw = function() { - // should be implemented by the component - return false; + Legend.prototype.updateGroup = function(label, graphOptions) { + this.groups[label] = graphOptions; + }; + + Legend.prototype.removeGroup = function(label) { + if (this.groups.hasOwnProperty(label)) { + delete this.groups[label]; + this.amountOfGroups -= 1; + } + }; + + Legend.prototype._create = function() { + this.dom.frame = document.createElement('div'); + this.dom.frame.className = 'legend'; + this.dom.frame.style.position = "absolute"; + this.dom.frame.style.top = "10px"; + this.dom.frame.style.display = "block"; + + this.dom.textArea = document.createElement('div'); + this.dom.textArea.className = 'legendText'; + this.dom.textArea.style.position = "relative"; + this.dom.textArea.style.top = "0px"; + + this.svg = document.createElementNS('http://www.w3.org/2000/svg',"svg"); + this.svg.style.position = 'absolute'; + this.svg.style.top = 0 +'px'; + this.svg.style.width = this.options.iconSize + 5 + 'px'; + + this.dom.frame.appendChild(this.svg); + this.dom.frame.appendChild(this.dom.textArea); }; /** - * Destroy the component. Cleanup DOM and event listeners + * Hide the component from the DOM */ - Component.prototype.destroy = function() { - // should be implemented by the component + Legend.prototype.hide = function() { + // remove the frame containing the items + if (this.dom.frame.parentNode) { + this.dom.frame.parentNode.removeChild(this.dom.frame); + } }; /** - * Test whether the component is resized since the last time _isResized() was - * called. - * @return {Boolean} Returns true if the component is resized - * @protected + * Show the component in the DOM (when not already visible). + * @return {Boolean} changed */ - Component.prototype._isResized = function() { - var resized = (this.props._previousWidth !== this.props.width || - this.props._previousHeight !== this.props.height); + Legend.prototype.show = function() { + // show frame containing the items + if (!this.dom.frame.parentNode) { + this.body.dom.center.appendChild(this.dom.frame); + } + }; - this.props._previousWidth = this.props.width; - this.props._previousHeight = this.props.height; + Legend.prototype.setOptions = function(options) { + var fields = ['enabled','orientation','icons','left','right']; + util.selectiveDeepExtend(fields, this.options, options); + }; - return resized; + Legend.prototype.redraw = function() { + var activeGroups = 0; + for (var groupId in this.groups) { + if (this.groups.hasOwnProperty(groupId)) { + if (this.groups[groupId].visible == true) { + activeGroups++; + } + } + } + + if (this.options[this.side].visible == false || this.amountOfGroups == 0 || this.options.enabled == false || activeGroups == 0) { + this.hide(); + } + else { + this.show(); + if (this.options[this.side].position == 'top-left' || this.options[this.side].position == 'bottom-left') { + this.dom.frame.style.left = '4px'; + this.dom.frame.style.textAlign = "left"; + this.dom.textArea.style.textAlign = "left"; + this.dom.textArea.style.left = (this.options.iconSize + 15) + 'px'; + this.dom.textArea.style.right = ''; + this.svg.style.left = 0 +'px'; + this.svg.style.right = ''; + } + else { + this.dom.frame.style.right = '4px'; + this.dom.frame.style.textAlign = "right"; + this.dom.textArea.style.textAlign = "right"; + this.dom.textArea.style.right = (this.options.iconSize + 15) + 'px'; + this.dom.textArea.style.left = ''; + this.svg.style.right = 0 +'px'; + this.svg.style.left = ''; + } + + if (this.options[this.side].position == 'top-left' || this.options[this.side].position == 'top-right') { + this.dom.frame.style.top = 4 - Number(this.body.dom.center.style.top.replace("px","")) + 'px'; + this.dom.frame.style.bottom = ''; + } + else { + this.dom.frame.style.bottom = 4 - Number(this.body.dom.center.style.top.replace("px","")) + 'px'; + this.dom.frame.style.top = ''; + } + + if (this.options.icons == false) { + this.dom.frame.style.width = this.dom.textArea.offsetWidth + 10 + 'px'; + this.dom.textArea.style.right = ''; + this.dom.textArea.style.left = ''; + this.svg.style.width = '0px'; + } + else { + this.dom.frame.style.width = this.options.iconSize + 15 + this.dom.textArea.offsetWidth + 10 + 'px' + this.drawLegendIcons(); + } + + var content = ''; + for (var groupId in this.groups) { + if (this.groups.hasOwnProperty(groupId)) { + if (this.groups[groupId].visible == true) { + content += this.groups[groupId].content + '
'; + } + } + } + this.dom.textArea.innerHTML = content; + this.dom.textArea.style.lineHeight = ((0.75 * this.options.iconSize) + this.options.iconSpacing) + 'px'; + } }; - module.exports = Component; + Legend.prototype.drawLegendIcons = function() { + if (this.dom.frame.parentNode) { + DOMutil.prepareElements(this.svgElements); + var padding = window.getComputedStyle(this.dom.frame).paddingTop; + var iconOffset = Number(padding.replace('px','')); + var x = iconOffset; + var iconWidth = this.options.iconSize; + var iconHeight = 0.75 * this.options.iconSize; + var y = iconOffset + 0.5 * iconHeight + 3; + + this.svg.style.width = iconWidth + 5 + iconOffset + 'px'; + + for (var groupId in this.groups) { + if (this.groups.hasOwnProperty(groupId)) { + if (this.groups[groupId].visible == true) { + this.groups[groupId].drawIcon(x, y, this.svgElements, this.svg, iconWidth, iconHeight); + y += iconHeight + this.options.iconSpacing; + } + } + } + + DOMutil.cleanupElements(this.svgElements); + } + }; + + module.exports = Legend; /***/ }, -/* 23 */ +/* 26 */ /***/ function(module, exports, __webpack_require__) { - var Emitter = __webpack_require__(10); - var Hammer = __webpack_require__(18); var util = __webpack_require__(1); - var DataSet = __webpack_require__(7); - var DataView = __webpack_require__(8); - var Range = __webpack_require__(20); - var TimeAxis = __webpack_require__(24); - var CurrentTime = __webpack_require__(26); - var CustomTime = __webpack_require__(27); - var ItemSet = __webpack_require__(28); + var DOMutil = __webpack_require__(2); + var DataSet = __webpack_require__(3); + var DataView = __webpack_require__(4); + var Component = __webpack_require__(18); + var DataAxis = __webpack_require__(21); + var GraphGroup = __webpack_require__(22); + var Legend = __webpack_require__(25); + + var UNGROUPED = '__ungrouped__'; // reserved group id for ungrouped items /** - * Create a timeline visualization - * @param {HTMLElement} container - * @param {vis.DataSet | Array | google.visualization.DataTable} [items] - * @param {Object} [options] See Core.setOptions for the available options. + * This is the constructor of the LineGraph. It requires a Timeline body and options. + * + * @param body + * @param options * @constructor */ - function Core () {} + function LineGraph(body, options) { + this.id = util.randomUUID(); + this.body = body; - // turn Core into an event emitter - Emitter(Core.prototype); + this.defaultOptions = { + yAxisOrientation: 'left', + defaultGroup: 'default', + sort: true, + sampling: true, + graphHeight: '400px', + shaded: { + enabled: false, + orientation: 'bottom' // top, bottom + }, + style: 'line', // line, bar + barChart: { + width: 50, + allowOverlap: true, + align: 'center' // left, center, right + }, + catmullRom: { + enabled: true, + parametrization: 'centripetal', // uniform (alpha = 0.0), chordal (alpha = 1.0), centripetal (alpha = 0.5) + alpha: 0.5 + }, + drawPoints: { + enabled: true, + size: 6, + style: 'square' // square, circle + }, + dataAxis: { + showMinorLabels: true, + showMajorLabels: true, + icons: false, + width: '40px', + visible: true + }, + legend: { + enabled: false, + icons: true, + left: { + visible: true, + position: 'top-left' // top/bottom - left,right + }, + right: { + visible: true, + position: 'top-right' // top/bottom - left,right + } + } + }; - /** - * Create the main DOM for the Core: a root panel containing left, right, - * top, bottom, content, and background panel. - * @param {Element} container The container element where the Core will - * be attached. - * @private - */ - Core.prototype._create = function (container) { + // options is shared by this ItemSet and all its items + this.options = util.extend({}, this.defaultOptions); this.dom = {}; + this.props = {}; + this.hammer = null; + this.groups = {}; - this.dom.root = document.createElement('div'); - this.dom.background = document.createElement('div'); - this.dom.backgroundVertical = document.createElement('div'); - this.dom.backgroundHorizontal = document.createElement('div'); - this.dom.centerContainer = document.createElement('div'); - this.dom.leftContainer = document.createElement('div'); - this.dom.rightContainer = document.createElement('div'); - this.dom.center = document.createElement('div'); - this.dom.left = document.createElement('div'); - this.dom.right = document.createElement('div'); - this.dom.top = document.createElement('div'); - this.dom.bottom = document.createElement('div'); - this.dom.shadowTop = document.createElement('div'); - this.dom.shadowBottom = document.createElement('div'); - this.dom.shadowTopLeft = document.createElement('div'); - this.dom.shadowBottomLeft = document.createElement('div'); - this.dom.shadowTopRight = document.createElement('div'); - this.dom.shadowBottomRight = document.createElement('div'); + var me = this; + this.itemsData = null; // DataSet + this.groupsData = null; // DataSet - this.dom.background.className = 'vispanel background'; - this.dom.backgroundVertical.className = 'vispanel background vertical'; - this.dom.backgroundHorizontal.className = 'vispanel background horizontal'; - this.dom.centerContainer.className = 'vispanel center'; - this.dom.leftContainer.className = 'vispanel left'; - this.dom.rightContainer.className = 'vispanel right'; - this.dom.top.className = 'vispanel top'; - this.dom.bottom.className = 'vispanel bottom'; - this.dom.left.className = 'content'; - this.dom.center.className = 'content'; - this.dom.right.className = 'content'; - this.dom.shadowTop.className = 'shadow top'; - this.dom.shadowBottom.className = 'shadow bottom'; - this.dom.shadowTopLeft.className = 'shadow top'; - this.dom.shadowBottomLeft.className = 'shadow bottom'; - this.dom.shadowTopRight.className = 'shadow top'; - this.dom.shadowBottomRight.className = 'shadow bottom'; - - this.dom.root.appendChild(this.dom.background); - this.dom.root.appendChild(this.dom.backgroundVertical); - this.dom.root.appendChild(this.dom.backgroundHorizontal); - this.dom.root.appendChild(this.dom.centerContainer); - this.dom.root.appendChild(this.dom.leftContainer); - this.dom.root.appendChild(this.dom.rightContainer); - this.dom.root.appendChild(this.dom.top); - this.dom.root.appendChild(this.dom.bottom); - - this.dom.centerContainer.appendChild(this.dom.center); - this.dom.leftContainer.appendChild(this.dom.left); - this.dom.rightContainer.appendChild(this.dom.right); + // listeners for the DataSet of the items + this.itemListeners = { + 'add': function (event, params, senderId) { + me._onAdd(params.items); + }, + 'update': function (event, params, senderId) { + me._onUpdate(params.items); + }, + 'remove': function (event, params, senderId) { + me._onRemove(params.items); + } + }; - this.dom.centerContainer.appendChild(this.dom.shadowTop); - this.dom.centerContainer.appendChild(this.dom.shadowBottom); - this.dom.leftContainer.appendChild(this.dom.shadowTopLeft); - this.dom.leftContainer.appendChild(this.dom.shadowBottomLeft); - this.dom.rightContainer.appendChild(this.dom.shadowTopRight); - this.dom.rightContainer.appendChild(this.dom.shadowBottomRight); + // listeners for the DataSet of the groups + this.groupListeners = { + 'add': function (event, params, senderId) { + me._onAddGroups(params.items); + }, + 'update': function (event, params, senderId) { + me._onUpdateGroups(params.items); + }, + 'remove': function (event, params, senderId) { + me._onRemoveGroups(params.items); + } + }; - this.on('rangechange', this.redraw.bind(this)); - this.on('change', this.redraw.bind(this)); - this.on('touch', this._onTouch.bind(this)); - this.on('pinch', this._onPinch.bind(this)); - this.on('dragstart', this._onDragStart.bind(this)); - this.on('drag', this._onDrag.bind(this)); + this.items = {}; // object with an Item for every data item + this.selection = []; // list with the ids of all selected nodes + this.lastStart = this.body.range.start; + this.touchParams = {}; // stores properties while dragging - // create event listeners for all interesting events, these events will be - // emitted via emitter - this.hammer = Hammer(this.dom.root, { - prevent_default: true - }); - this.listeners = {}; + this.svgElements = {}; + this.setOptions(options); + this.groupsUsingDefaultStyles = [0]; - var me = this; - var events = [ - 'touch', 'pinch', - 'tap', 'doubletap', 'hold', - 'dragstart', 'drag', 'dragend', - 'mousewheel', 'DOMMouseScroll' // DOMMouseScroll is needed for Firefox - ]; - events.forEach(function (event) { - var listener = function () { - var args = [event].concat(Array.prototype.slice.call(arguments, 0)); - me.emit.apply(me, args); - }; - me.hammer.on(event, listener); - me.listeners[event] = listener; + this.body.emitter.on("rangechange",function() { + if (me.lastStart != 0) { + var offset = me.body.range.start - me.lastStart; + var range = me.body.range.end - me.body.range.start; + if (me.width != 0) { + var rangePerPixelInv = me.width/range; + var xOffset = offset * rangePerPixelInv; + me.svg.style.left = (-me.width - xOffset) + "px"; + } + } + }); + this.body.emitter.on("rangechanged", function() { + me.lastStart = me.body.range.start; + me.svg.style.left = util.option.asSize(-me.width); + me._updateGraph.apply(me); }); - // size properties of each of the panels - this.props = { - root: {}, - background: {}, - centerContainer: {}, - leftContainer: {}, - rightContainer: {}, - center: {}, - left: {}, - right: {}, - top: {}, - bottom: {}, - border: {}, - scrollTop: 0, - scrollTopMin: 0 - }; - this.touch = {}; // store state information needed for touch events + // create the HTML DOM + this._create(); + this.body.emitter.emit("change"); + } - // attach the root panel to the provided container - if (!container) throw new Error('No container provided'); - container.appendChild(this.dom.root); - }; + LineGraph.prototype = new Component(); /** - * Destroy the Core, clean up all DOM elements and event listeners. + * Create the HTML DOM for the ItemSet */ - Core.prototype.destroy = function () { - // unbind datasets - this.clear(); - - // remove all event listeners - this.off(); + LineGraph.prototype._create = function(){ + var frame = document.createElement('div'); + frame.className = 'LineGraph'; + this.dom.frame = frame; - // stop checking for changed size - this._stopAutoResize(); + // create svg element for graph drawing. + this.svg = document.createElementNS('http://www.w3.org/2000/svg',"svg"); + this.svg.style.position = "relative"; + this.svg.style.height = ('' + this.options.graphHeight).replace("px",'') + 'px'; + this.svg.style.display = "block"; + frame.appendChild(this.svg); - // remove from DOM - if (this.dom.root.parentNode) { - this.dom.root.parentNode.removeChild(this.dom.root); - } - this.dom = null; + // data axis + this.options.dataAxis.orientation = 'left'; + this.yAxisLeft = new DataAxis(this.body, this.options.dataAxis, this.svg); - // cleanup hammer touch events - for (var event in this.listeners) { - if (this.listeners.hasOwnProperty(event)) { - delete this.listeners[event]; - } - } - this.listeners = null; - this.hammer = null; + this.options.dataAxis.orientation = 'right'; + this.yAxisRight = new DataAxis(this.body, this.options.dataAxis, this.svg); + delete this.options.dataAxis.orientation; - // give all components the opportunity to cleanup - this.components.forEach(function (component) { - component.destroy(); - }); + // legends + this.legendLeft = new Legend(this.body, this.options.legend, 'left'); + this.legendRight = new Legend(this.body, this.options.legend, 'right'); - this.body = null; + this.show(); }; - /** - * Set a custom time bar - * @param {Date} time + * set the options of the LineGraph. the mergeOptions is used for subObjects that have an enabled element. + * @param options */ - Core.prototype.setCustomTime = function (time) { - if (!this.customTime) { - throw new Error('Cannot get custom time: Custom time bar is not enabled'); - } + LineGraph.prototype.setOptions = function(options) { + if (options) { + var fields = ['sampling','defaultGroup','graphHeight','yAxisOrientation','style','barChart','dataAxis','sort']; + util.selectiveDeepExtend(fields, this.options, options); + util.mergeOptions(this.options, options,'catmullRom'); + util.mergeOptions(this.options, options,'drawPoints'); + util.mergeOptions(this.options, options,'shaded'); + util.mergeOptions(this.options, options,'legend'); - this.customTime.setCustomTime(time); + if (options.catmullRom) { + if (typeof options.catmullRom == 'object') { + if (options.catmullRom.parametrization) { + if (options.catmullRom.parametrization == 'uniform') { + this.options.catmullRom.alpha = 0; + } + else if (options.catmullRom.parametrization == 'chordal') { + this.options.catmullRom.alpha = 1.0; + } + else { + this.options.catmullRom.parametrization = 'centripetal'; + this.options.catmullRom.alpha = 0.5; + } + } + } + } + + if (this.yAxisLeft) { + if (options.dataAxis !== undefined) { + this.yAxisLeft.setOptions(this.options.dataAxis); + this.yAxisRight.setOptions(this.options.dataAxis); + } + } + + if (this.legendLeft) { + if (options.legend !== undefined) { + this.legendLeft.setOptions(this.options.legend); + this.legendRight.setOptions(this.options.legend); + } + } + + if (this.groups.hasOwnProperty(UNGROUPED)) { + this.groups[UNGROUPED].setOptions(options); + } + } + if (this.dom.frame) { + this._updateGraph(); + } }; /** - * Retrieve the current custom time. - * @return {Date} customTime + * Hide the component from the DOM */ - Core.prototype.getCustomTime = function() { - if (!this.customTime) { - throw new Error('Cannot get custom time: Custom time bar is not enabled'); + LineGraph.prototype.hide = function() { + // remove the frame containing the items + if (this.dom.frame.parentNode) { + this.dom.frame.parentNode.removeChild(this.dom.frame); } - - return this.customTime.getCustomTime(); }; - /** - * Get the id's of the currently visible items. - * @returns {Array} The ids of the visible items + * Show the component in the DOM (when not already visible). + * @return {Boolean} changed */ - Core.prototype.getVisibleItems = function() { - return this.itemSet && this.itemSet.getVisibleItems() || []; + LineGraph.prototype.show = function() { + // show frame containing the items + if (!this.dom.frame.parentNode) { + this.body.dom.center.appendChild(this.dom.frame); + } }; - /** - * Clear the Core. By Default, items, groups and options are cleared. - * Example usage: - * - * timeline.clear(); // clear items, groups, and options - * timeline.clear({options: true}); // clear options only - * - * @param {Object} [what] Optionally specify what to clear. By default: - * {items: true, groups: true, options: true} + * Set items + * @param {vis.DataSet | null} items */ - Core.prototype.clear = function(what) { - // clear items - if (!what || what.items) { - this.setItems(null); + LineGraph.prototype.setItems = function(items) { + var me = this, + ids, + oldItemsData = this.itemsData; + + // replace the dataset + if (!items) { + this.itemsData = null; + } + else if (items instanceof DataSet || items instanceof DataView) { + this.itemsData = items; + } + else { + throw new TypeError('Data must be an instance of DataSet or DataView'); } - // clear groups - if (!what || what.groups) { - this.setGroups(null); + if (oldItemsData) { + // unsubscribe from old dataset + util.forEach(this.itemListeners, function (callback, event) { + oldItemsData.off(event, callback); + }); + + // remove all drawn items + ids = oldItemsData.getIds(); + this._onRemove(ids); } - // clear options of timeline and of each of the components - if (!what || what.options) { - this.components.forEach(function (component) { - component.setOptions(component.defaultOptions); + if (this.itemsData) { + // subscribe to new dataset + var id = this.id; + util.forEach(this.itemListeners, function (callback, event) { + me.itemsData.on(event, callback, id); }); - this.setOptions(this.defaultOptions); // this will also do a redraw + // add all new items + ids = this.itemsData.getIds(); + this._onAdd(ids); } + this._updateUngrouped(); + this._updateGraph(); + this.redraw(); }; /** - * Set Core window such that it fits all items + * Set groups + * @param {vis.DataSet} groups */ - Core.prototype.fit = function() { - // apply the data range as range - var dataRange = this.getItemRange(); + LineGraph.prototype.setGroups = function(groups) { + var me = this, + ids; - // add 5% space on both sides - var start = dataRange.min; - var end = dataRange.max; - if (start != null && end != null) { - var interval = (end.valueOf() - start.valueOf()); - if (interval <= 0) { - // prevent an empty interval - interval = 24 * 60 * 60 * 1000; // 1 day - } - start = new Date(start.valueOf() - interval * 0.05); - end = new Date(end.valueOf() + interval * 0.05); + // unsubscribe from current dataset + if (this.groupsData) { + util.forEach(this.groupListeners, function (callback, event) { + me.groupsData.unsubscribe(event, callback); + }); + + // remove all drawn groups + ids = this.groupsData.getIds(); + this.groupsData = null; + this._onRemoveGroups(ids); // note: this will cause a redraw } - // skip range set if there is no start and end date - if (start === null && end === null) { - return; + // replace the dataset + if (!groups) { + this.groupsData = null; + } + else if (groups instanceof DataSet || groups instanceof DataView) { + this.groupsData = groups; + } + else { + throw new TypeError('Data must be an instance of DataSet or DataView'); } - this.range.setRange(start, end); + if (this.groupsData) { + // subscribe to new dataset + var id = this.id; + util.forEach(this.groupListeners, function (callback, event) { + me.groupsData.on(event, callback, id); + }); + + // draw all ms + ids = this.groupsData.getIds(); + this._onAddGroups(ids); + } + this._onUpdate(); + }; + + + + LineGraph.prototype._onUpdate = function(ids) { + this._updateUngrouped(); + this._updateAllGroupData(); + this._updateGraph(); + this.redraw(); + }; + LineGraph.prototype._onAdd = function (ids) {this._onUpdate(ids);}; + LineGraph.prototype._onRemove = function (ids) {this._onUpdate(ids);}; + LineGraph.prototype._onUpdateGroups = function (groupIds) { + for (var i = 0; i < groupIds.length; i++) { + var group = this.groupsData.get(groupIds[i]); + this._updateGroup(group, groupIds[i]); + } + + this._updateGraph(); + this.redraw(); }; + LineGraph.prototype._onAddGroups = function (groupIds) {this._onUpdateGroups(groupIds);}; + LineGraph.prototype._onRemoveGroups = function (groupIds) { + for (var i = 0; i < groupIds.length; i++) { + if (!this.groups.hasOwnProperty(groupIds[i])) { + if (this.groups[groupIds[i]].options.yAxisOrientation == 'right') { + this.yAxisRight.removeGroup(groupIds[i]); + this.legendRight.removeGroup(groupIds[i]); + this.legendRight.redraw(); + } + else { + this.yAxisLeft.removeGroup(groupIds[i]); + this.legendLeft.removeGroup(groupIds[i]); + this.legendLeft.redraw(); + } + delete this.groups[groupIds[i]]; + } + } + this._updateUngrouped(); + this._updateGraph(); + this.redraw(); + }; /** - * Set the visible window. Both parameters are optional, you can change only - * start or only end. Syntax: - * - * TimeLine.setWindow(start, end) - * TimeLine.setWindow(range) - * - * Where start and end can be a Date, number, or string, and range is an - * object with properties start and end. + * update a group object * - * @param {Date | Number | String | Object} [start] Start date of visible window - * @param {Date | Number | String} [end] End date of visible window + * @param group + * @param groupId + * @private */ - Core.prototype.setWindow = function(start, end) { - if (arguments.length == 1) { - var range = arguments[0]; - this.range.setRange(range.start, range.end); + LineGraph.prototype._updateGroup = function (group, groupId) { + if (!this.groups.hasOwnProperty(groupId)) { + this.groups[groupId] = new GraphGroup(group, groupId, this.options, this.groupsUsingDefaultStyles); + if (this.groups[groupId].options.yAxisOrientation == 'right') { + this.yAxisRight.addGroup(groupId, this.groups[groupId]); + this.legendRight.addGroup(groupId, this.groups[groupId]); + } + else { + this.yAxisLeft.addGroup(groupId, this.groups[groupId]); + this.legendLeft.addGroup(groupId, this.groups[groupId]); + } } else { - this.range.setRange(start, end); + this.groups[groupId].update(group); + if (this.groups[groupId].options.yAxisOrientation == 'right') { + this.yAxisRight.updateGroup(groupId, this.groups[groupId]); + this.legendRight.updateGroup(groupId, this.groups[groupId]); + } + else { + this.yAxisLeft.updateGroup(groupId, this.groups[groupId]); + this.legendLeft.updateGroup(groupId, this.groups[groupId]); + } } + this.legendLeft.redraw(); + this.legendRight.redraw(); }; - /** - * Get the visible window - * @return {{start: Date, end: Date}} Visible range - */ - Core.prototype.getWindow = function() { - var range = this.range.getRange(); - return { - start: new Date(range.start), - end: new Date(range.end) - }; + LineGraph.prototype._updateAllGroupData = function () { + if (this.itemsData != null) { + var groupsContent = {}; + for (var groupId in this.groups) { + if (this.groups.hasOwnProperty(groupId)) { + groupsContent[groupId] = []; + } + } + for (var itemId in this.itemsData._data) { + if (this.itemsData._data.hasOwnProperty(itemId)) { + var item = this.itemsData._data[itemId]; + item.x = util.convert(item.x,"Date"); + groupsContent[item.group].push(item); + } + } + for (var groupId in this.groups) { + if (this.groups.hasOwnProperty(groupId)) { + this.groups[groupId].setItems(groupsContent[groupId]); + } + } + } }; /** - * Force a redraw of the Core. Can be useful to manually redraw when - * option autoResize=false + * Create or delete the group holding all ungrouped items. This group is used when + * there are no groups specified. This anonymous group is called 'graph'. + * @protected */ - Core.prototype.redraw = function() { - var resized = false, - options = this.options, - props = this.props, - dom = this.dom; - - if (!dom) return; // when destroyed - - // update class names - dom.root.className = 'vis timeline root ' + options.orientation; - - // update root width and height options - dom.root.style.maxHeight = util.option.asSize(options.maxHeight, ''); - dom.root.style.minHeight = util.option.asSize(options.minHeight, ''); - dom.root.style.width = util.option.asSize(options.width, ''); - - // calculate border widths - props.border.left = (dom.centerContainer.offsetWidth - dom.centerContainer.clientWidth) / 2; - props.border.right = props.border.left; - props.border.top = (dom.centerContainer.offsetHeight - dom.centerContainer.clientHeight) / 2; - props.border.bottom = props.border.top; - var borderRootHeight= dom.root.offsetHeight - dom.root.clientHeight; - var borderRootWidth = dom.root.offsetWidth - dom.root.clientWidth; - - // calculate the heights. If any of the side panels is empty, we set the height to - // minus the border width, such that the border will be invisible - props.center.height = dom.center.offsetHeight; - props.left.height = dom.left.offsetHeight; - props.right.height = dom.right.offsetHeight; - props.top.height = dom.top.clientHeight || -props.border.top; - props.bottom.height = dom.bottom.clientHeight || -props.border.bottom; - - // TODO: compensate borders when any of the panels is empty. - - // apply auto height - // TODO: only calculate autoHeight when needed (else we cause an extra reflow/repaint of the DOM) - var contentHeight = Math.max(props.left.height, props.center.height, props.right.height); - var autoHeight = props.top.height + contentHeight + props.bottom.height + - borderRootHeight + props.border.top + props.border.bottom; - dom.root.style.height = util.option.asSize(options.height, autoHeight + 'px'); - - // calculate heights of the content panels - props.root.height = dom.root.offsetHeight; - props.background.height = props.root.height - borderRootHeight; - var containerHeight = props.root.height - props.top.height - props.bottom.height - - borderRootHeight; - props.centerContainer.height = containerHeight; - props.leftContainer.height = containerHeight; - props.rightContainer.height = props.leftContainer.height; - - // calculate the widths of the panels - props.root.width = dom.root.offsetWidth; - props.background.width = props.root.width - borderRootWidth; - props.left.width = dom.leftContainer.clientWidth || -props.border.left; - props.leftContainer.width = props.left.width; - props.right.width = dom.rightContainer.clientWidth || -props.border.right; - props.rightContainer.width = props.right.width; - var centerWidth = props.root.width - props.left.width - props.right.width - borderRootWidth; - props.center.width = centerWidth; - props.centerContainer.width = centerWidth; - props.top.width = centerWidth; - props.bottom.width = centerWidth; - - // resize the panels - dom.background.style.height = props.background.height + 'px'; - dom.backgroundVertical.style.height = props.background.height + 'px'; - dom.backgroundHorizontal.style.height = props.centerContainer.height + 'px'; - dom.centerContainer.style.height = props.centerContainer.height + 'px'; - dom.leftContainer.style.height = props.leftContainer.height + 'px'; - dom.rightContainer.style.height = props.rightContainer.height + 'px'; - - dom.background.style.width = props.background.width + 'px'; - dom.backgroundVertical.style.width = props.centerContainer.width + 'px'; - dom.backgroundHorizontal.style.width = props.background.width + 'px'; - dom.centerContainer.style.width = props.center.width + 'px'; - dom.top.style.width = props.top.width + 'px'; - dom.bottom.style.width = props.bottom.width + 'px'; - - // reposition the panels - dom.background.style.left = '0'; - dom.background.style.top = '0'; - dom.backgroundVertical.style.left = props.left.width + 'px'; - dom.backgroundVertical.style.top = '0'; - dom.backgroundHorizontal.style.left = '0'; - dom.backgroundHorizontal.style.top = props.top.height + 'px'; - dom.centerContainer.style.left = props.left.width + 'px'; - dom.centerContainer.style.top = props.top.height + 'px'; - dom.leftContainer.style.left = '0'; - dom.leftContainer.style.top = props.top.height + 'px'; - dom.rightContainer.style.left = (props.left.width + props.center.width) + 'px'; - dom.rightContainer.style.top = props.top.height + 'px'; - dom.top.style.left = props.left.width + 'px'; - dom.top.style.top = '0'; - dom.bottom.style.left = props.left.width + 'px'; - dom.bottom.style.top = (props.top.height + props.centerContainer.height) + 'px'; - - // update the scrollTop, feasible range for the offset can be changed - // when the height of the Core or of the contents of the center changed - this._updateScrollTop(); + LineGraph.prototype._updateUngrouped = function() { + if (this.itemsData != null) { + // var t0 = new Date(); + var group = {id: UNGROUPED, content: this.options.defaultGroup}; + this._updateGroup(group, UNGROUPED); + var ungroupedCounter = 0; + if (this.itemsData) { + for (var itemId in this.itemsData._data) { + if (this.itemsData._data.hasOwnProperty(itemId)) { + var item = this.itemsData._data[itemId]; + if (item != undefined) { + if (item.hasOwnProperty('group')) { + if (item.group === undefined) { + item.group = UNGROUPED; + } + } + else { + item.group = UNGROUPED; + } + ungroupedCounter = item.group == UNGROUPED ? ungroupedCounter + 1 : ungroupedCounter; + } + } + } + } - // reposition the scrollable contents - var offset = this.props.scrollTop; - if (options.orientation == 'bottom') { - offset += Math.max(this.props.centerContainer.height - this.props.center.height - - this.props.border.top - this.props.border.bottom, 0); + // much much slower + // var datapoints = this.itemsData.get({ + // filter: function (item) {return item.group === undefined;}, + // showInternalIds:true + // }); + // if (datapoints.length > 0) { + // var updateQuery = []; + // for (var i = 0; i < datapoints.length; i++) { + // updateQuery.push({id:datapoints[i].id, group: UNGROUPED}); + // } + // this.itemsData.update(updateQuery, true); + // } + // var t1 = new Date(); + // var pointInUNGROUPED = this.itemsData.get({filter: function (item) {return item.group == UNGROUPED;}}); + if (ungroupedCounter == 0) { + delete this.groups[UNGROUPED]; + this.legendLeft.removeGroup(UNGROUPED); + this.legendRight.removeGroup(UNGROUPED); + this.yAxisLeft.removeGroup(UNGROUPED); + this.yAxisRight.removeGroup(UNGROUPED); + } + // console.log("getting amount ungrouped",new Date() - t1); + // console.log("putting in ungrouped",new Date() - t0); } - dom.center.style.left = '0'; - dom.center.style.top = offset + 'px'; - dom.left.style.left = '0'; - dom.left.style.top = offset + 'px'; - dom.right.style.left = '0'; - dom.right.style.top = offset + 'px'; - - // show shadows when vertical scrolling is available - var visibilityTop = this.props.scrollTop == 0 ? 'hidden' : ''; - var visibilityBottom = this.props.scrollTop == this.props.scrollTopMin ? 'hidden' : ''; - dom.shadowTop.style.visibility = visibilityTop; - dom.shadowBottom.style.visibility = visibilityBottom; - dom.shadowTopLeft.style.visibility = visibilityTop; - dom.shadowBottomLeft.style.visibility = visibilityBottom; - dom.shadowTopRight.style.visibility = visibilityTop; - dom.shadowBottomRight.style.visibility = visibilityBottom; - - // redraw all components - this.components.forEach(function (component) { - resized = component.redraw() || resized; - }); - if (resized) { - // keep repainting until all sizes are settled - this.redraw(); + else { + delete this.groups[UNGROUPED]; + this.legendLeft.removeGroup(UNGROUPED); + this.legendRight.removeGroup(UNGROUPED); + this.yAxisLeft.removeGroup(UNGROUPED); + this.yAxisRight.removeGroup(UNGROUPED); } - }; - - // TODO: deprecated since version 1.1.0, remove some day - Core.prototype.repaint = function () { - throw new Error('Function repaint is deprecated. Use redraw instead.'); - }; - /** - * Convert a position on screen (pixels) to a datetime - * @param {int} x Position on the screen in pixels - * @return {Date} time The datetime the corresponds with given position x - * @private - */ - // TODO: move this function to Range - Core.prototype._toTime = function(x) { - var conversion = this.range.conversion(this.props.center.width); - return new Date(x / conversion.scale + conversion.offset); + this.legendLeft.redraw(); + this.legendRight.redraw(); }; /** - * Convert a position on the global screen (pixels) to a datetime - * @param {int} x Position on the screen in pixels - * @return {Date} time The datetime the corresponds with given position x - * @private - */ - // TODO: move this function to Range - Core.prototype._toGlobalTime = function(x) { - var conversion = this.range.conversion(this.props.root.width); - return new Date(x / conversion.scale + conversion.offset); - }; - - /** - * Convert a datetime (Date object) into a position on the screen - * @param {Date} time A date - * @return {int} x The position on the screen in pixels which corresponds - * with the given date. - * @private + * Redraw the component, mandatory function + * @return {boolean} Returns true if the component is resized */ - // TODO: move this function to Range - Core.prototype._toScreen = function(time) { - var conversion = this.range.conversion(this.props.center.width); - return (time.valueOf() - conversion.offset) * conversion.scale; - }; - + LineGraph.prototype.redraw = function() { + var resized = false; - /** - * Convert a datetime (Date object) into a position on the root - * This is used to get the pixel density estimate for the screen, not the center panel - * @param {Date} time A date - * @return {int} x The position on root in pixels which corresponds - * with the given date. - * @private - */ - // TODO: move this function to Range - Core.prototype._toGlobalScreen = function(time) { - var conversion = this.range.conversion(this.props.root.width); - return (time.valueOf() - conversion.offset) * conversion.scale; - }; + this.svg.style.height = ('' + this.options.graphHeight).replace('px','') + 'px'; + if (this.lastWidth === undefined && this.width || this.lastWidth != this.width) { + resized = true; + } + // check if this component is resized + resized = this._isResized() || resized; + // check whether zoomed (in that case we need to re-stack everything) + var visibleInterval = this.body.range.end - this.body.range.start; + var zoomed = (visibleInterval != this.lastVisibleInterval) || (this.width != this.lastWidth); + this.lastVisibleInterval = visibleInterval; + this.lastWidth = this.width; + // calculate actual size and position + this.width = this.dom.frame.offsetWidth; - /** - * Initialize watching when option autoResize is true - * @private - */ - Core.prototype._initAutoResize = function () { - if (this.options.autoResize == true) { - this._startAutoResize(); + // the svg element is three times as big as the width, this allows for fully dragging left and right + // without reloading the graph. the controls for this are bound to events in the constructor + if (resized == true) { + this.svg.style.width = util.option.asSize(3*this.width); + this.svg.style.left = util.option.asSize(-this.width); } - else { - this._stopAutoResize(); + if (zoomed == true) { + this._updateGraph(); } + + this.legendLeft.redraw(); + this.legendRight.redraw(); + + return resized; }; /** - * Watch for changes in the size of the container. On resize, the Panel will - * automatically redraw itself. - * @private + * Update and redraw the graph. + * */ - Core.prototype._startAutoResize = function () { - var me = this; + LineGraph.prototype._updateGraph = function () { + // reset the svg elements + DOMutil.prepareElements(this.svgElements); - this._stopAutoResize(); + if (this.width != 0 && this.itemsData != null) { + var group, groupData, preprocessedGroup, i; + var preprocessedGroupData = []; + var processedGroupData = []; + var groupRanges = []; + var changeCalled = false; - this._onResize = function() { - if (me.options.autoResize != true) { - // stop watching when the option autoResize is changed to false - me._stopAutoResize(); - return; + // getting group Ids + var groupIds = []; + for (var groupId in this.groups) { + if (this.groups.hasOwnProperty(groupId)) { + groupIds.push(groupId); + } } - if (me.dom.root) { - // check whether the frame is resized - if ((me.dom.root.clientWidth != me.props.lastWidth) || - (me.dom.root.clientHeight != me.props.lastHeight)) { - me.props.lastWidth = me.dom.root.clientWidth; - me.props.lastHeight = me.dom.root.clientHeight; + // this is the range of the SVG canvas + var minDate = this.body.util.toGlobalTime(- this.body.domProps.root.width); + var maxDate = this.body.util.toGlobalTime(2 * this.body.domProps.root.width); - me.emit('change'); + // first select and preprocess the data from the datasets. + // the groups have their preselection of data, we now loop over this data to see + // what data we need to draw. Sorted data is much faster. + // more optimization is possible by doing the sampling before and using the binary search + // to find the end date to determine the increment. + if (groupIds.length > 0) { + for (i = 0; i < groupIds.length; i++) { + group = this.groups[groupIds[i]]; + if (group.visible == true) { + groupData = []; + // optimization for sorted data + if (group.options.sort == true) { + var guess = Math.max(0,util.binarySearchGeneric(group.itemsData, minDate, 'x', 'before')); + + for (var j = guess; j < group.itemsData.length; j++) { + var item = group.itemsData[j]; + if (item !== undefined) { + if (item.x > maxDate) { + groupData.push(item); + break; + } + else { + groupData.push(item); + } + } + } + } + else { + for (var j = 0; j < group.itemsData.length; j++) { + var item = group.itemsData[j]; + if (item !== undefined) { + if (item.x > minDate && item.x < maxDate) { + groupData.push(item); + } + } + } + } + // preprocess, split into ranges and data + if (groupData.length > 0) { + preprocessedGroup = this._preprocessData(groupData, group); + groupRanges.push({min: preprocessedGroup.min, max: preprocessedGroup.max}); + preprocessedGroupData.push(preprocessedGroup.data); + } + else { + groupRanges.push({}); + preprocessedGroupData.push([]); + } + } + else { + groupRanges.push({}); + preprocessedGroupData.push([]); + } } - } - }; - // add event listener to window resize - util.addEventListener(window, 'resize', this._onResize); + // update the Y axis first, we use this data to draw at the correct Y points + // changeCalled is required to clean the SVG on a change emit. + changeCalled = this._updateYAxis(groupIds, groupRanges); + if (changeCalled == true) { + DOMutil.cleanupElements(this.svgElements); + this.body.emitter.emit("change"); + return; + } - this.watchTimer = setInterval(this._onResize, 1000); - }; + // with the yAxis scaled correctly, use this to get the Y values of the points. + for (i = 0; i < groupIds.length; i++) { + group = this.groups[groupIds[i]]; + processedGroupData.push(this._convertYvalues(preprocessedGroupData[i],group)) + } - /** - * Stop watching for a resize of the frame. - * @private - */ - Core.prototype._stopAutoResize = function () { - if (this.watchTimer) { - clearInterval(this.watchTimer); - this.watchTimer = undefined; + // draw the groups + for (i = 0; i < groupIds.length; i++) { + group = this.groups[groupIds[i]]; + if (group.visible == true) { + if (group.options.style == 'line') { + this._drawLineGraph(processedGroupData[i], group); + } + else { + this._drawBarGraph (processedGroupData[i], group); + } + } + } + } } - // remove event listener on window.resize - util.removeEventListener(window, 'resize', this._onResize); - this._onResize = null; + // cleanup unused svg elements + DOMutil.cleanupElements(this.svgElements); }; /** - * Start moving the timeline vertically - * @param {Event} event + * this sets the Y ranges for the Y axis. It also determines which of the axis should be shown or hidden. + * @param {array} groupIds * @private */ - Core.prototype._onTouch = function (event) { - this.touch.allowDragging = true; - }; + LineGraph.prototype._updateYAxis = function (groupIds, groupRanges) { + var changeCalled = false; + var yAxisLeftUsed = false; + var yAxisRightUsed = false; + var minLeft = 1e9, minRight = 1e9, maxLeft = -1e9, maxRight = -1e9, minVal, maxVal; + var orientation = 'left'; - /** - * Start moving the timeline vertically - * @param {Event} event - * @private - */ - Core.prototype._onPinch = function (event) { - this.touch.allowDragging = false; - }; + // if groups are present + if (groupIds.length > 0) { + for (var i = 0; i < groupIds.length; i++) { + orientation = 'left'; + var group = this.groups[groupIds[i]]; + if (group.visible == true) { + if (group.options.yAxisOrientation == 'right') { + orientation = 'right'; + } - /** - * Start moving the timeline vertically - * @param {Event} event - * @private - */ - Core.prototype._onDragStart = function (event) { - this.touch.initialScrollTop = this.props.scrollTop; - }; + minVal = groupRanges[i].min; + maxVal = groupRanges[i].max; - /** - * Move the timeline vertically - * @param {Event} event - * @private - */ - Core.prototype._onDrag = function (event) { - // refuse to drag when we where pinching to prevent the timeline make a jump - // when releasing the fingers in opposite order from the touch screen - if (!this.touch.allowDragging) return; + if (orientation == 'left') { + yAxisLeftUsed = true; + minLeft = minLeft > minVal ? minVal : minLeft; + maxLeft = maxLeft < maxVal ? maxVal : maxLeft; + } + else { + yAxisRightUsed = true; + minRight = minRight > minVal ? minVal : minRight; + maxRight = maxRight < maxVal ? maxVal : maxRight; + } + } + } + if (yAxisLeftUsed == true) { + this.yAxisLeft.setRange(minLeft, maxLeft); + } + if (yAxisRightUsed == true) { + this.yAxisRight.setRange(minRight, maxRight); + } + } - var delta = event.gesture.deltaY; + changeCalled = this._toggleAxisVisiblity(yAxisLeftUsed , this.yAxisLeft) || changeCalled; + changeCalled = this._toggleAxisVisiblity(yAxisRightUsed, this.yAxisRight) || changeCalled; - var oldScrollTop = this._getScrollTop(); - var newScrollTop = this._setScrollTop(this.touch.initialScrollTop + delta); + if (yAxisRightUsed == true && yAxisLeftUsed == true) { + this.yAxisLeft.drawIcons = true; + this.yAxisRight.drawIcons = true; + } + else { + this.yAxisLeft.drawIcons = false; + this.yAxisRight.drawIcons = false; + } - if (newScrollTop != oldScrollTop) { - this.redraw(); // TODO: this causes two redraws when dragging, the other is triggered by rangechange already + this.yAxisRight.master = !yAxisLeftUsed; + + if (this.yAxisRight.master == false) { + if (yAxisRightUsed == true) {this.yAxisLeft.lineOffset = this.yAxisRight.width;} + else {this.yAxisLeft.lineOffset = 0;} + + changeCalled = this.yAxisLeft.redraw() || changeCalled; + this.yAxisRight.stepPixelsForced = this.yAxisLeft.stepPixels; + changeCalled = this.yAxisRight.redraw() || changeCalled; + } + else { + changeCalled = this.yAxisRight.redraw() || changeCalled; } + return changeCalled; }; /** - * Apply a scrollTop - * @param {Number} scrollTop - * @returns {Number} scrollTop Returns the applied scrollTop + * This shows or hides the Y axis if needed. If there is a change, the changed event is emitted by the updateYAxis function + * + * @param {boolean} axisUsed + * @returns {boolean} * @private + * @param axis */ - Core.prototype._setScrollTop = function (scrollTop) { - this.props.scrollTop = scrollTop; - this._updateScrollTop(); - return this.props.scrollTop; + LineGraph.prototype._toggleAxisVisiblity = function (axisUsed, axis) { + var changed = false; + if (axisUsed == false) { + if (axis.dom.frame.parentNode) { + axis.hide(); + changed = true; + } + } + else { + if (!axis.dom.frame.parentNode) { + axis.show(); + changed = true; + } + } + return changed; }; + /** - * Update the current scrollTop when the height of the containers has been changed - * @returns {Number} scrollTop Returns the applied scrollTop - * @private + * draw a bar graph + * @param datapoints + * @param group */ - Core.prototype._updateScrollTop = function () { - // recalculate the scrollTopMin - var scrollTopMin = Math.min(this.props.centerContainer.height - this.props.center.height, 0); // is negative or zero - if (scrollTopMin != this.props.scrollTopMin) { - // in case of bottom orientation, change the scrollTop such that the contents - // do not move relative to the time axis at the bottom - if (this.options.orientation == 'bottom') { - this.props.scrollTop += (scrollTopMin - this.props.scrollTopMin); - } - this.props.scrollTopMin = scrollTopMin; - } - - // limit the scrollTop to the feasible scroll range - if (this.props.scrollTop > 0) this.props.scrollTop = 0; - if (this.props.scrollTop < scrollTopMin) this.props.scrollTop = scrollTopMin; - - return this.props.scrollTop; - }; - - /** - * Get the current scrollTop - * @returns {number} scrollTop - * @private - */ - Core.prototype._getScrollTop = function () { - return this.props.scrollTop; - }; + LineGraph.prototype._drawBarGraph = function (dataset, group) { + if (dataset != null) { + if (dataset.length > 0) { + var coreDistance; + var minWidth = 0.1 * group.options.barChart.width; + var offset = 0; - module.exports = Core; + // check for intersections + var intersections = {}; + for (var i = 0; i < dataset.length; i++) { + if (i+1 < dataset.length) {coreDistance = Math.abs(dataset[i+1].x - dataset[i].x);} + if (i > 0) {coreDistance = Math.min(coreDistance,Math.abs(dataset[i-1].x - dataset[i].x));} + if (coreDistance == 0) { + if (intersections[dataset[i].x] === undefined) { + intersections[dataset[i].x] = {amount:0, resolved:0}; + } + intersections[dataset[i].x].amount += 1; + } + } -/***/ }, -/* 24 */ -/***/ function(module, exports, __webpack_require__) { + // plot the bargraph + var key; + for (var i = 0; i < dataset.length; i++) { + key = dataset[i].x; + if (intersections[key] === undefined) { + if (i+1 < dataset.length) {coreDistance = Math.abs(dataset[i+1].x - key);} + if (i > 0) {coreDistance = Math.min(coreDistance,Math.abs(dataset[i-1].x - key));} + var drawData = this._getSafeDrawData(coreDistance, group, minWidth); + } + else { + var nextKey = i + (intersections[key].amount - intersections[key].resolved); + var prevKey = i - (intersections[key].resolved + 1); + if (nextKey < dataset.length) {coreDistance = Math.abs(dataset[nextKey].x - key);} + if (prevKey > 0) {coreDistance = Math.min(coreDistance,Math.abs(dataset[prevKey].x - key));} + var drawData = this._getSafeDrawData(coreDistance, group, minWidth); + intersections[key].resolved += 1; - var util = __webpack_require__(1); - var Component = __webpack_require__(22); - var TimeStep = __webpack_require__(25); + if (group.options.barChart.allowOverlap == false) { + drawData.width = drawData.width / intersections[key].amount; + drawData.offset += (intersections[key].resolved) * drawData.width - (0.5*drawData.width * (intersections[key].amount+1)); + if (group.options.barChart.align == 'left') {offset -= 0.5*drawData.width;} + else if (group.options.barChart.align == 'right') {offset += 0.5*drawData.width;} + } + } + DOMutil.drawBar(dataset[i].x + drawData.offset, dataset[i].y, drawData.width, group.zeroPosition - dataset[i].y, group.className + ' bar', this.svgElements, this.svg); - /** - * A horizontal time axis - * @param {{dom: Object, domProps: Object, emitter: Emitter, range: Range}} body - * @param {Object} [options] See TimeAxis.setOptions for the available - * options. - * @constructor TimeAxis - * @extends Component - */ - function TimeAxis (body, options) { - this.dom = { - foreground: null, - majorLines: [], - majorTexts: [], - minorLines: [], - minorTexts: [], - redundant: { - majorLines: [], - majorTexts: [], - minorLines: [], - minorTexts: [] + // draw points + if (group.options.drawPoints.enabled == true) { + DOMutil.drawPoint(dataset[i].x + drawData.offset, dataset[i].y, group, this.svgElements, this.svg); + } + } } - }; - this.props = { - range: { - start: 0, - end: 0, - minimumStep: 0 - }, - lineTop: 0 - }; - - this.defaultOptions = { - orientation: 'bottom', // supported: 'top', 'bottom' - // TODO: implement timeaxis orientations 'left' and 'right' - showMinorLabels: true, - showMajorLabels: true - }; - this.options = util.extend({}, this.defaultOptions); + } + }; - this.body = body; + LineGraph.prototype._getSafeDrawData = function (coreDistance, group, minWidth) { + var width, offset; + if (coreDistance < group.options.barChart.width && coreDistance > 0) { + width = coreDistance < minWidth ? minWidth : coreDistance; - // create the HTML DOM - this._create(); + offset = 0; // recalculate offset with the new width; + if (group.options.slots) { // recalculate the shared width and offset if these options are set. + width = (width / group.options.slots.total); + offset = group.options.slots.slot * width - (0.5*width * (group.options.slots.total+1)); + } + if (group.options.barChart.align == 'left') {offset -= 0.5*coreDistance;} + else if (group.options.barChart.align == 'right') {offset += 0.5*coreDistance;} + } + else { + // no collisions, plot with default settings + width = group.options.barChart.width; + offset = 0; + if (group.options.slots) { + // if the groups are sharing the same points, this allows them to be plotted side by side + width = width / group.options.slots.total; + offset = group.options.slots.slot * width - (0.5*width * (group.options.slots.total+1)); + } + if (group.options.barChart.align == 'left') {offset -= 0.5*group.options.barChart.width;} + else if (group.options.barChart.align == 'right') {offset += 0.5*group.options.barChart.width;} + } - this.setOptions(options); + return {width: width, offset: offset}; } - TimeAxis.prototype = new Component(); /** - * Set options for the TimeAxis. - * Parameters will be merged in current options. - * @param {Object} options Available options: - * {string} [orientation] - * {boolean} [showMinorLabels] - * {boolean} [showMajorLabels] + * draw a line graph + * + * @param datapoints + * @param group */ - TimeAxis.prototype.setOptions = function(options) { - if (options) { - // copy all options that we know - util.selectiveExtend(['orientation', 'showMinorLabels', 'showMajorLabels'], this.options, options); - } - }; + LineGraph.prototype._drawLineGraph = function (dataset, group) { + if (dataset != null) { + if (dataset.length > 0) { + var path, d; + var svgHeight = Number(this.svg.style.height.replace("px","")); + path = DOMutil.getSVGElement('path', this.svgElements, this.svg); + path.setAttributeNS(null, "class", group.className); - /** - * Create the HTML DOM for the TimeAxis - */ - TimeAxis.prototype._create = function() { - this.dom.foreground = document.createElement('div'); - this.dom.background = document.createElement('div'); + // construct path from dataset + if (group.options.catmullRom.enabled == true) { + d = this._catmullRom(dataset, group); + } + else { + d = this._linear(dataset); + } - this.dom.foreground.className = 'timeaxis foreground'; - this.dom.background.className = 'timeaxis background'; + // append with points for fill and finalize the path + if (group.options.shaded.enabled == true) { + var fillPath = DOMutil.getSVGElement('path',this.svgElements, this.svg); + var dFill; + if (group.options.shaded.orientation == 'top') { + dFill = "M" + dataset[0].x + "," + 0 + " " + d + "L" + dataset[dataset.length - 1].x + "," + 0; + } + else { + dFill = "M" + dataset[0].x + "," + svgHeight + " " + d + "L" + dataset[dataset.length - 1].x + "," + svgHeight; + } + fillPath.setAttributeNS(null, "class", group.className + " fill"); + fillPath.setAttributeNS(null, "d", dFill); + } + // copy properties to path for drawing. + path.setAttributeNS(null, "d", "M" + d); + + // draw points + if (group.options.drawPoints.enabled == true) { + this._drawPoints(dataset, group, this.svgElements, this.svg); + } + } + } }; /** - * Destroy the TimeAxis + * draw the data points + * + * @param dataset + * @param JSONcontainer + * @param svg + * @param group */ - TimeAxis.prototype.destroy = function() { - // remove from DOM - if (this.dom.foreground.parentNode) { - this.dom.foreground.parentNode.removeChild(this.dom.foreground); - } - if (this.dom.background.parentNode) { - this.dom.background.parentNode.removeChild(this.dom.background); + LineGraph.prototype._drawPoints = function (dataset, group, JSONcontainer, svg, offset) { + if (offset === undefined) {offset = 0;} + for (var i = 0; i < dataset.length; i++) { + DOMutil.drawPoint(dataset[i].x + offset, dataset[i].y, group, JSONcontainer, svg); } - - this.body = null; }; + + /** - * Repaint the component - * @return {boolean} Returns true if the component is resized + * This uses the DataAxis object to generate the correct X coordinate on the SVG window. It uses the + * util function toScreen to get the x coordinate from the timestamp. It also pre-filters the data and get the minMax ranges for + * the yAxis. + * + * @param datapoints + * @returns {Array} + * @private */ - TimeAxis.prototype.redraw = function () { - var options = this.options, - props = this.props, - foreground = this.dom.foreground, - background = this.dom.background; + LineGraph.prototype._preprocessData = function (datapoints, group) { + var extractedData = []; + var xValue, yValue; + var toScreen = this.body.util.toScreen; - // determine the correct parent DOM element (depending on option orientation) - var parent = (options.orientation == 'top') ? this.body.dom.top : this.body.dom.bottom; - var parentChanged = (foreground.parentNode !== parent); + var increment = 1; + var amountOfPoints = datapoints.length; - // calculate character width and height - this._calculateCharSize(); + var yMin = datapoints[0].y; + var yMax = datapoints[0].y; - // TODO: recalculate sizes only needed when parent is resized or options is changed - var orientation = this.options.orientation, - showMinorLabels = this.options.showMinorLabels, - showMajorLabels = this.options.showMajorLabels; - - // determine the width and height of the elemens for the axis - props.minorLabelHeight = showMinorLabels ? props.minorCharHeight : 0; - props.majorLabelHeight = showMajorLabels ? props.majorCharHeight : 0; - props.height = props.minorLabelHeight + props.majorLabelHeight; - props.width = foreground.offsetWidth; - - props.minorLineHeight = this.body.domProps.root.height - props.majorLabelHeight - - (options.orientation == 'top' ? this.body.domProps.bottom.height : this.body.domProps.top.height); - props.minorLineWidth = 1; // TODO: really calculate width - props.majorLineHeight = props.minorLineHeight + props.majorLabelHeight; - props.majorLineWidth = 1; // TODO: really calculate width - - // take foreground and background offline while updating (is almost twice as fast) - var foregroundNextSibling = foreground.nextSibling; - var backgroundNextSibling = background.nextSibling; - foreground.parentNode && foreground.parentNode.removeChild(foreground); - background.parentNode && background.parentNode.removeChild(background); - - foreground.style.height = this.props.height + 'px'; - - this._repaintLabels(); - - // put DOM online again (at the same place) - if (foregroundNextSibling) { - parent.insertBefore(foreground, foregroundNextSibling); - } - else { - parent.appendChild(foreground) - } - if (backgroundNextSibling) { - this.body.dom.backgroundVertical.insertBefore(background, backgroundNextSibling); + // the global screen is used because changing the width of the yAxis may affect the increment, resulting in an endless loop + // of width changing of the yAxis. + if (group.options.sampling == true) { + var xDistance = this.body.util.toGlobalScreen(datapoints[datapoints.length-1].x) - this.body.util.toGlobalScreen(datapoints[0].x); + var pointsPerPixel = amountOfPoints/xDistance; + increment = Math.min(Math.ceil(0.2 * amountOfPoints), Math.max(1,Math.round(pointsPerPixel))); } - else { - this.body.dom.backgroundVertical.appendChild(background) + + for (var i = 0; i < amountOfPoints; i += increment) { + xValue = toScreen(datapoints[i].x) + this.width - 1; + yValue = datapoints[i].y; + extractedData.push({x: xValue, y: yValue}); + yMin = yMin > yValue ? yValue : yMin; + yMax = yMax < yValue ? yValue : yMax; } - return this._isResized() || parentChanged; + // extractedData.sort(function (a,b) {return a.x - b.x;}); + return {min: yMin, max: yMax, data: extractedData}; }; /** - * Repaint major and minor text labels and vertical grid lines + * This uses the DataAxis object to generate the correct Y coordinate on the SVG window. It uses the + * util function toScreen to get the x coordinate from the timestamp. + * + * @param datapoints + * @param options + * @returns {Array} * @private */ - TimeAxis.prototype._repaintLabels = function () { - var orientation = this.options.orientation; - - // calculate range and step (step such that we have space for 7 characters per label) - var start = util.convert(this.body.range.start, 'Number'), - end = util.convert(this.body.range.end, 'Number'), - minimumStep = this.body.util.toTime((this.props.minorCharWidth || 10) * 7).valueOf() - -this.body.util.toTime(0).valueOf(); - var step = new TimeStep(new Date(start), new Date(end), minimumStep); - this.step = step; - - // Move all DOM elements to a "redundant" list, where they - // can be picked for re-use, and clear the lists with lines and texts. - // At the end of the function _repaintLabels, left over elements will be cleaned up - var dom = this.dom; - dom.redundant.majorLines = dom.majorLines; - dom.redundant.majorTexts = dom.majorTexts; - dom.redundant.minorLines = dom.minorLines; - dom.redundant.minorTexts = dom.minorTexts; - dom.majorLines = []; - dom.majorTexts = []; - dom.minorLines = []; - dom.minorTexts = []; - - step.first(); - var xFirstMajorLabel = undefined; - var max = 0; - while (step.hasNext() && max < 1000) { - max++; - var cur = step.getCurrent(), - x = this.body.util.toScreen(cur), - isMajor = step.isMajor(); - - // TODO: lines must have a width, such that we can create css backgrounds - - if (this.options.showMinorLabels) { - this._repaintMinorText(x, step.getLabelMinor(), orientation); - } - - if (isMajor && this.options.showMajorLabels) { - if (x > 0) { - if (xFirstMajorLabel == undefined) { - xFirstMajorLabel = x; - } - this._repaintMajorText(x, step.getLabelMajor(), orientation); - } - this._repaintMajorLine(x, orientation); - } - else { - this._repaintMinorLine(x, orientation); - } + LineGraph.prototype._convertYvalues = function (datapoints, group) { + var extractedData = []; + var xValue, yValue; + var axis = this.yAxisLeft; + var svgHeight = Number(this.svg.style.height.replace("px","")); - step.next(); + if (group.options.yAxisOrientation == 'right') { + axis = this.yAxisRight; } - // create a major label on the left when needed - if (this.options.showMajorLabels) { - var leftTime = this.body.util.toTime(0), - leftText = step.getLabelMajor(leftTime), - widthText = leftText.length * (this.props.majorCharWidth || 10) + 10; // upper bound estimation - - if (xFirstMajorLabel == undefined || widthText < xFirstMajorLabel) { - this._repaintMajorText(0, leftText, orientation); - } + for (var i = 0; i < datapoints.length; i++) { + xValue = datapoints[i].x; + yValue = Math.round(axis.convertValue(datapoints[i].y)); + extractedData.push({x: xValue, y: yValue}); } - // Cleanup leftover DOM elements from the redundant list - util.forEach(this.dom.redundant, function (arr) { - while (arr.length) { - var elem = arr.pop(); - if (elem && elem.parentNode) { - elem.parentNode.removeChild(elem); - } - } - }); + group.setZeroPosition(Math.min(svgHeight, axis.convertValue(0))); + + // extractedData.sort(function (a,b) {return a.x - b.x;}); + return extractedData; }; + /** - * Create a minor label for the axis at position x - * @param {Number} x - * @param {String} text - * @param {String} orientation "top" or "bottom" (default) + * This uses an uniform parametrization of the CatmullRom algorithm: + * "On the Parameterization of Catmull-Rom Curves" by Cem Yuksel et al. + * @param data + * @returns {string} * @private */ - TimeAxis.prototype._repaintMinorText = function (x, text, orientation) { - // reuse redundant label - var label = this.dom.redundant.minorTexts.shift(); + LineGraph.prototype._catmullRomUniform = function(data) { + // catmull rom + var p0, p1, p2, p3, bp1, bp2; + var d = Math.round(data[0].x) + "," + Math.round(data[0].y) + " "; + var normalization = 1/6; + var length = data.length; + for (var i = 0; i < length - 1; i++) { - if (!label) { - // create new label - var content = document.createTextNode(''); - label = document.createElement('div'); - label.appendChild(content); - label.className = 'text minor'; - this.dom.foreground.appendChild(label); - } - this.dom.minorTexts.push(label); + p0 = (i == 0) ? data[0] : data[i-1]; + p1 = data[i]; + p2 = data[i+1]; + p3 = (i + 2 < length) ? data[i+2] : p2; - label.childNodes[0].nodeValue = text; - label.style.top = (orientation == 'top') ? (this.props.majorLabelHeight + 'px') : '0'; - label.style.left = x + 'px'; - //label.title = title; // TODO: this is a heavy operation - }; + // Catmull-Rom to Cubic Bezier conversion matrix + // 0 1 0 0 + // -1/6 1 1/6 0 + // 0 1/6 1 -1/6 + // 0 0 1 0 - /** - * Create a Major label for the axis at position x - * @param {Number} x - * @param {String} text - * @param {String} orientation "top" or "bottom" (default) - * @private - */ - TimeAxis.prototype._repaintMajorText = function (x, text, orientation) { - // reuse redundant label - var label = this.dom.redundant.majorTexts.shift(); + // bp0 = { x: p1.x, y: p1.y }; + bp1 = { x: ((-p0.x + 6*p1.x + p2.x) *normalization), y: ((-p0.y + 6*p1.y + p2.y) *normalization)}; + bp2 = { x: (( p1.x + 6*p2.x - p3.x) *normalization), y: (( p1.y + 6*p2.y - p3.y) *normalization)}; + // bp0 = { x: p2.x, y: p2.y }; - if (!label) { - // create label - var content = document.createTextNode(text); - label = document.createElement('div'); - label.className = 'text major'; - label.appendChild(content); - this.dom.foreground.appendChild(label); + d += "C" + + bp1.x + "," + + bp1.y + " " + + bp2.x + "," + + bp2.y + " " + + p2.x + "," + + p2.y + " "; } - this.dom.majorTexts.push(label); - - label.childNodes[0].nodeValue = text; - //label.title = title; // TODO: this is a heavy operation - label.style.top = (orientation == 'top') ? '0' : (this.props.minorLabelHeight + 'px'); - label.style.left = x + 'px'; + return d; }; /** - * Create a minor line for the axis at position x - * @param {Number} x - * @param {String} orientation "top" or "bottom" (default) + * This uses either the chordal or centripetal parameterization of the catmull-rom algorithm. + * By default, the centripetal parameterization is used because this gives the nicest results. + * These parameterizations are relatively heavy because the distance between 4 points have to be calculated. + * + * One optimization can be used to reuse distances since this is a sliding window approach. + * @param data + * @returns {string} * @private */ - TimeAxis.prototype._repaintMinorLine = function (x, orientation) { - // reuse redundant line - var line = this.dom.redundant.minorLines.shift(); - - if (!line) { - // create vertical line - line = document.createElement('div'); - line.className = 'grid vertical minor'; - this.dom.background.appendChild(line); - } - this.dom.minorLines.push(line); - - var props = this.props; - if (orientation == 'top') { - line.style.top = props.majorLabelHeight + 'px'; + LineGraph.prototype._catmullRom = function(data, group) { + var alpha = group.options.catmullRom.alpha; + if (alpha == 0 || alpha === undefined) { + return this._catmullRomUniform(data); } else { - line.style.top = this.body.domProps.top.height + 'px'; - } - line.style.height = props.minorLineHeight + 'px'; - line.style.left = (x - props.minorLineWidth / 2) + 'px'; - }; + var p0, p1, p2, p3, bp1, bp2, d1,d2,d3, A, B, N, M; + var d3powA, d2powA, d3pow2A, d2pow2A, d1pow2A, d1powA; + var d = Math.round(data[0].x) + "," + Math.round(data[0].y) + " "; + var length = data.length; + for (var i = 0; i < length - 1; i++) { - /** - * Create a Major line for the axis at position x - * @param {Number} x - * @param {String} orientation "top" or "bottom" (default) - * @private - */ - TimeAxis.prototype._repaintMajorLine = function (x, orientation) { - // reuse redundant line - var line = this.dom.redundant.majorLines.shift(); + p0 = (i == 0) ? data[0] : data[i-1]; + p1 = data[i]; + p2 = data[i+1]; + p3 = (i + 2 < length) ? data[i+2] : p2; - if (!line) { - // create vertical line - line = document.createElement('DIV'); - line.className = 'grid vertical major'; - this.dom.background.appendChild(line); - } - this.dom.majorLines.push(line); + d1 = Math.sqrt(Math.pow(p0.x - p1.x,2) + Math.pow(p0.y - p1.y,2)); + d2 = Math.sqrt(Math.pow(p1.x - p2.x,2) + Math.pow(p1.y - p2.y,2)); + d3 = Math.sqrt(Math.pow(p2.x - p3.x,2) + Math.pow(p2.y - p3.y,2)); - var props = this.props; - if (orientation == 'top') { - line.style.top = '0'; - } - else { - line.style.top = this.body.domProps.top.height + 'px'; - } - line.style.left = (x - props.majorLineWidth / 2) + 'px'; - line.style.height = props.majorLineHeight + 'px'; - }; + // Catmull-Rom to Cubic Bezier conversion matrix + // + // A = 2d1^2a + 3d1^a * d2^a + d3^2a + // B = 2d3^2a + 3d3^a * d2^a + d2^2a + // + // [ 0 1 0 0 ] + // [ -d2^2a/N A/N d1^2a/N 0 ] + // [ 0 d3^2a/M B/M -d2^2a/M ] + // [ 0 0 1 0 ] - /** - * Determine the size of text on the axis (both major and minor axis). - * The size is calculated only once and then cached in this.props. - * @private - */ - TimeAxis.prototype._calculateCharSize = function () { - // Note: We calculate char size with every redraw. Size may change, for - // example when any of the timelines parents had display:none for example. + // [ 0 1 0 0 ] + // [ -d2pow2a/N A/N d1pow2a/N 0 ] + // [ 0 d3pow2a/M B/M -d2pow2a/M ] + // [ 0 0 1 0 ] - // determine the char width and height on the minor axis - if (!this.dom.measureCharMinor) { - this.dom.measureCharMinor = document.createElement('DIV'); - this.dom.measureCharMinor.className = 'text minor measure'; - this.dom.measureCharMinor.style.position = 'absolute'; + d3powA = Math.pow(d3, alpha); + d3pow2A = Math.pow(d3,2*alpha); + d2powA = Math.pow(d2, alpha); + d2pow2A = Math.pow(d2,2*alpha); + d1powA = Math.pow(d1, alpha); + d1pow2A = Math.pow(d1,2*alpha); - this.dom.measureCharMinor.appendChild(document.createTextNode('0')); - this.dom.foreground.appendChild(this.dom.measureCharMinor); - } - this.props.minorCharHeight = this.dom.measureCharMinor.clientHeight; - this.props.minorCharWidth = this.dom.measureCharMinor.clientWidth; + A = 2*d1pow2A + 3*d1powA * d2powA + d2pow2A; + B = 2*d3pow2A + 3*d3powA * d2powA + d2pow2A; + N = 3*d1powA * (d1powA + d2powA); + if (N > 0) {N = 1 / N;} + M = 3*d3powA * (d3powA + d2powA); + if (M > 0) {M = 1 / M;} - // determine the char width and height on the major axis - if (!this.dom.measureCharMajor) { - this.dom.measureCharMajor = document.createElement('DIV'); - this.dom.measureCharMajor.className = 'text minor measure'; - this.dom.measureCharMajor.style.position = 'absolute'; + bp1 = { x: ((-d2pow2A * p0.x + A*p1.x + d1pow2A * p2.x) * N), + y: ((-d2pow2A * p0.y + A*p1.y + d1pow2A * p2.y) * N)}; - this.dom.measureCharMajor.appendChild(document.createTextNode('0')); - this.dom.foreground.appendChild(this.dom.measureCharMajor); + bp2 = { x: (( d3pow2A * p1.x + B*p2.x - d2pow2A * p3.x) * M), + y: (( d3pow2A * p1.y + B*p2.y - d2pow2A * p3.y) * M)}; + + if (bp1.x == 0 && bp1.y == 0) {bp1 = p1;} + if (bp2.x == 0 && bp2.y == 0) {bp2 = p2;} + d += "C" + + bp1.x + "," + + bp1.y + " " + + bp2.x + "," + + bp2.y + " " + + p2.x + "," + + p2.y + " "; + } + + return d; } - this.props.majorCharHeight = this.dom.measureCharMajor.clientHeight; - this.props.majorCharWidth = this.dom.measureCharMajor.clientWidth; }; /** - * Snap a date to a rounded value. - * The snap intervals are dependent on the current scale and step. - * @param {Date} date the date to be snapped. - * @return {Date} snappedDate + * this generates the SVG path for a linear drawing between datapoints. + * @param data + * @returns {string} + * @private */ - TimeAxis.prototype.snap = function(date) { - return this.step.snap(date); + LineGraph.prototype._linear = function(data) { + // linear + var d = ""; + for (var i = 0; i < data.length; i++) { + if (i == 0) { + d += data[i].x + "," + data[i].y; + } + else { + d += " " + data[i].x + "," + data[i].y; + } + } + return d; }; - module.exports = TimeAxis; + module.exports = LineGraph; /***/ }, -/* 25 */ +/* 27 */ /***/ function(module, exports, __webpack_require__) { - var moment = __webpack_require__(2); + var util = __webpack_require__(1); + var Component = __webpack_require__(18); + var TimeStep = __webpack_require__(17); /** - * @constructor TimeStep - * The class TimeStep is an iterator for dates. You provide a start date and an - * end date. The class itself determines the best scale (step size) based on the - * provided start Date, end Date, and minimumStep. - * - * If minimumStep is provided, the step size is chosen as close as possible - * to the minimumStep but larger than minimumStep. If minimumStep is not - * provided, the scale is set to 1 DAY. - * The minimumStep should correspond with the onscreen size of about 6 characters - * - * Alternatively, you can set a scale by hand. - * After creation, you can initialize the class by executing first(). Then you - * can iterate from the start date to the end date via next(). You can check if - * the end date is reached with the function hasNext(). After each step, you can - * retrieve the current date via getCurrent(). - * The TimeStep has scales ranging from milliseconds, seconds, minutes, hours, - * days, to years. - * - * Version: 1.2 - * - * @param {Date} [start] The start date, for example new Date(2010, 9, 21) - * or new Date(2010, 9, 21, 23, 45, 00) - * @param {Date} [end] The end date - * @param {Number} [minimumStep] Optional. Minimum step size in milliseconds + * A horizontal time axis + * @param {{dom: Object, domProps: Object, emitter: Emitter, range: Range}} body + * @param {Object} [options] See TimeAxis.setOptions for the available + * options. + * @constructor TimeAxis + * @extends Component */ - function TimeStep(start, end, minimumStep) { - // variables - this.current = new Date(); - this._start = new Date(); - this._end = new Date(); + function TimeAxis (body, options) { + this.dom = { + foreground: null, + majorLines: [], + majorTexts: [], + minorLines: [], + minorTexts: [], + redundant: { + majorLines: [], + majorTexts: [], + minorLines: [], + minorTexts: [] + } + }; + this.props = { + range: { + start: 0, + end: 0, + minimumStep: 0 + }, + lineTop: 0 + }; - this.autoScale = true; - this.scale = TimeStep.SCALE.DAY; - this.step = 1; + this.defaultOptions = { + orientation: 'bottom', // supported: 'top', 'bottom' + // TODO: implement timeaxis orientations 'left' and 'right' + showMinorLabels: true, + showMajorLabels: true + }; + this.options = util.extend({}, this.defaultOptions); - // initialize the range - this.setRange(start, end, minimumStep); - } + this.body = body; - /// enum scale - TimeStep.SCALE = { - MILLISECOND: 1, - SECOND: 2, - MINUTE: 3, - HOUR: 4, - DAY: 5, - WEEKDAY: 6, - MONTH: 7, - YEAR: 8 - }; + // create the HTML DOM + this._create(); + + this.setOptions(options); + } + TimeAxis.prototype = new Component(); /** - * Set a new range - * If minimumStep is provided, the step size is chosen as close as possible - * to the minimumStep but larger than minimumStep. If minimumStep is not - * provided, the scale is set to 1 DAY. - * The minimumStep should correspond with the onscreen size of about 6 characters - * @param {Date} [start] The start date and time. - * @param {Date} [end] The end date and time. - * @param {int} [minimumStep] Optional. Minimum step size in milliseconds + * Set options for the TimeAxis. + * Parameters will be merged in current options. + * @param {Object} options Available options: + * {string} [orientation] + * {boolean} [showMinorLabels] + * {boolean} [showMajorLabels] */ - TimeStep.prototype.setRange = function(start, end, minimumStep) { - if (!(start instanceof Date) || !(end instanceof Date)) { - throw "No legal start or end date in method setRange"; - } - - this._start = (start != undefined) ? new Date(start.valueOf()) : new Date(); - this._end = (end != undefined) ? new Date(end.valueOf()) : new Date(); - - if (this.autoScale) { - this.setMinimumStep(minimumStep); + TimeAxis.prototype.setOptions = function(options) { + if (options) { + // copy all options that we know + util.selectiveExtend(['orientation', 'showMinorLabels', 'showMajorLabels'], this.options, options); } }; /** - * Set the range iterator to the start date. + * Create the HTML DOM for the TimeAxis */ - TimeStep.prototype.first = function() { - this.current = new Date(this._start.valueOf()); - this.roundToMinor(); + TimeAxis.prototype._create = function() { + this.dom.foreground = document.createElement('div'); + this.dom.background = document.createElement('div'); + + this.dom.foreground.className = 'timeaxis foreground'; + this.dom.background.className = 'timeaxis background'; }; /** - * Round the current date to the first minor date value - * This must be executed once when the current date is set to start Date + * Destroy the TimeAxis */ - TimeStep.prototype.roundToMinor = function() { - // round to floor - // IMPORTANT: we have no breaks in this switch! (this is no bug) - //noinspection FallthroughInSwitchStatementJS - switch (this.scale) { - case TimeStep.SCALE.YEAR: - this.current.setFullYear(this.step * Math.floor(this.current.getFullYear() / this.step)); - this.current.setMonth(0); - case TimeStep.SCALE.MONTH: this.current.setDate(1); - case TimeStep.SCALE.DAY: // intentional fall through - case TimeStep.SCALE.WEEKDAY: this.current.setHours(0); - case TimeStep.SCALE.HOUR: this.current.setMinutes(0); - case TimeStep.SCALE.MINUTE: this.current.setSeconds(0); - case TimeStep.SCALE.SECOND: this.current.setMilliseconds(0); - //case TimeStep.SCALE.MILLISECOND: // nothing to do for milliseconds + TimeAxis.prototype.destroy = function() { + // remove from DOM + if (this.dom.foreground.parentNode) { + this.dom.foreground.parentNode.removeChild(this.dom.foreground); } - - if (this.step != 1) { - // round down to the first minor value that is a multiple of the current step size - switch (this.scale) { - case TimeStep.SCALE.MILLISECOND: this.current.setMilliseconds(this.current.getMilliseconds() - this.current.getMilliseconds() % this.step); break; - case TimeStep.SCALE.SECOND: this.current.setSeconds(this.current.getSeconds() - this.current.getSeconds() % this.step); break; - case TimeStep.SCALE.MINUTE: this.current.setMinutes(this.current.getMinutes() - this.current.getMinutes() % this.step); break; - case TimeStep.SCALE.HOUR: this.current.setHours(this.current.getHours() - this.current.getHours() % this.step); break; - case TimeStep.SCALE.WEEKDAY: // intentional fall through - case TimeStep.SCALE.DAY: this.current.setDate((this.current.getDate()-1) - (this.current.getDate()-1) % this.step + 1); break; - case TimeStep.SCALE.MONTH: this.current.setMonth(this.current.getMonth() - this.current.getMonth() % this.step); break; - case TimeStep.SCALE.YEAR: this.current.setFullYear(this.current.getFullYear() - this.current.getFullYear() % this.step); break; - default: break; - } + if (this.dom.background.parentNode) { + this.dom.background.parentNode.removeChild(this.dom.background); } - }; - /** - * Check if the there is a next step - * @return {boolean} true if the current date has not passed the end date - */ - TimeStep.prototype.hasNext = function () { - return (this.current.valueOf() <= this._end.valueOf()); + this.body = null; }; /** - * Do the next step + * Repaint the component + * @return {boolean} Returns true if the component is resized */ - TimeStep.prototype.next = function() { - var prev = this.current.valueOf(); + TimeAxis.prototype.redraw = function () { + var options = this.options, + props = this.props, + foreground = this.dom.foreground, + background = this.dom.background; - // Two cases, needed to prevent issues with switching daylight savings - // (end of March and end of October) - if (this.current.getMonth() < 6) { - switch (this.scale) { - case TimeStep.SCALE.MILLISECOND: + // determine the correct parent DOM element (depending on option orientation) + var parent = (options.orientation == 'top') ? this.body.dom.top : this.body.dom.bottom; + var parentChanged = (foreground.parentNode !== parent); - this.current = new Date(this.current.valueOf() + this.step); break; - case TimeStep.SCALE.SECOND: this.current = new Date(this.current.valueOf() + this.step * 1000); break; - case TimeStep.SCALE.MINUTE: this.current = new Date(this.current.valueOf() + this.step * 1000 * 60); break; - case TimeStep.SCALE.HOUR: - this.current = new Date(this.current.valueOf() + this.step * 1000 * 60 * 60); - // in case of skipping an hour for daylight savings, adjust the hour again (else you get: 0h 5h 9h ... instead of 0h 4h 8h ...) - var h = this.current.getHours(); - this.current.setHours(h - (h % this.step)); - break; - case TimeStep.SCALE.WEEKDAY: // intentional fall through - case TimeStep.SCALE.DAY: this.current.setDate(this.current.getDate() + this.step); break; - case TimeStep.SCALE.MONTH: this.current.setMonth(this.current.getMonth() + this.step); break; - case TimeStep.SCALE.YEAR: this.current.setFullYear(this.current.getFullYear() + this.step); break; - default: break; - } + // calculate character width and height + this._calculateCharSize(); + + // TODO: recalculate sizes only needed when parent is resized or options is changed + var orientation = this.options.orientation, + showMinorLabels = this.options.showMinorLabels, + showMajorLabels = this.options.showMajorLabels; + + // determine the width and height of the elemens for the axis + props.minorLabelHeight = showMinorLabels ? props.minorCharHeight : 0; + props.majorLabelHeight = showMajorLabels ? props.majorCharHeight : 0; + props.height = props.minorLabelHeight + props.majorLabelHeight; + props.width = foreground.offsetWidth; + + props.minorLineHeight = this.body.domProps.root.height - props.majorLabelHeight - + (options.orientation == 'top' ? this.body.domProps.bottom.height : this.body.domProps.top.height); + props.minorLineWidth = 1; // TODO: really calculate width + props.majorLineHeight = props.minorLineHeight + props.majorLabelHeight; + props.majorLineWidth = 1; // TODO: really calculate width + + // take foreground and background offline while updating (is almost twice as fast) + var foregroundNextSibling = foreground.nextSibling; + var backgroundNextSibling = background.nextSibling; + foreground.parentNode && foreground.parentNode.removeChild(foreground); + background.parentNode && background.parentNode.removeChild(background); + + foreground.style.height = this.props.height + 'px'; + + this._repaintLabels(); + + // put DOM online again (at the same place) + if (foregroundNextSibling) { + parent.insertBefore(foreground, foregroundNextSibling); } else { - switch (this.scale) { - case TimeStep.SCALE.MILLISECOND: this.current = new Date(this.current.valueOf() + this.step); break; - case TimeStep.SCALE.SECOND: this.current.setSeconds(this.current.getSeconds() + this.step); break; - case TimeStep.SCALE.MINUTE: this.current.setMinutes(this.current.getMinutes() + this.step); break; - case TimeStep.SCALE.HOUR: this.current.setHours(this.current.getHours() + this.step); break; - case TimeStep.SCALE.WEEKDAY: // intentional fall through - case TimeStep.SCALE.DAY: this.current.setDate(this.current.getDate() + this.step); break; - case TimeStep.SCALE.MONTH: this.current.setMonth(this.current.getMonth() + this.step); break; - case TimeStep.SCALE.YEAR: this.current.setFullYear(this.current.getFullYear() + this.step); break; - default: break; - } + parent.appendChild(foreground) } - - if (this.step != 1) { - // round down to the correct major value - switch (this.scale) { - case TimeStep.SCALE.MILLISECOND: if(this.current.getMilliseconds() < this.step) this.current.setMilliseconds(0); break; - case TimeStep.SCALE.SECOND: if(this.current.getSeconds() < this.step) this.current.setSeconds(0); break; - case TimeStep.SCALE.MINUTE: if(this.current.getMinutes() < this.step) this.current.setMinutes(0); break; - case TimeStep.SCALE.HOUR: if(this.current.getHours() < this.step) this.current.setHours(0); break; - case TimeStep.SCALE.WEEKDAY: // intentional fall through - case TimeStep.SCALE.DAY: if(this.current.getDate() < this.step+1) this.current.setDate(1); break; - case TimeStep.SCALE.MONTH: if(this.current.getMonth() < this.step) this.current.setMonth(0); break; - case TimeStep.SCALE.YEAR: break; // nothing to do for year - default: break; - } + if (backgroundNextSibling) { + this.body.dom.backgroundVertical.insertBefore(background, backgroundNextSibling); } - - // safety mechanism: if current time is still unchanged, move to the end - if (this.current.valueOf() == prev) { - this.current = new Date(this._end.valueOf()); + else { + this.body.dom.backgroundVertical.appendChild(background) } - }; - - /** - * Get the current datetime - * @return {Date} current The current date - */ - TimeStep.prototype.getCurrent = function() { - return this.current; + return this._isResized() || parentChanged; }; /** - * Set a custom scale. Autoscaling will be disabled. - * For example setScale(SCALE.MINUTES, 5) will result - * in minor steps of 5 minutes, and major steps of an hour. - * - * @param {TimeStep.SCALE} newScale - * A scale. Choose from SCALE.MILLISECOND, - * SCALE.SECOND, SCALE.MINUTE, SCALE.HOUR, - * SCALE.WEEKDAY, SCALE.DAY, SCALE.MONTH, - * SCALE.YEAR. - * @param {Number} newStep A step size, by default 1. Choose for - * example 1, 2, 5, or 10. + * Repaint major and minor text labels and vertical grid lines + * @private */ - TimeStep.prototype.setScale = function(newScale, newStep) { - this.scale = newScale; + TimeAxis.prototype._repaintLabels = function () { + var orientation = this.options.orientation; - if (newStep > 0) { - this.step = newStep; - } + // calculate range and step (step such that we have space for 7 characters per label) + var start = util.convert(this.body.range.start, 'Number'), + end = util.convert(this.body.range.end, 'Number'), + minimumStep = this.body.util.toTime((this.props.minorCharWidth || 10) * 7).valueOf() + -this.body.util.toTime(0).valueOf(); + var step = new TimeStep(new Date(start), new Date(end), minimumStep); + this.step = step; - this.autoScale = false; - }; + // Move all DOM elements to a "redundant" list, where they + // can be picked for re-use, and clear the lists with lines and texts. + // At the end of the function _repaintLabels, left over elements will be cleaned up + var dom = this.dom; + dom.redundant.majorLines = dom.majorLines; + dom.redundant.majorTexts = dom.majorTexts; + dom.redundant.minorLines = dom.minorLines; + dom.redundant.minorTexts = dom.minorTexts; + dom.majorLines = []; + dom.majorTexts = []; + dom.minorLines = []; + dom.minorTexts = []; - /** - * Enable or disable autoscaling - * @param {boolean} enable If true, autoascaling is set true - */ - TimeStep.prototype.setAutoScale = function (enable) { - this.autoScale = enable; - }; + step.first(); + var xFirstMajorLabel = undefined; + var max = 0; + while (step.hasNext() && max < 1000) { + max++; + var cur = step.getCurrent(), + x = this.body.util.toScreen(cur), + isMajor = step.isMajor(); + // TODO: lines must have a width, such that we can create css backgrounds - /** - * Automatically determine the scale that bests fits the provided minimum step - * @param {Number} [minimumStep] The minimum step size in milliseconds - */ - TimeStep.prototype.setMinimumStep = function(minimumStep) { - if (minimumStep == undefined) { - return; + if (this.options.showMinorLabels) { + this._repaintMinorText(x, step.getLabelMinor(), orientation); + } + + if (isMajor && this.options.showMajorLabels) { + if (x > 0) { + if (xFirstMajorLabel == undefined) { + xFirstMajorLabel = x; + } + this._repaintMajorText(x, step.getLabelMajor(), orientation); + } + this._repaintMajorLine(x, orientation); + } + else { + this._repaintMinorLine(x, orientation); + } + + step.next(); } - var stepYear = (1000 * 60 * 60 * 24 * 30 * 12); - var stepMonth = (1000 * 60 * 60 * 24 * 30); - var stepDay = (1000 * 60 * 60 * 24); - var stepHour = (1000 * 60 * 60); - var stepMinute = (1000 * 60); - var stepSecond = (1000); - var stepMillisecond= (1); + // create a major label on the left when needed + if (this.options.showMajorLabels) { + var leftTime = this.body.util.toTime(0), + leftText = step.getLabelMajor(leftTime), + widthText = leftText.length * (this.props.majorCharWidth || 10) + 10; // upper bound estimation - // find the smallest step that is larger than the provided minimumStep - if (stepYear*1000 > minimumStep) {this.scale = TimeStep.SCALE.YEAR; this.step = 1000;} - if (stepYear*500 > minimumStep) {this.scale = TimeStep.SCALE.YEAR; this.step = 500;} - if (stepYear*100 > minimumStep) {this.scale = TimeStep.SCALE.YEAR; this.step = 100;} - if (stepYear*50 > minimumStep) {this.scale = TimeStep.SCALE.YEAR; this.step = 50;} - if (stepYear*10 > minimumStep) {this.scale = TimeStep.SCALE.YEAR; this.step = 10;} - if (stepYear*5 > minimumStep) {this.scale = TimeStep.SCALE.YEAR; this.step = 5;} - if (stepYear > minimumStep) {this.scale = TimeStep.SCALE.YEAR; this.step = 1;} - if (stepMonth*3 > minimumStep) {this.scale = TimeStep.SCALE.MONTH; this.step = 3;} - if (stepMonth > minimumStep) {this.scale = TimeStep.SCALE.MONTH; this.step = 1;} - if (stepDay*5 > minimumStep) {this.scale = TimeStep.SCALE.DAY; this.step = 5;} - if (stepDay*2 > minimumStep) {this.scale = TimeStep.SCALE.DAY; this.step = 2;} - if (stepDay > minimumStep) {this.scale = TimeStep.SCALE.DAY; this.step = 1;} - if (stepDay/2 > minimumStep) {this.scale = TimeStep.SCALE.WEEKDAY; this.step = 1;} - if (stepHour*4 > minimumStep) {this.scale = TimeStep.SCALE.HOUR; this.step = 4;} - if (stepHour > minimumStep) {this.scale = TimeStep.SCALE.HOUR; this.step = 1;} - if (stepMinute*15 > minimumStep) {this.scale = TimeStep.SCALE.MINUTE; this.step = 15;} - if (stepMinute*10 > minimumStep) {this.scale = TimeStep.SCALE.MINUTE; this.step = 10;} - if (stepMinute*5 > minimumStep) {this.scale = TimeStep.SCALE.MINUTE; this.step = 5;} - if (stepMinute > minimumStep) {this.scale = TimeStep.SCALE.MINUTE; this.step = 1;} - if (stepSecond*15 > minimumStep) {this.scale = TimeStep.SCALE.SECOND; this.step = 15;} - if (stepSecond*10 > minimumStep) {this.scale = TimeStep.SCALE.SECOND; this.step = 10;} - if (stepSecond*5 > minimumStep) {this.scale = TimeStep.SCALE.SECOND; this.step = 5;} - if (stepSecond > minimumStep) {this.scale = TimeStep.SCALE.SECOND; this.step = 1;} - if (stepMillisecond*200 > minimumStep) {this.scale = TimeStep.SCALE.MILLISECOND; this.step = 200;} - if (stepMillisecond*100 > minimumStep) {this.scale = TimeStep.SCALE.MILLISECOND; this.step = 100;} - if (stepMillisecond*50 > minimumStep) {this.scale = TimeStep.SCALE.MILLISECOND; this.step = 50;} - if (stepMillisecond*10 > minimumStep) {this.scale = TimeStep.SCALE.MILLISECOND; this.step = 10;} - if (stepMillisecond*5 > minimumStep) {this.scale = TimeStep.SCALE.MILLISECOND; this.step = 5;} - if (stepMillisecond > minimumStep) {this.scale = TimeStep.SCALE.MILLISECOND; this.step = 1;} + if (xFirstMajorLabel == undefined || widthText < xFirstMajorLabel) { + this._repaintMajorText(0, leftText, orientation); + } + } + + // Cleanup leftover DOM elements from the redundant list + util.forEach(this.dom.redundant, function (arr) { + while (arr.length) { + var elem = arr.pop(); + if (elem && elem.parentNode) { + elem.parentNode.removeChild(elem); + } + } + }); }; /** - * Snap a date to a rounded value. - * The snap intervals are dependent on the current scale and step. - * @param {Date} date the date to be snapped. - * @return {Date} snappedDate + * Create a minor label for the axis at position x + * @param {Number} x + * @param {String} text + * @param {String} orientation "top" or "bottom" (default) + * @private */ - TimeStep.prototype.snap = function(date) { - var clone = new Date(date.valueOf()); + TimeAxis.prototype._repaintMinorText = function (x, text, orientation) { + // reuse redundant label + var label = this.dom.redundant.minorTexts.shift(); - if (this.scale == TimeStep.SCALE.YEAR) { - var year = clone.getFullYear() + Math.round(clone.getMonth() / 12); - clone.setFullYear(Math.round(year / this.step) * this.step); - clone.setMonth(0); - clone.setDate(0); - clone.setHours(0); - clone.setMinutes(0); - clone.setSeconds(0); - clone.setMilliseconds(0); + if (!label) { + // create new label + var content = document.createTextNode(''); + label = document.createElement('div'); + label.appendChild(content); + label.className = 'text minor'; + this.dom.foreground.appendChild(label); } - else if (this.scale == TimeStep.SCALE.MONTH) { - if (clone.getDate() > 15) { - clone.setDate(1); - clone.setMonth(clone.getMonth() + 1); - // important: first set Date to 1, after that change the month. - } - else { - clone.setDate(1); - } + this.dom.minorTexts.push(label); - clone.setHours(0); - clone.setMinutes(0); - clone.setSeconds(0); - clone.setMilliseconds(0); - } - else if (this.scale == TimeStep.SCALE.DAY) { - //noinspection FallthroughInSwitchStatementJS - switch (this.step) { - case 5: - case 2: - clone.setHours(Math.round(clone.getHours() / 24) * 24); break; - default: - clone.setHours(Math.round(clone.getHours() / 12) * 12); break; - } - clone.setMinutes(0); - clone.setSeconds(0); - clone.setMilliseconds(0); - } - else if (this.scale == TimeStep.SCALE.WEEKDAY) { - //noinspection FallthroughInSwitchStatementJS - switch (this.step) { - case 5: - case 2: - clone.setHours(Math.round(clone.getHours() / 12) * 12); break; - default: - clone.setHours(Math.round(clone.getHours() / 6) * 6); break; - } - clone.setMinutes(0); - clone.setSeconds(0); - clone.setMilliseconds(0); - } - else if (this.scale == TimeStep.SCALE.HOUR) { - switch (this.step) { - case 4: - clone.setMinutes(Math.round(clone.getMinutes() / 60) * 60); break; - default: - clone.setMinutes(Math.round(clone.getMinutes() / 30) * 30); break; - } - clone.setSeconds(0); - clone.setMilliseconds(0); - } else if (this.scale == TimeStep.SCALE.MINUTE) { - //noinspection FallthroughInSwitchStatementJS - switch (this.step) { - case 15: - case 10: - clone.setMinutes(Math.round(clone.getMinutes() / 5) * 5); - clone.setSeconds(0); - break; - case 5: - clone.setSeconds(Math.round(clone.getSeconds() / 60) * 60); break; - default: - clone.setSeconds(Math.round(clone.getSeconds() / 30) * 30); break; - } - clone.setMilliseconds(0); - } - else if (this.scale == TimeStep.SCALE.SECOND) { - //noinspection FallthroughInSwitchStatementJS - switch (this.step) { - case 15: - case 10: - clone.setSeconds(Math.round(clone.getSeconds() / 5) * 5); - clone.setMilliseconds(0); - break; - case 5: - clone.setMilliseconds(Math.round(clone.getMilliseconds() / 1000) * 1000); break; - default: - clone.setMilliseconds(Math.round(clone.getMilliseconds() / 500) * 500); break; - } - } - else if (this.scale == TimeStep.SCALE.MILLISECOND) { - var step = this.step > 5 ? this.step / 2 : 1; - clone.setMilliseconds(Math.round(clone.getMilliseconds() / step) * step); - } - - return clone; + label.childNodes[0].nodeValue = text; + + label.style.top = (orientation == 'top') ? (this.props.majorLabelHeight + 'px') : '0'; + label.style.left = x + 'px'; + //label.title = title; // TODO: this is a heavy operation }; /** - * Check if the current value is a major value (for example when the step - * is DAY, a major value is each first day of the MONTH) - * @return {boolean} true if current date is major, else false. + * Create a Major label for the axis at position x + * @param {Number} x + * @param {String} text + * @param {String} orientation "top" or "bottom" (default) + * @private */ - TimeStep.prototype.isMajor = function() { - switch (this.scale) { - case TimeStep.SCALE.MILLISECOND: - return (this.current.getMilliseconds() == 0); - case TimeStep.SCALE.SECOND: - return (this.current.getSeconds() == 0); - case TimeStep.SCALE.MINUTE: - return (this.current.getHours() == 0) && (this.current.getMinutes() == 0); - // Note: this is no bug. Major label is equal for both minute and hour scale - case TimeStep.SCALE.HOUR: - return (this.current.getHours() == 0); - case TimeStep.SCALE.WEEKDAY: // intentional fall through - case TimeStep.SCALE.DAY: - return (this.current.getDate() == 1); - case TimeStep.SCALE.MONTH: - return (this.current.getMonth() == 0); - case TimeStep.SCALE.YEAR: - return false; - default: - return false; + TimeAxis.prototype._repaintMajorText = function (x, text, orientation) { + // reuse redundant label + var label = this.dom.redundant.majorTexts.shift(); + + if (!label) { + // create label + var content = document.createTextNode(text); + label = document.createElement('div'); + label.className = 'text major'; + label.appendChild(content); + this.dom.foreground.appendChild(label); } - }; + this.dom.majorTexts.push(label); + label.childNodes[0].nodeValue = text; + //label.title = title; // TODO: this is a heavy operation + + label.style.top = (orientation == 'top') ? '0' : (this.props.minorLabelHeight + 'px'); + label.style.left = x + 'px'; + }; /** - * Returns formatted text for the minor axislabel, depending on the current - * date and the scale. For example when scale is MINUTE, the current time is - * formatted as "hh:mm". - * @param {Date} [date] custom date. if not provided, current date is taken + * Create a minor line for the axis at position x + * @param {Number} x + * @param {String} orientation "top" or "bottom" (default) + * @private */ - TimeStep.prototype.getLabelMinor = function(date) { - if (date == undefined) { - date = this.current; + TimeAxis.prototype._repaintMinorLine = function (x, orientation) { + // reuse redundant line + var line = this.dom.redundant.minorLines.shift(); + + if (!line) { + // create vertical line + line = document.createElement('div'); + line.className = 'grid vertical minor'; + this.dom.background.appendChild(line); } + this.dom.minorLines.push(line); - switch (this.scale) { - case TimeStep.SCALE.MILLISECOND: return moment(date).format('SSS'); - case TimeStep.SCALE.SECOND: return moment(date).format('s'); - case TimeStep.SCALE.MINUTE: return moment(date).format('HH:mm'); - case TimeStep.SCALE.HOUR: return moment(date).format('HH:mm'); - case TimeStep.SCALE.WEEKDAY: return moment(date).format('ddd D'); - case TimeStep.SCALE.DAY: return moment(date).format('D'); - case TimeStep.SCALE.MONTH: return moment(date).format('MMM'); - case TimeStep.SCALE.YEAR: return moment(date).format('YYYY'); - default: return ''; + var props = this.props; + if (orientation == 'top') { + line.style.top = props.majorLabelHeight + 'px'; } + else { + line.style.top = this.body.domProps.top.height + 'px'; + } + line.style.height = props.minorLineHeight + 'px'; + line.style.left = (x - props.minorLineWidth / 2) + 'px'; }; - /** - * Returns formatted text for the major axis label, depending on the current - * date and the scale. For example when scale is MINUTE, the major scale is - * hours, and the hour will be formatted as "hh". - * @param {Date} [date] custom date. if not provided, current date is taken - */ - TimeStep.prototype.getLabelMajor = function(date) { - if (date == undefined) { - date = this.current; + * Create a Major line for the axis at position x + * @param {Number} x + * @param {String} orientation "top" or "bottom" (default) + * @private + */ + TimeAxis.prototype._repaintMajorLine = function (x, orientation) { + // reuse redundant line + var line = this.dom.redundant.majorLines.shift(); + + if (!line) { + // create vertical line + line = document.createElement('DIV'); + line.className = 'grid vertical major'; + this.dom.background.appendChild(line); } + this.dom.majorLines.push(line); - //noinspection FallthroughInSwitchStatementJS - switch (this.scale) { - case TimeStep.SCALE.MILLISECOND:return moment(date).format('HH:mm:ss'); - case TimeStep.SCALE.SECOND: return moment(date).format('D MMMM HH:mm'); - case TimeStep.SCALE.MINUTE: - case TimeStep.SCALE.HOUR: return moment(date).format('ddd D MMMM'); - case TimeStep.SCALE.WEEKDAY: - case TimeStep.SCALE.DAY: return moment(date).format('MMMM YYYY'); - case TimeStep.SCALE.MONTH: return moment(date).format('YYYY'); - case TimeStep.SCALE.YEAR: return ''; - default: return ''; + var props = this.props; + if (orientation == 'top') { + line.style.top = '0'; + } + else { + line.style.top = this.body.domProps.top.height + 'px'; } + line.style.left = (x - props.majorLineWidth / 2) + 'px'; + line.style.height = props.majorLineHeight + 'px'; }; - module.exports = TimeStep; + /** + * Determine the size of text on the axis (both major and minor axis). + * The size is calculated only once and then cached in this.props. + * @private + */ + TimeAxis.prototype._calculateCharSize = function () { + // Note: We calculate char size with every redraw. Size may change, for + // example when any of the timelines parents had display:none for example. + // determine the char width and height on the minor axis + if (!this.dom.measureCharMinor) { + this.dom.measureCharMinor = document.createElement('DIV'); + this.dom.measureCharMinor.className = 'text minor measure'; + this.dom.measureCharMinor.style.position = 'absolute'; -/***/ }, -/* 26 */ -/***/ function(module, exports, __webpack_require__) { + this.dom.measureCharMinor.appendChild(document.createTextNode('0')); + this.dom.foreground.appendChild(this.dom.measureCharMinor); + } + this.props.minorCharHeight = this.dom.measureCharMinor.clientHeight; + this.props.minorCharWidth = this.dom.measureCharMinor.clientWidth; - var util = __webpack_require__(1); - var Component = __webpack_require__(22); + // determine the char width and height on the major axis + if (!this.dom.measureCharMajor) { + this.dom.measureCharMajor = document.createElement('DIV'); + this.dom.measureCharMajor.className = 'text minor measure'; + this.dom.measureCharMajor.style.position = 'absolute'; + + this.dom.measureCharMajor.appendChild(document.createTextNode('0')); + this.dom.foreground.appendChild(this.dom.measureCharMajor); + } + this.props.majorCharHeight = this.dom.measureCharMajor.clientHeight; + this.props.majorCharWidth = this.dom.measureCharMajor.clientWidth; + }; /** - * A current time bar - * @param {{range: Range, dom: Object, domProps: Object}} body - * @param {Object} [options] Available parameters: - * {Boolean} [showCurrentTime] - * @constructor CurrentTime - * @extends Component + * Snap a date to a rounded value. + * The snap intervals are dependent on the current scale and step. + * @param {Date} date the date to be snapped. + * @return {Date} snappedDate */ - function CurrentTime (body, options) { - this.body = body; + TimeAxis.prototype.snap = function(date) { + return this.step.snap(date); + }; - // default options - this.defaultOptions = { - showCurrentTime: true - }; - this.options = util.extend({}, this.defaultOptions); + module.exports = TimeAxis; - this._create(); - this.setOptions(options); - } +/***/ }, +/* 28 */ +/***/ function(module, exports, __webpack_require__) { - CurrentTime.prototype = new Component(); + var Hammer = __webpack_require__(41); /** - * Create the HTML DOM for the current time bar - * @private + * @constructor Item + * @param {Object} data Object containing (optional) parameters type, + * start, end, content, group, className. + * @param {{toScreen: function, toTime: function}} conversion + * Conversion functions from time to screen and vice versa + * @param {Object} options Configuration options + * // TODO: describe available options */ - CurrentTime.prototype._create = function() { - var bar = document.createElement('div'); - bar.className = 'currenttime'; - bar.style.position = 'absolute'; - bar.style.top = '0px'; - bar.style.height = '100%'; + function Item (data, conversion, options) { + this.id = null; + this.parent = null; + this.data = data; + this.dom = null; + this.conversion = conversion || {}; + this.options = options || {}; - this.bar = bar; - }; + this.selected = false; + this.displayed = false; + this.dirty = true; + + this.top = null; + this.left = null; + this.width = null; + this.height = null; + } /** - * Destroy the CurrentTime bar + * Select current item */ - CurrentTime.prototype.destroy = function () { - this.options.showCurrentTime = false; - this.redraw(); // will remove the bar from the DOM and stop refreshing - - this.body = null; + Item.prototype.select = function() { + this.selected = true; + if (this.displayed) this.redraw(); }; /** - * Set options for the component. Options will be merged in current options. - * @param {Object} options Available parameters: - * {boolean} [showCurrentTime] + * Unselect current item */ - CurrentTime.prototype.setOptions = function(options) { - if (options) { - // copy all options that we know - util.selectiveExtend(['showCurrentTime'], this.options, options); - } + Item.prototype.unselect = function() { + this.selected = false; + if (this.displayed) this.redraw(); }; /** - * Repaint the component - * @return {boolean} Returns true if the component is resized + * Set a parent for the item + * @param {ItemSet | Group} parent */ - CurrentTime.prototype.redraw = function() { - if (this.options.showCurrentTime) { - 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); - - this.start(); + Item.prototype.setParent = function(parent) { + if (this.displayed) { + this.hide(); + this.parent = parent; + if (this.parent) { + this.show(); } - - var now = new Date(); - var x = this.body.util.toScreen(now); - - this.bar.style.left = x + 'px'; - this.bar.title = 'Current time: ' + now; } else { - // remove the line from the DOM - if (this.bar.parentNode) { - this.bar.parentNode.removeChild(this.bar); - } - this.stop(); + this.parent = parent; } + }; + /** + * Check whether this item is visible inside given range + * @returns {{start: Number, end: Number}} range with a timestamp for start and end + * @returns {boolean} True if visible + */ + Item.prototype.isVisible = function(range) { + // Should be implemented by Item implementations return false; }; /** - * Start auto refreshing the current time bar + * Show the Item in the DOM (when not already visible) + * @return {Boolean} changed */ - CurrentTime.prototype.start = function() { - var me = this; - - function update () { - me.stop(); - - // determine interval to refresh - var scale = me.body.range.conversion(me.body.domProps.center.width).scale; - var interval = 1 / scale / 10; - if (interval < 30) interval = 30; - if (interval > 1000) interval = 1000; - - me.redraw(); - - // start a timer to adjust for the new time - me.currentTimeTimer = setTimeout(update, interval); - } - - update(); + Item.prototype.show = function() { + return false; }; /** - * Stop auto refreshing the current time bar + * Hide the Item from the DOM (when visible) + * @return {Boolean} changed */ - CurrentTime.prototype.stop = function() { - if (this.currentTimeTimer !== undefined) { - clearTimeout(this.currentTimeTimer); - delete this.currentTimeTimer; - } + Item.prototype.hide = function() { + return false; }; - module.exports = CurrentTime; - - -/***/ }, -/* 27 */ -/***/ function(module, exports, __webpack_require__) { - - var Hammer = __webpack_require__(18); - var util = __webpack_require__(1); - var Component = __webpack_require__(22); - /** - * A custom time bar - * @param {{range: Range, dom: Object}} body - * @param {Object} [options] Available parameters: - * {Boolean} [showCustomTime] - * @constructor CustomTime - * @extends Component + * Repaint the item */ + Item.prototype.redraw = function() { + // should be implemented by the item + }; - function CustomTime (body, options) { - this.body = body; - - // default options - this.defaultOptions = { - showCustomTime: false - }; - this.options = util.extend({}, this.defaultOptions); - - this.customTime = new Date(); - this.eventParams = {}; // stores state parameters while dragging the bar - - // create the DOM - this._create(); - - this.setOptions(options); - } - - CustomTime.prototype = new Component(); + /** + * Reposition the Item horizontally + */ + Item.prototype.repositionX = function() { + // should be implemented by the item + }; /** - * Set options for the component. Options will be merged in current options. - * @param {Object} options Available parameters: - * {boolean} [showCustomTime] + * Reposition the Item vertically */ - CustomTime.prototype.setOptions = function(options) { - if (options) { - // copy all options that we know - util.selectiveExtend(['showCustomTime'], this.options, options); - } + Item.prototype.repositionY = function() { + // should be implemented by the item }; /** - * Create the DOM for the custom time - * @private + * Repaint a delete button on the top right of the item when the item is selected + * @param {HTMLElement} anchor + * @protected */ - CustomTime.prototype._create = function() { - var bar = document.createElement('div'); - bar.className = 'customtime'; - bar.style.position = 'absolute'; - bar.style.top = '0px'; - bar.style.height = '100%'; - this.bar = bar; + Item.prototype._repaintDeleteButton = function (anchor) { + if (this.selected && this.options.editable.remove && !this.dom.deleteButton) { + // create and show button + var me = this; - 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); + var deleteButton = document.createElement('div'); + deleteButton.className = 'delete'; + deleteButton.title = 'Delete this item'; - // attach event listeners - this.hammer = Hammer(bar, { - prevent_default: true - }); - this.hammer.on('dragstart', this._onDragStart.bind(this)); - this.hammer.on('drag', this._onDrag.bind(this)); - this.hammer.on('dragend', this._onDragEnd.bind(this)); + Hammer(deleteButton, { + preventDefault: true + }).on('tap', function (event) { + me.parent.removeFromDataSet(me); + event.stopPropagation(); + }); + + anchor.appendChild(deleteButton); + this.dom.deleteButton = deleteButton; + } + else if (!this.selected && this.dom.deleteButton) { + // remove button + if (this.dom.deleteButton.parentNode) { + this.dom.deleteButton.parentNode.removeChild(this.dom.deleteButton); + } + this.dom.deleteButton = null; + } }; - /** - * Destroy the CustomTime bar - */ - CustomTime.prototype.destroy = function () { - this.options.showCustomTime = false; - this.redraw(); // will remove the bar from the DOM + module.exports = Item; - this.hammer.enable(false); - this.hammer = null; - this.body = null; - }; +/***/ }, +/* 29 */ +/***/ function(module, exports, __webpack_require__) { + + var Item = __webpack_require__(28); /** - * Repaint the component - * @return {boolean} Returns true if the component is resized + * @constructor ItemBox + * @extends Item + * @param {Object} data Object containing parameters start + * content, className. + * @param {{toScreen: function, toTime: function}} conversion + * Conversion functions from time to screen and vice versa + * @param {Object} [options] Configuration options + * // TODO: describe available options */ - CustomTime.prototype.redraw = function () { - if (this.options.showCustomTime) { - 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); + function ItemBox (data, conversion, options) { + this.props = { + dot: { + width: 0, + height: 0 + }, + line: { + width: 0, + height: 0 } + }; - var x = this.body.util.toScreen(this.customTime); - - this.bar.style.left = x + 'px'; - this.bar.title = 'Time: ' + this.customTime; - } - else { - // remove the line from the DOM - if (this.bar.parentNode) { - this.bar.parentNode.removeChild(this.bar); + // validate data + if (data) { + if (data.start == undefined) { + throw new Error('Property "start" missing in item ' + data); } } - return false; - }; + Item.call(this, data, conversion, options); + } - /** - * Set custom time. - * @param {Date} time - */ - CustomTime.prototype.setCustomTime = function(time) { - this.customTime = new Date(time.valueOf()); - this.redraw(); - }; + ItemBox.prototype = new Item (null, null, null); /** - * Retrieve the current custom time. - * @return {Date} customTime + * Check whether this item is visible inside given range + * @returns {{start: Number, end: Number}} range with a timestamp for start and end + * @returns {boolean} True if visible */ - CustomTime.prototype.getCustomTime = function() { - return new Date(this.customTime.valueOf()); + ItemBox.prototype.isVisible = function(range) { + // determine visibility + // TODO: account for the real width of the item. Right now we just add 1/4 to the window + var interval = (range.end - range.start) / 4; + return (this.data.start > range.start - interval) && (this.data.start < range.end + interval); }; /** - * Start moving horizontally - * @param {Event} event - * @private + * Repaint the item */ - CustomTime.prototype._onDragStart = function(event) { - this.eventParams.dragging = true; - this.eventParams.customTime = this.customTime; + ItemBox.prototype.redraw = function() { + var dom = this.dom; + if (!dom) { + // create DOM + this.dom = {}; + dom = this.dom; - event.stopPropagation(); - event.preventDefault(); - }; + // create main box + dom.box = document.createElement('DIV'); - /** - * Perform moving operating. - * @param {Event} event - * @private - */ - CustomTime.prototype._onDrag = function (event) { - if (!this.eventParams.dragging) return; + // contents box (inside the background box). used for making margins + dom.content = document.createElement('DIV'); + dom.content.className = 'content'; + dom.box.appendChild(dom.content); - var deltaX = event.gesture.deltaX, - x = this.body.util.toScreen(this.eventParams.customTime) + deltaX, - time = this.body.util.toTime(x); + // line to axis + dom.line = document.createElement('DIV'); + dom.line.className = 'line'; - this.setCustomTime(time); + // dot on axis + dom.dot = document.createElement('DIV'); + dom.dot.className = 'dot'; - // fire a timechange event - this.body.emitter.emit('timechange', { - time: new Date(this.customTime.valueOf()) - }); + // attach this item as attribute + dom.box['timeline-item'] = this; + } - event.stopPropagation(); - event.preventDefault(); - }; + // append DOM to parent DOM + if (!this.parent) { + throw new Error('Cannot redraw item: no parent attached'); + } + if (!dom.box.parentNode) { + var foreground = this.parent.dom.foreground; + if (!foreground) throw new Error('Cannot redraw time axis: parent has no foreground container element'); + foreground.appendChild(dom.box); + } + if (!dom.line.parentNode) { + var background = this.parent.dom.background; + if (!background) throw new Error('Cannot redraw time axis: parent has no background container element'); + background.appendChild(dom.line); + } + if (!dom.dot.parentNode) { + var axis = this.parent.dom.axis; + if (!background) throw new Error('Cannot redraw time axis: parent has no axis container element'); + axis.appendChild(dom.dot); + } + this.displayed = true; - /** - * Stop moving operating. - * @param {event} event - * @private - */ - CustomTime.prototype._onDragEnd = function (event) { - if (!this.eventParams.dragging) return; + // update contents + if (this.data.content != this.content) { + this.content = this.data.content; + if (this.content instanceof Element) { + dom.content.innerHTML = ''; + dom.content.appendChild(this.content); + } + else if (this.data.content != undefined) { + dom.content.innerHTML = this.content; + } + else { + throw new Error('Property "content" missing in item ' + this.data.id); + } - // fire a timechanged event - this.body.emitter.emit('timechanged', { - time: new Date(this.customTime.valueOf()) - }); + this.dirty = true; + } - event.stopPropagation(); - event.preventDefault(); + // update title + if (this.data.title != this.title) { + dom.box.title = this.data.title; + this.title = this.data.title; + } + + // update class + var className = (this.data.className? ' ' + this.data.className : '') + + (this.selected ? ' selected' : ''); + if (this.className != className) { + this.className = className; + dom.box.className = 'item box' + className; + dom.line.className = 'item line' + className; + dom.dot.className = 'item dot' + className; + + this.dirty = true; + } + + // recalculate size + if (this.dirty) { + this.props.dot.height = dom.dot.offsetHeight; + this.props.dot.width = dom.dot.offsetWidth; + this.props.line.width = dom.line.offsetWidth; + this.width = dom.box.offsetWidth; + this.height = dom.box.offsetHeight; + + this.dirty = false; + } + + this._repaintDeleteButton(dom.box); }; - module.exports = CustomTime; + /** + * Show the item in the DOM (when not already displayed). The items DOM will + * be created when needed. + */ + ItemBox.prototype.show = function() { + if (!this.displayed) { + this.redraw(); + } + }; + /** + * Hide the item from the DOM (when visible) + */ + ItemBox.prototype.hide = function() { + if (this.displayed) { + var dom = this.dom; -/***/ }, -/* 28 */ -/***/ function(module, exports, __webpack_require__) { + if (dom.box.parentNode) dom.box.parentNode.removeChild(dom.box); + if (dom.line.parentNode) dom.line.parentNode.removeChild(dom.line); + if (dom.dot.parentNode) dom.dot.parentNode.removeChild(dom.dot); - var Hammer = __webpack_require__(18); - var util = __webpack_require__(1); - var DataSet = __webpack_require__(7); - var DataView = __webpack_require__(8); - var Component = __webpack_require__(22); - var Group = __webpack_require__(29); - var ItemBox = __webpack_require__(33); - var ItemPoint = __webpack_require__(34); - var ItemRange = __webpack_require__(31); + this.top = null; + this.left = null; + this.displayed = false; + } + }; - var UNGROUPED = '__ungrouped__'; // reserved group id for ungrouped items + /** + * Reposition the item horizontally + * @Override + */ + ItemBox.prototype.repositionX = function() { + var start = this.conversion.toScreen(this.data.start), + align = this.options.align, + left, + box = this.dom.box, + line = this.dom.line, + dot = this.dom.dot; + + // calculate left position of the box + if (align == 'right') { + this.left = start - this.width; + } + else if (align == 'left') { + this.left = start; + } + else { + // default or 'center' + this.left = start - this.width / 2; + } + + // reposition box + box.style.left = this.left + 'px'; + + // reposition line + line.style.left = (start - this.props.line.width / 2) + 'px'; + + // reposition dot + dot.style.left = (start - this.props.dot.width / 2) + 'px'; + }; /** - * An ItemSet holds a set of items and ranges which can be displayed in a - * range. The width is determined by the parent of the ItemSet, and the height - * is determined by the size of the items. - * @param {{dom: Object, domProps: Object, emitter: Emitter, range: Range}} body - * @param {Object} [options] See ItemSet.setOptions for the available options. - * @constructor ItemSet - * @extends Component + * Reposition the item vertically + * @Override */ - function ItemSet(body, options) { - this.body = body; + ItemBox.prototype.repositionY = function() { + var orientation = this.options.orientation, + box = this.dom.box, + line = this.dom.line, + dot = this.dom.dot; - this.defaultOptions = { - type: null, // 'box', 'point', 'range' - orientation: 'bottom', // 'top' or 'bottom' - align: 'center', // alignment of box items - stack: true, - groupOrder: null, + if (orientation == 'top') { + box.style.top = (this.top || 0) + 'px'; - selectable: true, - editable: { - updateTime: false, - updateGroup: false, - add: false, - remove: false - }, + line.style.top = '0'; + line.style.height = (this.parent.top + this.top + 1) + 'px'; + line.style.bottom = ''; + } + else { // orientation 'bottom' + var itemSetHeight = this.parent.itemSet.props.height; // TODO: this is nasty + var lineHeight = itemSetHeight - this.parent.top - this.parent.height + this.top; - onAdd: function (item, callback) { - callback(item); - }, - onUpdate: function (item, callback) { - callback(item); - }, - onMove: function (item, callback) { - callback(item); - }, - onRemove: function (item, callback) { - callback(item); - }, + box.style.top = (this.parent.height - this.top - this.height || 0) + 'px'; + line.style.top = (itemSetHeight - lineHeight) + 'px'; + line.style.bottom = '0'; + } - margin: { - item: { - horizontal: 10, - vertical: 10 - }, - axis: 20 - }, - padding: 5 - }; + dot.style.top = (-this.props.dot.height / 2) + 'px'; + }; - // options is shared by this ItemSet and all its items - this.options = util.extend({}, this.defaultOptions); + module.exports = ItemBox; - // options for getting items from the DataSet with the correct type - this.itemOptions = { - type: {start: 'Date', end: 'Date'} - }; - this.conversion = { - toScreen: body.util.toScreen, - toTime: body.util.toTime - }; - this.dom = {}; - this.props = {}; - this.hammer = null; +/***/ }, +/* 30 */ +/***/ function(module, exports, __webpack_require__) { - var me = this; - this.itemsData = null; // DataSet - this.groupsData = null; // DataSet + var Item = __webpack_require__(28); - // listeners for the DataSet of the items - this.itemListeners = { - 'add': function (event, params, senderId) { - me._onAdd(params.items); - }, - 'update': function (event, params, senderId) { - me._onUpdate(params.items); + /** + * @constructor ItemPoint + * @extends Item + * @param {Object} data Object containing parameters start + * content, className. + * @param {{toScreen: function, toTime: function}} conversion + * Conversion functions from time to screen and vice versa + * @param {Object} [options] Configuration options + * // TODO: describe available options + */ + function ItemPoint (data, conversion, options) { + this.props = { + dot: { + top: 0, + width: 0, + height: 0 }, - 'remove': function (event, params, senderId) { - me._onRemove(params.items); + content: { + height: 0, + marginLeft: 0 } }; - // listeners for the DataSet of the groups - this.groupListeners = { - 'add': function (event, params, senderId) { - me._onAddGroups(params.items); - }, - 'update': function (event, params, senderId) { - me._onUpdateGroups(params.items); - }, - 'remove': function (event, params, senderId) { - me._onRemoveGroups(params.items); + // validate data + if (data) { + if (data.start == undefined) { + throw new Error('Property "start" missing in item ' + data); } - }; - - this.items = {}; // object with an Item for every data item - this.groups = {}; // Group object for every group - this.groupIds = []; - - this.selection = []; // list with the ids of all selected nodes - this.stackDirty = true; // if true, all items will be restacked on next redraw - - this.touchParams = {}; // stores properties while dragging - // create the HTML DOM - - this._create(); + } - this.setOptions(options); + Item.call(this, data, conversion, options); } - ItemSet.prototype = new Component(); + ItemPoint.prototype = new Item (null, null, null); - // available item types will be registered here - ItemSet.types = { - box: ItemBox, - range: ItemRange, - point: ItemPoint + /** + * Check whether this item is visible inside given range + * @returns {{start: Number, end: Number}} range with a timestamp for start and end + * @returns {boolean} True if visible + */ + ItemPoint.prototype.isVisible = function(range) { + // determine visibility + // TODO: account for the real width of the item. Right now we just add 1/4 to the window + var interval = (range.end - range.start) / 4; + return (this.data.start > range.start - interval) && (this.data.start < range.end + interval); }; /** - * Create the HTML DOM for the ItemSet + * Repaint the item */ - ItemSet.prototype._create = function(){ - var frame = document.createElement('div'); - frame.className = 'itemset'; - frame['timeline-itemset'] = this; - this.dom.frame = frame; - - // create background panel - var background = document.createElement('div'); - background.className = 'background'; - frame.appendChild(background); - this.dom.background = background; - - // create foreground panel - var foreground = document.createElement('div'); - foreground.className = 'foreground'; - frame.appendChild(foreground); - this.dom.foreground = foreground; + ItemPoint.prototype.redraw = function() { + var dom = this.dom; + if (!dom) { + // create DOM + this.dom = {}; + dom = this.dom; - // create axis panel - var axis = document.createElement('div'); - axis.className = 'axis'; - this.dom.axis = axis; + // background box + dom.point = document.createElement('div'); + // className is updated in redraw() - // create labelset - var labelSet = document.createElement('div'); - labelSet.className = 'labelset'; - this.dom.labelSet = labelSet; + // contents box, right from the dot + dom.content = document.createElement('div'); + dom.content.className = 'content'; + dom.point.appendChild(dom.content); - // create ungrouped Group - this._updateUngrouped(); + // dot at start + dom.dot = document.createElement('div'); + dom.point.appendChild(dom.dot); - // attach event listeners - // Note: we bind to the centerContainer for the case where the height - // of the center container is larger than of the ItemSet, so we - // can click in the empty area to create a new item or deselect an item. - this.hammer = Hammer(this.body.dom.centerContainer, { - prevent_default: true - }); + // attach this item as attribute + dom.point['timeline-item'] = this; + } - // drag items when selected - this.hammer.on('touch', this._onTouch.bind(this)); - this.hammer.on('dragstart', this._onDragStart.bind(this)); - this.hammer.on('drag', this._onDrag.bind(this)); - this.hammer.on('dragend', this._onDragEnd.bind(this)); + // append DOM to parent DOM + if (!this.parent) { + throw new Error('Cannot redraw item: no parent attached'); + } + if (!dom.point.parentNode) { + var foreground = this.parent.dom.foreground; + if (!foreground) { + throw new Error('Cannot redraw time axis: parent has no foreground container element'); + } + foreground.appendChild(dom.point); + } + this.displayed = true; - // single select (or unselect) when tapping an item - this.hammer.on('tap', this._onSelectItem.bind(this)); + // update contents + if (this.data.content != this.content) { + this.content = this.data.content; + if (this.content instanceof Element) { + dom.content.innerHTML = ''; + dom.content.appendChild(this.content); + } + else if (this.data.content != undefined) { + dom.content.innerHTML = this.content; + } + else { + throw new Error('Property "content" missing in item ' + this.data.id); + } - // multi select when holding mouse/touch, or on ctrl+click - this.hammer.on('hold', this._onMultiSelectItem.bind(this)); + this.dirty = true; + } - // add item on doubletap - this.hammer.on('doubletap', this._onAddItem.bind(this)); + // update title + if (this.data.title != this.title) { + dom.point.title = this.data.title; + this.title = this.data.title; + } - // attach to the DOM - this.show(); - }; + // update class + var className = (this.data.className? ' ' + this.data.className : '') + + (this.selected ? ' selected' : ''); + if (this.className != className) { + this.className = className; + dom.point.className = 'item point' + className; + dom.dot.className = 'item dot' + className; - /** - * Set options for the ItemSet. Existing options will be extended/overwritten. - * @param {Object} [options] The following options are available: - * {String} type - * Default type for the items. Choose from 'box' - * (default), 'point', or 'range'. The default - * Style can be overwritten by individual items. - * {String} align - * Alignment for the items, only applicable for - * ItemBox. Choose 'center' (default), 'left', or - * 'right'. - * {String} orientation - * Orientation of the item set. Choose 'top' or - * 'bottom' (default). - * {Function} groupOrder - * A sorting function for ordering groups - * {Boolean} stack - * If true (deafult), items will be stacked on - * top of each other. - * {Number} margin.axis - * Margin between the axis and the items in pixels. - * Default is 20. - * {Number} margin.item.horizontal - * Horizontal margin between items in pixels. - * Default is 10. - * {Number} margin.item.vertical - * Vertical Margin between items in pixels. - * Default is 10. - * {Number} margin.item - * Margin between items in pixels in both horizontal - * and vertical direction. Default is 10. - * {Number} margin - * Set margin for both axis and items in pixels. - * {Number} padding - * Padding of the contents of an item in pixels. - * Must correspond with the items css. Default is 5. - * {Boolean} selectable - * If true (default), items can be selected. - * {Boolean} editable - * Set all editable options to true or false - * {Boolean} editable.updateTime - * Allow dragging an item to an other moment in time - * {Boolean} editable.updateGroup - * Allow dragging an item to an other group - * {Boolean} editable.add - * Allow creating new items on double tap - * {Boolean} editable.remove - * Allow removing items by clicking the delete button - * top right of a selected item. - * {Function(item: Item, callback: Function)} onAdd - * Callback function triggered when an item is about to be added: - * when the user double taps an empty space in the Timeline. - * {Function(item: Item, callback: Function)} onUpdate - * Callback function fired when an item is about to be updated. - * This function typically has to show a dialog where the user - * change the item. If not implemented, nothing happens. - * {Function(item: Item, callback: Function)} onMove - * Fired when an item has been moved. If not implemented, - * the move action will be accepted. - * {Function(item: Item, callback: Function)} onRemove - * Fired when an item is about to be deleted. - * If not implemented, the item will be always removed. - */ - ItemSet.prototype.setOptions = function(options) { - if (options) { - // copy all options that we know - var fields = ['type', 'align', 'orientation', 'padding', 'stack', 'selectable', 'groupOrder']; - util.selectiveExtend(fields, this.options, options); + this.dirty = true; + } - if ('margin' in options) { - if (typeof options.margin === 'number') { - this.options.margin.axis = options.margin; - this.options.margin.item.horizontal = options.margin; - this.options.margin.item.vertical = options.margin; - } - else if (typeof options.margin === 'object') { - util.selectiveExtend(['axis'], this.options.margin, options.margin); - if ('item' in options.margin) { - if (typeof options.margin.item === 'number') { - this.options.margin.item.horizontal = options.margin.item; - this.options.margin.item.vertical = options.margin.item; - } - else if (typeof options.margin.item === 'object') { - util.selectiveExtend(['horizontal', 'vertical'], this.options.margin.item, options.margin.item); - } - } - } - } + // recalculate size + if (this.dirty) { + this.width = dom.point.offsetWidth; + this.height = dom.point.offsetHeight; + this.props.dot.width = dom.dot.offsetWidth; + this.props.dot.height = dom.dot.offsetHeight; + this.props.content.height = dom.content.offsetHeight; - if ('editable' in options) { - if (typeof options.editable === 'boolean') { - this.options.editable.updateTime = options.editable; - this.options.editable.updateGroup = options.editable; - this.options.editable.add = options.editable; - this.options.editable.remove = options.editable; - } - else if (typeof options.editable === 'object') { - util.selectiveExtend(['updateTime', 'updateGroup', 'add', 'remove'], this.options.editable, options.editable); - } - } + // resize contents + dom.content.style.marginLeft = 2 * this.props.dot.width + 'px'; + //dom.content.style.marginRight = ... + 'px'; // TODO: margin right - // callback functions - var addCallback = (function (name) { - if (name in options) { - var fn = options[name]; - if (!(fn instanceof Function)) { - throw new Error('option ' + name + ' must be a function ' + name + '(item, callback)'); - } - this.options[name] = fn; - } - }).bind(this); - ['onAdd', 'onUpdate', 'onRemove', 'onMove'].forEach(addCallback); + dom.dot.style.top = ((this.height - this.props.dot.height) / 2) + 'px'; + dom.dot.style.left = (this.props.dot.width / 2) + 'px'; - // force the itemSet to refresh: options like orientation and margins may be changed - this.markDirty(); + this.dirty = false; } + + this._repaintDeleteButton(dom.point); }; /** - * Mark the ItemSet dirty so it will refresh everything with next redraw + * Show the item in the DOM (when not already visible). The items DOM will + * be created when needed. */ - ItemSet.prototype.markDirty = function() { - this.groupIds = []; - this.stackDirty = true; + ItemPoint.prototype.show = function() { + if (!this.displayed) { + this.redraw(); + } }; /** - * Destroy the ItemSet + * Hide the item from the DOM (when visible) */ - ItemSet.prototype.destroy = function() { - this.hide(); - this.setItems(null); - this.setGroups(null); + ItemPoint.prototype.hide = function() { + if (this.displayed) { + if (this.dom.point.parentNode) { + this.dom.point.parentNode.removeChild(this.dom.point); + } - this.hammer = null; + this.top = null; + this.left = null; - this.body = null; - this.conversion = null; + this.displayed = false; + } }; /** - * Hide the component from the DOM + * Reposition the item horizontally + * @Override */ - ItemSet.prototype.hide = function() { - // remove the frame containing the items - if (this.dom.frame.parentNode) { - this.dom.frame.parentNode.removeChild(this.dom.frame); - } + ItemPoint.prototype.repositionX = function() { + var start = this.conversion.toScreen(this.data.start); - // remove the axis with dots - if (this.dom.axis.parentNode) { - this.dom.axis.parentNode.removeChild(this.dom.axis); - } + this.left = start - this.props.dot.width; - // remove the labelset containing all group labels - if (this.dom.labelSet.parentNode) { - this.dom.labelSet.parentNode.removeChild(this.dom.labelSet); - } + // reposition point + this.dom.point.style.left = this.left + 'px'; }; /** - * Show the component in the DOM (when not already visible). - * @return {Boolean} changed + * Reposition the item vertically + * @Override */ - ItemSet.prototype.show = function() { - // show frame containing the items - if (!this.dom.frame.parentNode) { - this.body.dom.center.appendChild(this.dom.frame); - } + ItemPoint.prototype.repositionY = function() { + var orientation = this.options.orientation, + point = this.dom.point; - // show axis with dots - if (!this.dom.axis.parentNode) { - this.body.dom.backgroundVertical.appendChild(this.dom.axis); + if (orientation == 'top') { + point.style.top = this.top + 'px'; } - - // show labelset containing labels - if (!this.dom.labelSet.parentNode) { - this.body.dom.left.appendChild(this.dom.labelSet); + else { + point.style.top = (this.parent.height - this.top - this.height) + 'px'; } }; + module.exports = ItemPoint; + + +/***/ }, +/* 31 */ +/***/ function(module, exports, __webpack_require__) { + + var Hammer = __webpack_require__(41); + var Item = __webpack_require__(28); + /** - * Set selected items by their id. Replaces the current selection - * Unknown id's are silently ignored. - * @param {Array} [ids] An array with zero or more id's of the items to be - * selected. If ids is an empty array, all items will be - * unselected. + * @constructor ItemRange + * @extends Item + * @param {Object} data Object containing parameters start, end + * content, className. + * @param {{toScreen: function, toTime: function}} conversion + * Conversion functions from time to screen and vice versa + * @param {Object} [options] Configuration options + * // TODO: describe options */ - ItemSet.prototype.setSelection = function(ids) { - var i, ii, id, item; - - if (ids) { - if (!Array.isArray(ids)) { - throw new TypeError('Array expected'); + function ItemRange (data, conversion, options) { + this.props = { + content: { + width: 0 } + }; + this.overflow = false; // if contents can overflow (css styling), this flag is set to true - // unselect currently selected items - for (i = 0, ii = this.selection.length; i < ii; i++) { - id = this.selection[i]; - item = this.items[id]; - if (item) item.unselect(); + // validate data + if (data) { + if (data.start == undefined) { + throw new Error('Property "start" missing in item ' + data.id); } - - // select items - this.selection = []; - for (i = 0, ii = ids.length; i < ii; i++) { - id = ids[i]; - item = this.items[id]; - if (item) { - this.selection.push(id); - item.select(); - } + if (data.end == undefined) { + throw new Error('Property "end" missing in item ' + data.id); } } - }; + + Item.call(this, data, conversion, options); + } + + ItemRange.prototype = new Item (null, null, null); + + ItemRange.prototype.baseClassName = 'item range'; /** - * Get the selected items by their id - * @return {Array} ids The ids of the selected items + * Check whether this item is visible inside given range + * @returns {{start: Number, end: Number}} range with a timestamp for start and end + * @returns {boolean} True if visible */ - ItemSet.prototype.getSelection = function() { - return this.selection.concat([]); + ItemRange.prototype.isVisible = function(range) { + // determine visibility + return (this.data.start < range.end) && (this.data.end > range.start); }; /** - * Get the id's of the currently visible items. - * @returns {Array} The ids of the visible items + * Repaint the item */ - ItemSet.prototype.getVisibleItems = function() { - var range = this.body.range.getRange(); - var left = this.body.util.toScreen(range.start); - var right = this.body.util.toScreen(range.end); + ItemRange.prototype.redraw = function() { + var dom = this.dom; + if (!dom) { + // create DOM + this.dom = {}; + dom = this.dom; - var ids = []; - for (var groupId in this.groups) { - if (this.groups.hasOwnProperty(groupId)) { - var group = this.groups[groupId]; - var rawVisibleItems = group.visibleItems; + // background box + dom.box = document.createElement('div'); + // className is updated in redraw() - // filter the "raw" set with visibleItems into a set which is really - // visible by pixels - for (var i = 0; i < rawVisibleItems.length; i++) { - var item = rawVisibleItems[i]; - // TODO: also check whether visible vertically - if ((item.left < right) && (item.left + item.width > left)) { - ids.push(item.id); - } - } + // contents box + dom.content = document.createElement('div'); + dom.content.className = 'content'; + dom.box.appendChild(dom.content); + + // attach this item as attribute + dom.box['timeline-item'] = this; + } + + // append DOM to parent DOM + if (!this.parent) { + throw new Error('Cannot redraw item: no parent attached'); + } + if (!dom.box.parentNode) { + var foreground = this.parent.dom.foreground; + if (!foreground) { + throw new Error('Cannot redraw time axis: parent has no foreground container element'); } + foreground.appendChild(dom.box); } + this.displayed = true; - return ids; + // update contents + if (this.data.content != this.content) { + this.content = this.data.content; + if (this.content instanceof Element) { + dom.content.innerHTML = ''; + dom.content.appendChild(this.content); + } + else if (this.data.content != undefined) { + dom.content.innerHTML = this.content; + } + else { + throw new Error('Property "content" missing in item ' + this.data.id); + } + + this.dirty = true; + } + + // update title + if (this.data.title != this.title) { + dom.box.title = this.data.title; + this.title = this.data.title; + } + + // update class + var className = (this.data.className ? (' ' + this.data.className) : '') + + (this.selected ? ' selected' : ''); + if (this.className != className) { + this.className = className; + dom.box.className = this.baseClassName + className; + + this.dirty = true; + } + + // recalculate size + if (this.dirty) { + // determine from css whether this box has overflow + this.overflow = window.getComputedStyle(dom.content).overflow !== 'hidden'; + + this.props.content.width = this.dom.content.offsetWidth; + this.height = this.dom.box.offsetHeight; + + this.dirty = false; + } + + this._repaintDeleteButton(dom.box); + this._repaintDragLeft(); + this._repaintDragRight(); }; /** - * Deselect a selected item - * @param {String | Number} id - * @private + * Show the item in the DOM (when not already visible). The items DOM will + * be created when needed. */ - ItemSet.prototype._deselect = function(id) { - var selection = this.selection; - for (var i = 0, ii = selection.length; i < ii; i++) { - if (selection[i] == id) { // non-strict comparison! - selection.splice(i, 1); - break; - } + ItemRange.prototype.show = function() { + if (!this.displayed) { + this.redraw(); } }; /** - * Repaint the component - * @return {boolean} Returns true if the component is resized + * Hide the item from the DOM (when visible) + * @return {Boolean} changed */ - ItemSet.prototype.redraw = function() { - var margin = this.options.margin, - range = this.body.range, - asSize = util.option.asSize, - options = this.options, - orientation = options.orientation, - resized = false, - frame = this.dom.frame, - editable = options.editable.updateTime || options.editable.updateGroup; + ItemRange.prototype.hide = function() { + if (this.displayed) { + var box = this.dom.box; - // update class name - frame.className = 'itemset' + (editable ? ' editable' : ''); + if (box.parentNode) { + box.parentNode.removeChild(box); + } - // reorder the groups (if needed) - resized = this._orderGroups() || resized; + this.top = null; + this.left = null; - // check whether zoomed (in that case we need to re-stack everything) - // TODO: would be nicer to get this as a trigger from Range - var visibleInterval = range.end - range.start; - var zoomed = (visibleInterval != this.lastVisibleInterval) || (this.props.width != this.props.lastWidth); - if (zoomed) this.stackDirty = true; - this.lastVisibleInterval = visibleInterval; - this.props.lastWidth = this.props.width; + this.displayed = false; + } + }; - // redraw all groups - var restack = this.stackDirty, - firstGroup = this._firstGroup(), - firstMargin = { - item: margin.item, - axis: margin.axis - }, - nonFirstMargin = { - item: margin.item, - axis: margin.item.vertical / 2 - }, - height = 0, - minHeight = margin.axis + margin.item.vertical; - util.forEach(this.groups, function (group) { - var groupMargin = (group == firstGroup) ? firstMargin : nonFirstMargin; - var groupResized = group.redraw(range, groupMargin, restack); - resized = groupResized || resized; - height += group.height; - }); - height = Math.max(height, minHeight); - this.stackDirty = false; + /** + * Reposition the item horizontally + * @Override + */ + ItemRange.prototype.repositionX = function() { + var props = this.props, + parentWidth = this.parent.width, + start = this.conversion.toScreen(this.data.start), + end = this.conversion.toScreen(this.data.end), + padding = this.options.padding, + contentLeft; - // update frame height - frame.style.height = asSize(height); + // limit the width of the this, as browsers cannot draw very wide divs + if (start < -parentWidth) { + start = -parentWidth; + } + if (end > 2 * parentWidth) { + end = 2 * parentWidth; + } + var boxWidth = Math.max(end - start, 1); - // calculate actual size and position - this.props.top = frame.offsetTop; - this.props.left = frame.offsetLeft; - this.props.width = frame.offsetWidth; - this.props.height = height; + if (this.overflow) { + // when range exceeds left of the window, position the contents at the left of the visible area + contentLeft = Math.max(-start, 0); - // reposition axis - this.dom.axis.style.top = asSize((orientation == 'top') ? - (this.body.domProps.top.height + this.body.domProps.border.top) : - (this.body.domProps.top.height + this.body.domProps.centerContainer.height)); - this.dom.axis.style.left = this.body.domProps.border.left + 'px'; + this.left = start; + this.width = boxWidth + this.props.content.width; + // Note: The calculation of width is an optimistic calculation, giving + // a width which will not change when moving the Timeline + // So no restacking needed, which is nicer for the eye; + } + else { // no overflow + // when range exceeds left of the window, position the contents at the left of the visible area + if (start < 0) { + contentLeft = Math.min(-start, + (end - start - props.content.width - 2 * padding)); + // TODO: remove the need for options.padding. it's terrible. + } + else { + contentLeft = 0; + } - // check if this component is resized - resized = this._isResized() || resized; + this.left = start; + this.width = boxWidth; + } - return resized; + this.dom.box.style.left = this.left + 'px'; + this.dom.box.style.width = boxWidth + 'px'; + this.dom.content.style.left = contentLeft + 'px'; }; /** - * Get the first group, aligned with the axis - * @return {Group | null} firstGroup - * @private + * Reposition the item vertically + * @Override */ - ItemSet.prototype._firstGroup = function() { - var firstGroupIndex = (this.options.orientation == 'top') ? 0 : (this.groupIds.length - 1); - var firstGroupId = this.groupIds[firstGroupIndex]; - var firstGroup = this.groups[firstGroupId] || this.groups[UNGROUPED]; + ItemRange.prototype.repositionY = function() { + var orientation = this.options.orientation, + box = this.dom.box; - return firstGroup || null; + if (orientation == 'top') { + box.style.top = this.top + 'px'; + } + else { + box.style.top = (this.parent.height - this.top - this.height) + 'px'; + } }; /** - * Create or delete the group holding all ungrouped items. This group is used when - * there are no groups specified. + * Repaint a drag area on the left side of the range when the range is selected * @protected */ - ItemSet.prototype._updateUngrouped = function() { - var ungrouped = this.groups[UNGROUPED]; - - if (this.groupsData) { - // remove the group holding all ungrouped items - if (ungrouped) { - ungrouped.hide(); - delete this.groups[UNGROUPED]; - } - } - else { - // create a group holding all (unfiltered) items - if (!ungrouped) { - var id = null; - var data = null; - ungrouped = new Group(id, data, this); - this.groups[UNGROUPED] = ungrouped; + ItemRange.prototype._repaintDragLeft = function () { + if (this.selected && this.options.editable.updateTime && !this.dom.dragLeft) { + // create and show drag area + var dragLeft = document.createElement('div'); + dragLeft.className = 'drag-left'; + dragLeft.dragLeftItem = this; - for (var itemId in this.items) { - if (this.items.hasOwnProperty(itemId)) { - ungrouped.add(this.items[itemId]); - } - } + // TODO: this should be redundant? + Hammer(dragLeft, { + preventDefault: true + }).on('drag', function () { + //console.log('drag left') + }); - ungrouped.show(); + this.dom.box.appendChild(dragLeft); + this.dom.dragLeft = dragLeft; + } + else if (!this.selected && this.dom.dragLeft) { + // delete drag area + if (this.dom.dragLeft.parentNode) { + this.dom.dragLeft.parentNode.removeChild(this.dom.dragLeft); } + this.dom.dragLeft = null; } }; /** - * Get the element for the labelset - * @return {HTMLElement} labelSet + * Repaint a drag area on the right side of the range when the range is selected + * @protected */ - ItemSet.prototype.getLabelSet = function() { - return this.dom.labelSet; - }; + ItemRange.prototype._repaintDragRight = function () { + if (this.selected && this.options.editable.updateTime && !this.dom.dragRight) { + // create and show drag area + var dragRight = document.createElement('div'); + dragRight.className = 'drag-right'; + dragRight.dragRightItem = this; - /** - * Set items - * @param {vis.DataSet | null} items - */ - ItemSet.prototype.setItems = function(items) { - var me = this, - ids, - oldItemsData = this.itemsData; + // TODO: this should be redundant? + Hammer(dragRight, { + preventDefault: true + }).on('drag', function () { + //console.log('drag right') + }); - // replace the dataset - if (!items) { - this.itemsData = null; - } - else if (items instanceof DataSet || items instanceof DataView) { - this.itemsData = items; + this.dom.box.appendChild(dragRight); + this.dom.dragRight = dragRight; } - else { - throw new TypeError('Data must be an instance of DataSet or DataView'); + else if (!this.selected && this.dom.dragRight) { + // delete drag area + if (this.dom.dragRight.parentNode) { + this.dom.dragRight.parentNode.removeChild(this.dom.dragRight); + } + this.dom.dragRight = null; } + }; - if (oldItemsData) { - // unsubscribe from old dataset - util.forEach(this.itemListeners, function (callback, event) { - oldItemsData.off(event, callback); - }); + module.exports = ItemRange; - // remove all drawn items - ids = oldItemsData.getIds(); - this._onRemove(ids); - } - if (this.itemsData) { - // subscribe to new dataset - var id = this.id; - util.forEach(this.itemListeners, function (callback, event) { - me.itemsData.on(event, callback, id); - }); +/***/ }, +/* 32 */ +/***/ function(module, exports, __webpack_require__) { - // add all new items - ids = this.itemsData.getIds(); - this._onAdd(ids); + var Emitter = __webpack_require__(46); + var Hammer = __webpack_require__(41); + var mousetrap = __webpack_require__(49); + var util = __webpack_require__(1); + var hammerUtil = __webpack_require__(43); + var DataSet = __webpack_require__(3); + var DataView = __webpack_require__(4); + var dotparser = __webpack_require__(38); + var gephiParser = __webpack_require__(39); + var Groups = __webpack_require__(34); + var Images = __webpack_require__(35); + var Node = __webpack_require__(36); + var Edge = __webpack_require__(33); + var Popup = __webpack_require__(37); + var MixinLoader = __webpack_require__(45); - // update the group holding all ungrouped items - this._updateUngrouped(); - } - }; + // Load custom shapes into CanvasRenderingContext2D + __webpack_require__(44); /** - * Get the current items - * @returns {vis.DataSet | null} + * @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 */ - ItemSet.prototype.getItems = function() { - return this.itemsData; - }; + function Network (container, data, options) { + if (!(this instanceof Network)) { + throw new SyntaxError('Constructor must be called with the new operator'); + } - /** - * Set groups - * @param {vis.DataSet} groups - */ - ItemSet.prototype.setGroups = function(groups) { - var me = this, - ids; + this._initializeMixinLoaders(); - // unsubscribe from current dataset - if (this.groupsData) { - util.forEach(this.groupListeners, function (callback, event) { - me.groupsData.unsubscribe(event, callback); - }); - - // remove all drawn groups - ids = this.groupsData.getIds(); - this.groupsData = null; - this._onRemoveGroups(ids); // note: this will cause a redraw - } - - // replace the dataset - if (!groups) { - this.groupsData = null; - } - else if (groups instanceof DataSet || groups instanceof DataView) { - this.groupsData = groups; - } - else { - throw new TypeError('Data must be an instance of DataSet or DataView'); - } + // create variables and set default values + this.containerElement = container; - if (this.groupsData) { - // subscribe to new dataset - var id = this.id; - util.forEach(this.groupListeners, function (callback, event) { - me.groupsData.on(event, callback, id); - }); + // render and calculation settings + this.renderRefreshRate = 60; // hz (fps) + this.renderTimestep = 1000 / this.renderRefreshRate; // ms -- saves calculation later on + this.renderTime = 0.5 * this.renderTimestep; // measured time it takes to render a frame + this.maxPhysicsTicksPerRender = 3; // max amount of physics ticks per render step. + this.physicsDiscreteStepsize = 0.50; // discrete stepsize of the simulation - // draw all ms - ids = this.groupsData.getIds(); - this._onAddGroups(ids); - } + this.initializing = true; - // update the group holding all ungrouped items - this._updateUngrouped(); + this.triggerFunctions = {add:null,edit:null,editEdge:null,connect:null,del:null}; - // update the order of all items in each group - this._order(); + // set constant values + this.defaultOptions = { + nodes: { + mass: 1, + radiusMin: 10, + radiusMax: 30, + radius: 10, + shape: 'ellipse', + image: undefined, + widthMin: 16, // px + widthMax: 64, // px + fixed: false, + fontColor: 'black', + fontSize: 14, // px + fontFace: 'verdana', + level: -1, + color: { + border: '#2B7CE9', + background: '#97C2FC', + highlight: { + border: '#2B7CE9', + background: '#D2E5FF' + }, + hover: { + border: '#2B7CE9', + background: '#D2E5FF' + } + }, + borderColor: '#2B7CE9', + backgroundColor: '#97C2FC', + highlightColor: '#D2E5FF', + group: undefined, + borderWidth: 1 + }, + edges: { + widthMin: 1, + widthMax: 15, + width: 1, + widthSelectionMultiplier: 2, + hoverWidth: 1.5, + style: 'line', + color: { + color:'#848484', + highlight:'#848484', + hover: '#848484' + }, + fontColor: '#343434', + fontSize: 14, // px + fontFace: 'arial', + fontFill: 'white', + arrowScaleFactor: 1, + dash: { + length: 10, + gap: 5, + altLength: undefined + }, + inheritColor: "from" // to, from, false, true (== from) + }, + configurePhysics:false, + physics: { + barnesHut: { + enabled: true, + theta: 1 / 0.6, // inverted to save time during calculation + gravitationalConstant: -2000, + centralGravity: 0.3, + springLength: 95, + springConstant: 0.04, + damping: 0.09 + }, + repulsion: { + centralGravity: 0.0, + springLength: 200, + springConstant: 0.05, + nodeDistance: 100, + damping: 0.09 + }, + hierarchicalRepulsion: { + enabled: false, + centralGravity: 0.0, + springLength: 100, + springConstant: 0.01, + nodeDistance: 150, + damping: 0.09 + }, + damping: null, + centralGravity: null, + springLength: null, + springConstant: null + }, + clustering: { // Per Node in Cluster = PNiC + enabled: false, // (Boolean) | global on/off switch for clustering. + initialMaxNodes: 100, // (# nodes) | if the initial amount of nodes is larger than this, we cluster until the total number is less than this threshold. + clusterThreshold:500, // (# nodes) | during calculate forces, we check if the total number of nodes is larger than this. If it is, cluster until reduced to reduceToNodes + reduceToNodes:300, // (# nodes) | during calculate forces, we check if the total number of nodes is larger than clusterThreshold. If it is, cluster until reduced to this + chainThreshold: 0.4, // (% of all drawn nodes)| maximum percentage of allowed chainnodes (long strings of connected nodes) within all nodes. (lower means less chains). + clusterEdgeThreshold: 20, // (px) | edge length threshold. if smaller, this node is clustered. + sectorThreshold: 100, // (# nodes in cluster) | cluster size threshold. If larger, expanding in own sector. + screenSizeThreshold: 0.2, // (% of canvas) | relative size threshold. If the width or height of a clusternode takes up this much of the screen, decluster node. + fontSizeMultiplier: 4.0, // (px PNiC) | how much the cluster font size grows per node in cluster (in px). + maxFontSize: 1000, + forceAmplification: 0.1, // (multiplier PNiC) | factor of increase fo the repulsion force of a cluster (per node in cluster). + distanceAmplification: 0.1, // (multiplier PNiC) | factor how much the repulsion distance of a cluster increases (per node in cluster). + edgeGrowth: 20, // (px PNiC) | amount of clusterSize connected to the edge is multiplied with this and added to edgeLength. + nodeScaling: {width: 1, // (px PNiC) | growth of the width per node in cluster. + height: 1, // (px PNiC) | growth of the height per node in cluster. + radius: 1}, // (px PNiC) | growth of the radius per node in cluster. + maxNodeSizeIncrements: 600, // (# increments) | max growth of the width per node in cluster. + activeAreaBoxSize: 80, // (px) | box area around the curser where clusters are popped open. + clusterLevelDifference: 2 + }, + navigation: { + enabled: false + }, + keyboard: { + enabled: false, + speed: {x: 10, y: 10, zoom: 0.02} + }, + dataManipulation: { + enabled: false, + initiallyVisible: false + }, + hierarchicalLayout: { + enabled:false, + levelSeparation: 150, + nodeSpacing: 100, + direction: "UD" // UD, DU, LR, RL + }, + freezeForStabilization: false, + smoothCurves: { + enabled: true, + dynamic: true, + type: "continuous", + roundness: 0.5 + }, + dynamicSmoothCurves: true, + maxVelocity: 30, + minVelocity: 0.1, // px/s + stabilize: true, // stabilize before displaying the network + stabilizationIterations: 1000, // maximum number of iteration to stabilize + labels:{ + add:"Add Node", + edit:"Edit", + link:"Add Link", + del:"Delete selected", + editNode:"Edit Node", + editEdge:"Edit Edge", + back:"Back", + addDescription:"Click in an empty space to place a new node.", + linkDescription:"Click on a node and drag the edge to another node to connect them.", + editEdgeDescription:"Click on the control points and drag them to a node to connect to it.", + addError:"The function for add does not support two arguments (data,callback).", + linkError:"The function for connect does not support two arguments (data,callback).", + editError:"The function for edit does not support two arguments (data, callback).", + editBoundError:"No edit function has been bound to this button.", + deleteError:"The function for delete does not support two arguments (data, callback).", + deleteClusterError:"Clusters cannot be deleted." + }, + tooltip: { + delay: 300, + fontColor: 'black', + fontSize: 14, // px + fontFace: 'verdana', + color: { + border: '#666', + background: '#FFFFC6' + } + }, + dragNetwork: true, + dragNodes: true, + zoomable: true, + hover: false, + hideEdgesOnDrag: false, + hideNodesOnDrag: false, + width : '100%', + height : '100%', + selectable: true + }; + this.constants = util.extend({}, this.defaultOptions); - this.body.emitter.emit('change'); - }; + this.hoverObj = {nodes:{},edges:{}}; + this.controlNodesActive = false; - /** - * Get the current groups - * @returns {vis.DataSet | null} groups - */ - ItemSet.prototype.getGroups = function() { - return this.groupsData; - }; + // Node variables + var network = this; + this.groups = new Groups(); // object with groups + this.images = new Images(); // object with images + this.images.setOnloadCallback(function () { + network._redraw(); + }); - /** - * Remove an item by its id - * @param {String | Number} id - */ - ItemSet.prototype.removeItem = function(id) { - var item = this.itemsData.get(id), - dataset = this.itemsData.getDataSet(); + // keyboard navigation variables + this.xIncrement = 0; + this.yIncrement = 0; + this.zoomIncrement = 0; - if (item) { - // confirm deletion - this.options.onRemove(item, function (item) { - if (item) { - // remove by id here, it is possible that an item has no id defined - // itself, so better not delete by the item itself - dataset.remove(id); - } - }); - } - }; + // loading all the mixins: + // load the force calculation functions, grouped under the physics system. + this._loadPhysicsSystem(); + // create a frame and canvas + this._create(); + // load the sector system. (mandatory, fully integrated with Network) + this._loadSectorSystem(); + // load the cluster system. (mandatory, even when not using the cluster system, there are function calls to it) + this._loadClusterSystem(); + // load the selection system. (mandatory, required by Network) + this._loadSelectionSystem(); + // load the selection system. (mandatory, required by Network) + this._loadHierarchySystem(); - /** - * Handle updated items - * @param {Number[]} ids - * @protected - */ - ItemSet.prototype._onUpdate = function(ids) { - var me = this; + // apply options + this._setTranslation(this.frame.clientWidth / 2, this.frame.clientHeight / 2); + this._setScale(1); + this.setOptions(options); - ids.forEach(function (id) { - var itemData = me.itemsData.get(id, me.itemOptions), - item = me.items[id], - type = itemData.type || me.options.type || (itemData.end ? 'range' : 'box'); + // other vars + this.freezeSimulation = false;// freeze the simulation + this.cachedFunctions = {}; - var constructor = ItemSet.types[type]; + // containers for nodes and edges + this.calculationNodes = {}; + this.calculationNodeIndices = []; + this.nodeIndices = []; // array with all the indices of the nodes. Used to speed up forces calculation + this.nodes = {}; // object with Node objects + this.edges = {}; // object with Edge objects - if (item) { - // update item - if (!constructor || !(item instanceof constructor)) { - // item type has changed, delete the item and recreate it - me._removeItem(item); - item = null; - } - else { - me._updateItem(item, itemData); - } + // position and scale variables and objects + this.canvasTopLeft = {"x": 0,"y": 0}; // coordinates of the top left of the canvas. they will be set during _redraw. + this.canvasBottomRight = {"x": 0,"y": 0}; // coordinates of the bottom right of the canvas. they will be set during _redraw + this.pointerPosition = {"x": 0,"y": 0}; // coordinates of the bottom right of the canvas. they will be set during _redraw + this.areaCenter = {}; // object with x and y elements used for determining the center of the zoom action + this.scale = 1; // defining the global scale variable in the constructor + this.previousScale = this.scale; // this is used to check if the zoom operation is zooming in or out + + // datasets or dataviews + this.nodesData = null; // A DataSet or DataView + this.edgesData = null; // A DataSet or DataView + + // create event listeners used to subscribe on the DataSets of the nodes and edges + this.nodesListeners = { + 'add': function (event, params) { + network._addNodes(params.items); + network.start(); + }, + 'update': function (event, params) { + network._updateNodes(params.items); + network.start(); + }, + 'remove': function (event, params) { + network._removeNodes(params.items); + network.start(); + } + }; + this.edgesListeners = { + 'add': function (event, params) { + network._addEdges(params.items); + network.start(); + }, + 'update': function (event, params) { + network._updateEdges(params.items); + network.start(); + }, + 'remove': function (event, params) { + network._removeEdges(params.items); + network.start(); } + }; - if (!item) { - // create item - if (constructor) { - item = new constructor(itemData, me.conversion, me.options); - item.id = id; // TODO: not so nice setting id afterwards - me._addItem(item); - } - else if (type == 'rangeoverflow') { - // TODO: deprecated since version 2.1.0 (or 3.0.0?). cleanup some day - throw new TypeError('Item type "rangeoverflow" is deprecated. Use css styling instead: ' + - '.vis.timeline .item.range .content {overflow: visible;}'); - } - else { - throw new TypeError('Unknown item type "' + type + '"'); - } + // properties for the animation + this.moving = true; + this.timer = undefined; // Scheduling function. Is definded in this.start(); + + // load data (the disable start variable will be the same as the enabled clustering) + this.setData(data,this.constants.clustering.enabled || this.constants.hierarchicalLayout.enabled); + + // hierarchical layout + this.initializing = false; + if (this.constants.hierarchicalLayout.enabled == true) { + this._setupHierarchicalLayout(); + } + else { + // zoom so all data will fit on the screen, if clustering is enabled, we do not want start to be called here. + if (this.constants.stabilize == false) { + this.zoomExtent(true,this.constants.clustering.enabled); } - }); + } - this._order(); - this.stackDirty = true; // force re-stacking of all items next redraw - this.body.emitter.emit('change'); - }; + // if clustering is disabled, the simulation will have started in the setData function + if (this.constants.clustering.enabled) { + this.startWithClustering(); + } + } - /** - * Handle added items - * @param {Number[]} ids - * @protected - */ - ItemSet.prototype._onAdd = ItemSet.prototype._onUpdate; + // Extend Network with an Emitter mixin + Emitter(Network.prototype); /** - * Handle removed items - * @param {Number[]} ids - * @protected + * Get the script path where the vis.js library is located + * + * @returns {string | null} path Path or null when not found. Path does not + * end with a slash. + * @private */ - ItemSet.prototype._onRemove = function(ids) { - var count = 0; - var me = this; - ids.forEach(function (id) { - var item = me.items[id]; - if (item) { - count++; - me._removeItem(item); - } - }); + Network.prototype._getScriptPath = function() { + var scripts = document.getElementsByTagName( 'script' ); - if (count) { - // update order - this._order(); - this.stackDirty = true; // force re-stacking of all items next redraw - this.body.emitter.emit('change'); + // find script named vis.js or vis.min.js + for (var i = 0; i < scripts.length; i++) { + var src = scripts[i].src; + var match = src && /\/?vis(.min)?\.js$/.exec(src); + if (match) { + // return path without the script name + return src.substring(0, src.length - match[0].length); + } } + + return null; }; + /** - * Update the order of item in all groups + * Find the center position of the network * @private */ - ItemSet.prototype._order = function() { - // reorder the items in all groups - // TODO: optimization: only reorder groups affected by the changed items - util.forEach(this.groups, function (group) { - group.order(); - }); + Network.prototype._getRange = function() { + var minY = 1e9, maxY = -1e9, minX = 1e9, maxX = -1e9, node; + for (var nodeId in this.nodes) { + if (this.nodes.hasOwnProperty(nodeId)) { + node = this.nodes[nodeId]; + if (minX > (node.x)) {minX = node.x;} + if (maxX < (node.x)) {maxX = node.x;} + if (minY > (node.y)) {minY = node.y;} + if (maxY < (node.y)) {maxY = node.y;} + } + } + if (minX == 1e9 && maxX == -1e9 && minY == 1e9 && maxY == -1e9) { + minY = 0, maxY = 0, minX = 0, maxX = 0; + } + return {minX: minX, maxX: maxX, minY: minY, maxY: maxY}; }; + /** - * Handle updated groups - * @param {Number[]} ids + * @param {object} range = {minX: minX, maxX: maxX, minY: minY, maxY: maxY}; + * @returns {{x: number, y: number}} * @private */ - ItemSet.prototype._onUpdateGroups = function(ids) { - this._onAddGroups(ids); + Network.prototype._findCenter = function(range) { + return {x: (0.5 * (range.maxX + range.minX)), + y: (0.5 * (range.maxY + range.minY))}; }; + /** - * Handle changed groups - * @param {Number[]} ids - * @private + * center the network + * + * @param {object} range = {minX: minX, maxX: maxX, minY: minY, maxY: maxY}; */ - ItemSet.prototype._onAddGroups = function(ids) { - var me = this; - - ids.forEach(function (id) { - var groupData = me.groupsData.get(id); - var group = me.groups[id]; + Network.prototype._centerNetwork = function(range) { + var center = this._findCenter(range); - if (!group) { - // check for reserved ids - if (id == UNGROUPED) { - throw new Error('Illegal group id. ' + id + ' is a reserved id.'); - } + center.x *= this.scale; + center.y *= this.scale; + center.x -= 0.5 * this.frame.canvas.clientWidth; + center.y -= 0.5 * this.frame.canvas.clientHeight; - var groupOptions = Object.create(me.options); - util.extend(groupOptions, { - height: null - }); + this._setTranslation(-center.x,-center.y); // set at 0,0 + }; - group = new Group(id, groupData, me); - me.groups[id] = group; - // add items with this groupId to the new group - for (var itemId in me.items) { - if (me.items.hasOwnProperty(itemId)) { - var item = me.items[itemId]; - if (item.data.group == id) { - group.add(item); - } - } - } + /** + * This function zooms out to fit all data on screen based on amount of nodes + * + * @param {Boolean} [initialZoom] | zoom based on fitted formula or range, true = fitted, default = false; + * @param {Boolean} [disableStart] | If true, start is not called. + */ + Network.prototype.zoomExtent = function(initialZoom, disableStart) { + if (initialZoom === undefined) { + initialZoom = false; + } + if (disableStart === undefined) { + disableStart = false; + } - group.order(); - group.show(); + var range = this._getRange(); + var zoomLevel; + + if (initialZoom == true) { + var numberOfNodes = this.nodeIndices.length; + if (this.constants.smoothCurves == true) { + if (this.constants.clustering.enabled == true && + numberOfNodes >= this.constants.clustering.initialMaxNodes) { + zoomLevel = 49.07548 / (numberOfNodes + 142.05338) + 9.1444e-04; // this is obtained from fitting a dataset from 5 points with scale levels that looked good. + } + else { + zoomLevel = 12.662 / (numberOfNodes + 7.4147) + 0.0964822; // this is obtained from fitting a dataset from 5 points with scale levels that looked good. + } } else { - // update group - group.setData(groupData); + if (this.constants.clustering.enabled == true && + numberOfNodes >= this.constants.clustering.initialMaxNodes) { + zoomLevel = 77.5271985 / (numberOfNodes + 187.266146) + 4.76710517e-05; // this is obtained from fitting a dataset from 5 points with scale levels that looked good. + } + else { + zoomLevel = 30.5062972 / (numberOfNodes + 19.93597763) + 0.08413486; // this is obtained from fitting a dataset from 5 points with scale levels that looked good. + } } - }); - this.body.emitter.emit('change'); - }; + // correct for larger canvasses. + var factor = Math.min(this.frame.canvas.clientWidth / 600, this.frame.canvas.clientHeight / 600); + zoomLevel *= factor; + } + else { + var xDistance = (Math.abs(range.minX) + Math.abs(range.maxX)) * 1.1; + var yDistance = (Math.abs(range.minY) + Math.abs(range.maxY)) * 1.1; - /** - * Handle removed groups - * @param {Number[]} ids - * @private - */ - ItemSet.prototype._onRemoveGroups = function(ids) { - var groups = this.groups; - ids.forEach(function (id) { - var group = groups[id]; + var xZoomLevel = this.frame.canvas.clientWidth / xDistance; + var yZoomLevel = this.frame.canvas.clientHeight / yDistance; - if (group) { - group.hide(); - delete groups[id]; - } - }); + zoomLevel = (xZoomLevel <= yZoomLevel) ? xZoomLevel : yZoomLevel; + } - this.markDirty(); + if (zoomLevel > 1.0) { + zoomLevel = 1.0; + } - this.body.emitter.emit('change'); + + this._setScale(zoomLevel); + this._centerNetwork(range); + if (disableStart == false) { + this.moving = true; + this.start(); + } }; + /** - * Reorder the groups if needed - * @return {boolean} changed + * Update the this.nodeIndices with the most recent node index list * @private */ - ItemSet.prototype._orderGroups = function () { - if (this.groupsData) { - // reorder the groups - var groupIds = this.groupsData.getIds({ - order: this.options.groupOrder - }); - - var changed = !util.equalArray(groupIds, this.groupIds); - if (changed) { - // hide all groups, removes them from the DOM - var groups = this.groups; - groupIds.forEach(function (groupId) { - groups[groupId].hide(); - }); - - // show the groups again, attach them to the DOM in correct order - groupIds.forEach(function (groupId) { - groups[groupId].show(); - }); - - this.groupIds = groupIds; + Network.prototype._updateNodeIndexList = function() { + this._clearNodeIndexList(); + for (var idx in this.nodes) { + if (this.nodes.hasOwnProperty(idx)) { + this.nodeIndices.push(idx); } - - return changed; - } - else { - return false; } }; - /** - * Add a new item - * @param {Item} item - * @private - */ - ItemSet.prototype._addItem = function(item) { - this.items[item.id] = item; - - // add to group - var groupId = this.groupsData ? item.data.group : UNGROUPED; - var group = this.groups[groupId]; - if (group) group.add(item); - }; /** - * Update an existing item - * @param {Item} item - * @param {Object} itemData - * @private + * 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 + * @param {Boolean} [disableStart] | optional: disable the calling of the start function. */ - ItemSet.prototype._updateItem = function(item, itemData) { - var oldGroupId = item.data.group; + Network.prototype.setData = function(data, disableStart) { + if (disableStart === undefined) { + disableStart = false; + } - item.data = itemData; - if (item.displayed) { - item.redraw(); + 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.'); } - // update group - if (oldGroupId != item.data.group) { - var oldGroup = this.groups[oldGroupId]; - if (oldGroup) oldGroup.remove(item); + // set options + this.setOptions(data && data.options); - var groupId = this.groupsData ? item.data.group : UNGROUPED; - var group = this.groups[groupId]; - if (group) group.add(item); + // set all data + if (data && data.dot) { + // parse DOT file + if(data && data.dot) { + var dotData = dotparser.DOTToGraph(data.dot); + this.setData(dotData); + return; + } + } + else if (data && data.gephi) { + // parse DOT file + if(data && data.gephi) { + var gephiData = gephiParser.parseGephi(data.gephi); + this.setData(gephiData); + return; + } + } + else { + this._setNodes(data && data.nodes); + this._setEdges(data && data.edges); + } + + this._putDataInSector(); + if (!disableStart) { + // find a stable position or start animating to a stable position + if (this.constants.stabilize) { + var me = this; + setTimeout(function() {me._stabilize(); me.start();},0) + } + else { + this.start(); + } } }; /** - * Delete an item from the ItemSet: remove it from the DOM, from the map - * with items, and from the map with visible items, and from the selection - * @param {Item} item - * @private + * Set options + * @param {Object} options + * @param {Boolean} [initializeView] | set zoom and translation to default. */ - ItemSet.prototype._removeItem = function(item) { - // remove from DOM - item.hide(); - - // remove from items - delete this.items[item.id]; - - // remove from selection - var index = this.selection.indexOf(item.id); - if (index != -1) this.selection.splice(index, 1); + Network.prototype.setOptions = function (options) { + if (options) { + var prop; - // remove from group - var groupId = this.groupsData ? item.data.group : UNGROUPED; - var group = this.groups[groupId]; - if (group) group.remove(item); - }; + var fields = ['nodes','edges','smoothCurves','hierarchicalLayout','clustering','navigation','keyboard','dataManipulation', + 'onAdd','onEdit','onEditEdge','onConnect','onDelete' + ]; + util.selectiveNotDeepExtend(fields,this.constants, options); + util.selectiveNotDeepExtend(['color'],this.constants.nodes, options.nodes); + util.selectiveNotDeepExtend(['color','length'],this.constants.edges, options.edges); - /** - * Create an array containing all items being a range (having an end date) - * @param array - * @returns {Array} - * @private - */ - ItemSet.prototype._constructByEndArray = function(array) { - var endArray = []; + if (options.physics) { + util.mergeOptions(this.constants.physics, options.physics,'barnesHut'); + util.mergeOptions(this.constants.physics, options.physics,'repulsion'); - for (var i = 0; i < array.length; i++) { - if (array[i] instanceof ItemRange) { - endArray.push(array[i]); + if (options.physics.hierarchicalRepulsion) { + this.constants.hierarchicalLayout.enabled = true; + this.constants.physics.hierarchicalRepulsion.enabled = true; + this.constants.physics.barnesHut.enabled = false; + for (prop in options.physics.hierarchicalRepulsion) { + if (options.physics.hierarchicalRepulsion.hasOwnProperty(prop)) { + this.constants.physics.hierarchicalRepulsion[prop] = options.physics.hierarchicalRepulsion[prop]; + } + } + } } - } - return endArray; - }; - /** - * Register the clicked item on touch, before dragStart is initiated. - * - * dragStart is initiated from a mousemove event, which can have left the item - * already resulting in an item == null - * - * @param {Event} event - * @private - */ - ItemSet.prototype._onTouch = function (event) { - // store the touched item, used in _onDragStart - this.touchParams.item = ItemSet.itemFromTarget(event); - }; + if (options.onAdd) {this.triggerFunctions.add = options.onAdd;} + if (options.onEdit) {this.triggerFunctions.edit = options.onEdit;} + if (options.onEditEdge) {this.triggerFunctions.editEdge = options.onEditEdge;} + if (options.onConnect) {this.triggerFunctions.connect = options.onConnect;} + if (options.onDelete) {this.triggerFunctions.del = options.onDelete;} - /** - * Start dragging the selected events - * @param {Event} event - * @private - */ - ItemSet.prototype._onDragStart = function (event) { - if (!this.options.editable.updateTime && !this.options.editable.updateGroup) { - return; - } + util.mergeOptions(this.constants, options,'smoothCurves'); + util.mergeOptions(this.constants, options,'hierarchicalLayout'); + util.mergeOptions(this.constants, options,'clustering'); + util.mergeOptions(this.constants, options,'navigation'); + util.mergeOptions(this.constants, options,'keyboard'); + util.mergeOptions(this.constants, options,'dataManipulation'); - var item = this.touchParams.item || null, - me = this, - props; - if (item && item.selected) { - var dragLeftItem = event.target.dragLeftItem; - var dragRightItem = event.target.dragRightItem; + if (options.dataManipulation) { + this.editMode = this.constants.dataManipulation.initiallyVisible; + } - if (dragLeftItem) { - props = { - item: dragLeftItem - }; - if (me.options.editable.updateTime) { - props.start = item.data.start.valueOf(); - } - if (me.options.editable.updateGroup) { - if ('group' in item.data) props.group = item.data.group; + // TODO: work out these options and document them + if (options.edges) { + if (options.edges.color !== undefined) { + if (util.isString(options.edges.color)) { + this.constants.edges.color = {}; + this.constants.edges.color.color = options.edges.color; + this.constants.edges.color.highlight = options.edges.color; + this.constants.edges.color.hover = options.edges.color; + } + else { + if (options.edges.color.color !== undefined) {this.constants.edges.color.color = options.edges.color.color;} + if (options.edges.color.highlight !== undefined) {this.constants.edges.color.highlight = options.edges.color.highlight;} + if (options.edges.color.hover !== undefined) {this.constants.edges.color.hover = options.edges.color.hover;} + } } - this.touchParams.itemProps = [props]; + if (!options.edges.fontColor) { + if (options.edges.color !== undefined) { + if (util.isString(options.edges.color)) {this.constants.edges.fontColor = options.edges.color;} + else if (options.edges.color.color !== undefined) {this.constants.edges.fontColor = options.edges.color.color;} + } + } } - else if (dragRightItem) { - props = { - item: dragRightItem - }; - if (me.options.editable.updateTime) { - props.end = item.data.end.valueOf(); + if (options.nodes) { + if (options.nodes.color) { + var newColorObj = util.parseColor(options.nodes.color); + this.constants.nodes.color.background = newColorObj.background; + this.constants.nodes.color.border = newColorObj.border; + this.constants.nodes.color.highlight.background = newColorObj.highlight.background; + this.constants.nodes.color.highlight.border = newColorObj.highlight.border; + this.constants.nodes.color.hover.background = newColorObj.hover.background; + this.constants.nodes.color.hover.border = newColorObj.hover.border; } - if (me.options.editable.updateGroup) { - if ('group' in item.data) props.group = item.data.group; + } + if (options.groups) { + for (var groupname in options.groups) { + if (options.groups.hasOwnProperty(groupname)) { + var group = options.groups[groupname]; + this.groups.add(groupname, group); + } } - - this.touchParams.itemProps = [props]; } - else { - this.touchParams.itemProps = this.getSelection().map(function (id) { - var item = me.items[id]; - var props = { - item: item - }; - if (me.options.editable.updateTime) { - if ('start' in item.data) props.start = item.data.start.valueOf(); - if ('end' in item.data) props.end = item.data.end.valueOf(); - } - if (me.options.editable.updateGroup) { - if ('group' in item.data) props.group = item.data.group; + if (options.tooltip) { + for (prop in options.tooltip) { + if (options.tooltip.hasOwnProperty(prop)) { + this.constants.tooltip[prop] = options.tooltip[prop]; } - - return props; - }); + } + if (options.tooltip.color) { + this.constants.tooltip.color = util.parseColor(options.tooltip.color); + } } - - event.stopPropagation(); } + + // (Re)loading the mixins that can be enabled or disabled in the options. + // load the force calculation functions, grouped under the physics system. + this._loadPhysicsSystem(); + // load the navigation system. + this._loadNavigationControls(); + // load the data manipulation system + this._loadManipulationSystem(); + // configure the smooth curves + this._configureSmoothCurves(); + + + // bind keys. If disabled, this will not do anything; + this._createKeyBinds(); + this.setSize(this.constants.width, this.constants.height); + this.moving = true; + this.start(); + }; /** - * Drag selected items - * @param {Event} event + * Create the main frame for the Network. + * This function is executed once when a Network object is created. The frame + * contains a canvas, and this canvas contains all objects like the axis and + * nodes. * @private */ - ItemSet.prototype._onDrag = function (event) { - if (this.touchParams.itemProps) { - var range = this.body.range, - snap = this.body.util.snap || null, - deltaX = event.gesture.deltaX, - scale = (this.props.width / (range.end - range.start)), - offset = deltaX / scale; - - // move - this.touchParams.itemProps.forEach(function (props) { - if ('start' in props) { - var start = new Date(props.start + offset); - props.item.data.start = snap ? snap(start) : start; - } + Network.prototype._create = function () { + // remove all elements from the container element. + while (this.containerElement.hasChildNodes()) { + this.containerElement.removeChild(this.containerElement.firstChild); + } - if ('end' in props) { - var end = new Date(props.end + offset); - props.item.data.end = snap ? snap(end) : end; - } + this.frame = document.createElement('div'); + this.frame.className = 'network-frame'; + this.frame.style.position = 'relative'; + this.frame.style.overflow = 'hidden'; - if ('group' in props) { - // drag from one group to another - var group = ItemSet.groupFromTarget(event); - _moveToGroup(props.item, group); - } - }); + // create the network canvas (HTML canvas element) + this.frame.canvas = document.createElement( 'canvas' ); + this.frame.canvas.style.position = 'relative'; + this.frame.appendChild(this.frame.canvas); + if (!this.frame.canvas.getContext) { + var noCanvas = document.createElement( 'DIV' ); + noCanvas.style.color = 'red'; + noCanvas.style.fontWeight = 'bold' ; + noCanvas.style.padding = '10px'; + noCanvas.innerHTML = 'Error: your browser does not support HTML canvas'; + this.frame.canvas.appendChild(noCanvas); + } - // TODO: implement onMoving handler + var me = this; + this.drag = {}; + this.pinch = {}; + this.hammer = Hammer(this.frame.canvas, { + prevent_default: true + }); + this.hammer.on('tap', me._onTap.bind(me) ); + this.hammer.on('doubletap', me._onDoubleTap.bind(me) ); + this.hammer.on('hold', me._onHold.bind(me) ); + this.hammer.on('pinch', me._onPinch.bind(me) ); + this.hammer.on('touch', me._onTouch.bind(me) ); + this.hammer.on('dragstart', me._onDragStart.bind(me) ); + this.hammer.on('drag', me._onDrag.bind(me) ); + this.hammer.on('dragend', me._onDragEnd.bind(me) ); + this.hammer.on('release', me._onRelease.bind(me) ); + this.hammer.on('mousewheel',me._onMouseWheel.bind(me) ); + this.hammer.on('DOMMouseScroll',me._onMouseWheel.bind(me) ); // for FF + this.hammer.on('mousemove', me._onMouseMoveTitle.bind(me) ); - this.stackDirty = true; // force re-stacking of all items next redraw - this.body.emitter.emit('change'); + // add the frame to the container element + this.containerElement.appendChild(this.frame); - event.stopPropagation(); - } }; + /** - * Move an item to another group - * @param {Item} item - * @param {Group} group + * Binding the keys for keyboard navigation. These functions are defined in the NavigationMixin * @private */ - function _moveToGroup (item, group) { - if (group && group.groupId != item.data.group) { - var oldGroup = item.parent; - oldGroup.remove(item); - oldGroup.order(); - group.add(item); - group.order(); + Network.prototype._createKeyBinds = function() { + var me = this; + this.mousetrap = mousetrap; - item.data.group = group.groupId; + this.mousetrap.reset(); + + if (this.constants.keyboard.enabled == true) { + this.mousetrap.bind("up", this._moveUp.bind(me) , "keydown"); + this.mousetrap.bind("up", this._yStopMoving.bind(me), "keyup"); + this.mousetrap.bind("down", this._moveDown.bind(me) , "keydown"); + this.mousetrap.bind("down", this._yStopMoving.bind(me), "keyup"); + this.mousetrap.bind("left", this._moveLeft.bind(me) , "keydown"); + this.mousetrap.bind("left", this._xStopMoving.bind(me), "keyup"); + this.mousetrap.bind("right",this._moveRight.bind(me), "keydown"); + this.mousetrap.bind("right",this._xStopMoving.bind(me), "keyup"); + this.mousetrap.bind("=", this._zoomIn.bind(me), "keydown"); + this.mousetrap.bind("=", this._stopZoom.bind(me), "keyup"); + this.mousetrap.bind("-", this._zoomOut.bind(me), "keydown"); + this.mousetrap.bind("-", this._stopZoom.bind(me), "keyup"); + this.mousetrap.bind("[", this._zoomIn.bind(me), "keydown"); + this.mousetrap.bind("[", this._stopZoom.bind(me), "keyup"); + this.mousetrap.bind("]", this._zoomOut.bind(me), "keydown"); + this.mousetrap.bind("]", this._stopZoom.bind(me), "keyup"); + this.mousetrap.bind("pageup",this._zoomIn.bind(me), "keydown"); + this.mousetrap.bind("pageup",this._stopZoom.bind(me), "keyup"); + this.mousetrap.bind("pagedown",this._zoomOut.bind(me),"keydown"); + this.mousetrap.bind("pagedown",this._stopZoom.bind(me), "keyup"); } - } + + if (this.constants.dataManipulation.enabled == true) { + this.mousetrap.bind("escape",this._createManipulatorBar.bind(me)); + this.mousetrap.bind("del",this._deleteSelected.bind(me)); + } + }; /** - * End of dragging selected items - * @param {Event} event + * Get the pointer location from a touch location + * @param {{pageX: Number, pageY: Number}} touch + * @return {{x: Number, y: Number}} pointer * @private */ - ItemSet.prototype._onDragEnd = function (event) { - if (this.touchParams.itemProps) { - // prepare a change set for the changed items - var changes = [], - me = this, - dataset = this.itemsData.getDataSet(); - - var itemProps = this.touchParams.itemProps ; - this.touchParams.itemProps = null; - itemProps.forEach(function (props) { - var id = props.item.id, - itemData = me.itemsData.get(id, me.itemOptions); - - var changed = false; - if ('start' in props.item.data) { - changed = (props.start != props.item.data.start.valueOf()); - itemData.start = util.convert(props.item.data.start, - dataset._options.type && dataset._options.type.start || 'Date'); - } - if ('end' in props.item.data) { - changed = changed || (props.end != props.item.data.end.valueOf()); - itemData.end = util.convert(props.item.data.end, - dataset._options.type && dataset._options.type.end || 'Date'); - } - if ('group' in props.item.data) { - changed = changed || (props.group != props.item.data.group); - itemData.group = props.item.data.group; - } - - // only apply changes when start or end is actually changed - if (changed) { - me.options.onMove(itemData, function (itemData) { - if (itemData) { - // apply changes - itemData[dataset._fieldId] = id; // ensure the item contains its id (can be undefined) - changes.push(itemData); - } - else { - // restore original values - if ('start' in props) props.item.data.start = props.start; - if ('end' in props) props.item.data.end = props.end; - if ('group' in props && props.item.data.group != props.group) { - var group = me.groups[props.group]; - _moveToGroup(props.item, group); - } + Network.prototype._getPointer = function (touch) { + return { + x: touch.pageX - util.getAbsoluteLeft(this.frame.canvas), + y: touch.pageY - util.getAbsoluteTop(this.frame.canvas) + }; + }; - me.stackDirty = true; // force re-stacking of all items next redraw - me.body.emitter.emit('change'); - } - }); - } - }); + /** + * On start of a touch gesture, store the pointer + * @param event + * @private + */ + Network.prototype._onTouch = function (event) { + this.drag.pointer = this._getPointer(event.gesture.center); + this.drag.pinched = false; + this.pinch.scale = this._getScale(); - // apply the changes to the data (if there are changes) - if (changes.length) { - dataset.update(changes); - } + this._handleTouch(this.drag.pointer); + }; - event.stopPropagation(); - } + /** + * handle drag start event + * @private + */ + Network.prototype._onDragStart = function () { + this._handleDragStart(); }; + /** - * Handle selecting/deselecting an item when tapping it - * @param {Event} event + * This function is called by _onDragStart. + * It is separated out because we can then overload it for the datamanipulation system. + * * @private */ - ItemSet.prototype._onSelectItem = function (event) { - if (!this.options.selectable) return; + Network.prototype._handleDragStart = function() { + var drag = this.drag; + var node = this._getNodeAt(drag.pointer); + // note: drag.pointer is set in _onTouch to get the initial touch location - var ctrlKey = event.gesture.srcEvent && event.gesture.srcEvent.ctrlKey; - var shiftKey = event.gesture.srcEvent && event.gesture.srcEvent.shiftKey; - if (ctrlKey || shiftKey) { - this._onMultiSelectItem(event); - return; - } + drag.dragging = true; + drag.selection = []; + drag.translation = this._getTranslation(); + drag.nodeId = null; - var oldSelection = this.getSelection(); + if (node != null) { + drag.nodeId = node.id; + // select the clicked node if not yet selected + if (!node.isSelected()) { + this._selectObject(node,false); + } - var item = ItemSet.itemFromTarget(event); - var selection = item ? [item.id] : []; - this.setSelection(selection); + // create an array with the selected nodes and their original location and status + for (var objectId in this.selectionObj.nodes) { + if (this.selectionObj.nodes.hasOwnProperty(objectId)) { + var object = this.selectionObj.nodes[objectId]; + var s = { + id: object.id, + node: object, - var newSelection = this.getSelection(); + // store original x, y, xFixed and yFixed, make the node temporarily Fixed + x: object.x, + y: object.y, + xFixed: object.xFixed, + yFixed: object.yFixed + }; - // emit a select event, - // except when old selection is empty and new selection is still empty - if (newSelection.length > 0 || oldSelection.length > 0) { - this.body.emitter.emit('select', { - items: this.getSelection() - }); + object.xFixed = true; + object.yFixed = true; + + drag.selection.push(s); + } + } } + }; - event.stopPropagation(); + + /** + * handle drag event + * @private + */ + Network.prototype._onDrag = function (event) { + this._handleOnDrag(event) }; + /** - * Handle creation and updates of an item on double tap - * @param event + * This function is called by _onDrag. + * It is separated out because we can then overload it for the datamanipulation system. + * * @private */ - ItemSet.prototype._onAddItem = function (event) { - if (!this.options.selectable) return; - if (!this.options.editable.add) return; + Network.prototype._handleOnDrag = function(event) { + if (this.drag.pinched) { + return; + } - var me = this, - snap = this.body.util.snap || null, - item = ItemSet.itemFromTarget(event); + var pointer = this._getPointer(event.gesture.center); - if (item) { - // update item + var me = this; + var drag = this.drag; + var selection = drag.selection; + if (selection && selection.length && this.constants.dragNodes == true) { + // calculate delta's and new location + var deltaX = pointer.x - drag.pointer.x; + var deltaY = pointer.y - drag.pointer.y; - // execute async handler to update the item (or cancel it) - var itemData = me.itemsData.get(item.id); // get a clone of the data from the dataset - this.options.onUpdate(itemData, function (itemData) { - if (itemData) { - me.itemsData.update(itemData); + // update position of all selected nodes + selection.forEach(function (s) { + var node = s.node; + + if (!s.xFixed) { + node.x = me._XconvertDOMtoCanvas(me._XconvertCanvasToDOM(s.x) + deltaX); } - }); - } - else { - // add item - var xAbs = util.getAbsoluteLeft(this.dom.frame); - var x = event.gesture.center.pageX - xAbs; - var start = this.body.util.toTime(x); - var newItem = { - start: snap ? snap(start) : start, - content: 'new item' - }; - // when default type is a range, add a default end date to the new item - if (this.options.type === 'range') { - var end = this.body.util.toTime(x + this.props.width / 5); - newItem.end = snap ? snap(end) : end; - } + if (!s.yFixed) { + node.y = me._YconvertDOMtoCanvas(me._YconvertCanvasToDOM(s.y) + deltaY); + } + }); - newItem[this.itemsData.fieldId] = util.randomUUID(); - var group = ItemSet.groupFromTarget(event); - if (group) { - newItem.group = group.groupId; + // start _animationStep if not yet running + if (!this.moving) { + this.moving = true; + this.start(); } + } + else { + if (this.constants.dragNetwork == true) { + // move the network + var diffX = pointer.x - this.drag.pointer.x; + var diffY = pointer.y - this.drag.pointer.y; - // execute async handler to customize (or cancel) adding an item - this.options.onAdd(newItem, function (item) { - if (item) { - me.itemsData.add(newItem); - // TODO: need to trigger a redraw? - } - }); + this._setTranslation( + this.drag.translation.x + diffX, + this.drag.translation.y + diffY + ); + this._redraw(); + // this.moving = true; + // this.start(); + } } }; /** - * Handle selecting/deselecting multiple items when holding an item - * @param {Event} event + * handle drag start event * @private */ - ItemSet.prototype._onMultiSelectItem = function (event) { - if (!this.options.selectable) return; - - var selection, - item = ItemSet.itemFromTarget(event); - - if (item) { - // multi select items - selection = this.getSelection(); // current selection - var index = selection.indexOf(item.id); - if (index == -1) { - // item is not yet selected -> select it - selection.push(item.id); - } - else { - // item is already selected -> deselect it - selection.splice(index, 1); - } - this.setSelection(selection); - - this.body.emitter.emit('select', { - items: this.getSelection() + Network.prototype._onDragEnd = function () { + this.drag.dragging = false; + var selection = this.drag.selection; + if (selection && selection.length) { + selection.forEach(function (s) { + // restore original xFixed and yFixed + s.node.xFixed = s.xFixed; + s.node.yFixed = s.yFixed; }); - - event.stopPropagation(); + this.moving = true; + this.start(); + } + else { + this._redraw(); } + }; /** - * Find an item from an event target: - * searches for the attribute 'timeline-item' in the event target's element tree - * @param {Event} event - * @return {Item | null} item + * handle tap/click event: select/unselect a node + * @private */ - ItemSet.itemFromTarget = function(event) { - var target = event.target; - while (target) { - if (target.hasOwnProperty('timeline-item')) { - return target['timeline-item']; - } - target = target.parentNode; - } + Network.prototype._onTap = function (event) { + var pointer = this._getPointer(event.gesture.center); + this.pointerPosition = pointer; + this._handleTap(pointer); - return null; }; + /** - * Find the Group from an event target: - * searches for the attribute 'timeline-group' in the event target's element tree - * @param {Event} event - * @return {Group | null} group + * handle doubletap event + * @private */ - ItemSet.groupFromTarget = function(event) { - var target = event.target; - while (target) { - if (target.hasOwnProperty('timeline-group')) { - return target['timeline-group']; - } - target = target.parentNode; - } - - return null; + Network.prototype._onDoubleTap = function (event) { + var pointer = this._getPointer(event.gesture.center); + this._handleDoubleTap(pointer); }; + /** - * Find the ItemSet from an event target: - * searches for the attribute 'timeline-itemset' in the event target's element tree - * @param {Event} event - * @return {ItemSet | null} item + * handle long tap event: multi select nodes + * @private */ - ItemSet.itemSetFromTarget = function(event) { - var target = event.target; - while (target) { - if (target.hasOwnProperty('timeline-itemset')) { - return target['timeline-itemset']; - } - target = target.parentNode; - } - - return null; + Network.prototype._onHold = function (event) { + var pointer = this._getPointer(event.gesture.center); + this.pointerPosition = pointer; + this._handleOnHold(pointer); }; - module.exports = ItemSet; + /** + * handle the release of the screen + * + * @private + */ + Network.prototype._onRelease = function (event) { + var pointer = this._getPointer(event.gesture.center); + this._handleOnRelease(pointer); + }; + /** + * Handle pinch event + * @param event + * @private + */ + Network.prototype._onPinch = function (event) { + var pointer = this._getPointer(event.gesture.center); -/***/ }, -/* 29 */ -/***/ function(module, exports, __webpack_require__) { + this.drag.pinched = true; + if (!('scale' in this.pinch)) { + this.pinch.scale = 1; + } - var util = __webpack_require__(1); - var stack = __webpack_require__(30); - var ItemRange = __webpack_require__(31); + // TODO: enabled moving while pinching? + var scale = this.pinch.scale * event.gesture.scale; + this._zoom(scale, pointer) + }; /** - * @constructor Group - * @param {Number | String} groupId - * @param {Object} data - * @param {ItemSet} itemSet + * Zoom the network in or out + * @param {Number} scale a number around 1, and between 0.01 and 10 + * @param {{x: Number, y: Number}} pointer Position on screen + * @return {Number} appliedScale scale is limited within the boundaries + * @private */ - function Group (groupId, data, itemSet) { - this.groupId = groupId; + Network.prototype._zoom = function(scale, pointer) { + if (this.constants.zoomable == true) { + var scaleOld = this._getScale(); + if (scale < 0.00001) { + scale = 0.00001; + } + if (scale > 10) { + scale = 10; + } - this.itemSet = itemSet; + var preScaleDragPointer = null; + if (this.drag !== undefined) { + if (this.drag.dragging == true) { + preScaleDragPointer = this.DOMtoCanvas(this.drag.pointer); + } + } + // + this.frame.canvas.clientHeight / 2 + var translation = this._getTranslation(); - this.dom = {}; - this.props = { - label: { - width: 0, - height: 0 + var scaleFrac = scale / scaleOld; + var tx = (1 - scaleFrac) * pointer.x + translation.x * scaleFrac; + var ty = (1 - scaleFrac) * pointer.y + translation.y * scaleFrac; + + this.areaCenter = {"x" : this._XconvertDOMtoCanvas(pointer.x), + "y" : this._YconvertDOMtoCanvas(pointer.y)}; + + this._setScale(scale); + this._setTranslation(tx, ty); + this.updateClustersDefault(); + + if (preScaleDragPointer != null) { + var postScaleDragPointer = this.canvasToDOM(preScaleDragPointer); + this.drag.pointer.x = postScaleDragPointer.x; + this.drag.pointer.y = postScaleDragPointer.y; } - }; - this.className = null; - this.items = {}; // items filtered by groupId of this group - this.visibleItems = []; // items currently visible in window - this.orderedItems = { // items sorted by start and by end - byStart: [], - byEnd: [] - }; + this._redraw(); - this._create(); + if (scaleOld < scale) { + this.emit("zoom", {direction:"+"}); + } + else { + this.emit("zoom", {direction:"-"}); + } + + return scale; + } + }; - this.setData(data); - } /** - * Create DOM elements for the group + * Event handler for mouse wheel event, used to zoom the timeline + * See http://adomas.org/javascript-mouse-wheel/ + * https://github.com/EightMedia/hammer.js/issues/256 + * @param {MouseEvent} event * @private */ - Group.prototype._create = function() { - var label = document.createElement('div'); - label.className = 'vlabel'; - this.dom.label = label; + Network.prototype._onMouseWheel = function(event) { + // retrieve delta + var delta = 0; + if (event.wheelDelta) { /* IE/Opera. */ + delta = event.wheelDelta/120; + } else if (event.detail) { /* Mozilla case. */ + // In Mozilla, sign of delta is different than in IE. + // Also, delta is multiple of 3. + delta = -event.detail/3; + } - var inner = document.createElement('div'); - inner.className = 'inner'; - label.appendChild(inner); - this.dom.inner = inner; + // If delta is nonzero, handle it. + // Basically, delta is now positive if wheel was scrolled up, + // and negative, if wheel was scrolled down. + if (delta) { - var foreground = document.createElement('div'); - foreground.className = 'group'; - foreground['timeline-group'] = this; - this.dom.foreground = foreground; + // calculate the new scale + var scale = this._getScale(); + var zoom = delta / 10; + if (delta < 0) { + zoom = zoom / (1 - zoom); + } + scale *= (1 + zoom); - this.dom.background = document.createElement('div'); - this.dom.background.className = 'group'; + // calculate the pointer location + var gesture = hammerUtil.fakeGesture(this, event); + var pointer = this._getPointer(gesture.center); - this.dom.axis = document.createElement('div'); - this.dom.axis.className = 'group'; + // apply the new scale + this._zoom(scale, pointer); + } - // create a hidden marker to detect when the Timelines container is attached - // to the DOM, or the style of a parent of the Timeline is changed from - // display:none is changed to visible. - this.dom.marker = document.createElement('div'); - this.dom.marker.style.visibility = 'hidden'; - this.dom.marker.innerHTML = '?'; - this.dom.background.appendChild(this.dom.marker); + // Prevent default actions caused by mouse wheel. + event.preventDefault(); }; + /** - * Set the group data for this group - * @param {Object} data Group data, can contain properties content and className + * Mouse move handler for checking whether the title moves over a node with a title. + * @param {Event} event + * @private */ - Group.prototype.setData = function(data) { - // update contents - var content = data && data.content; - if (content instanceof Element) { - this.dom.inner.appendChild(content); - } - else if (content !== undefined && content !== null) { - this.dom.inner.innerHTML = content; - } - else { - this.dom.inner.innerHTML = this.groupId || ''; // groupId can be null - } + Network.prototype._onMouseMoveTitle = function (event) { + var gesture = hammerUtil.fakeGesture(this, event); + var pointer = this._getPointer(gesture.center); - // update title - this.dom.label.title = data && data.title || ''; + // check if the previously selected node is still selected + if (this.popupObj) { + this._checkHidePopup(pointer); + } - if (!this.dom.inner.firstChild) { - util.addClassName(this.dom.inner, 'hidden'); + // start a timeout that will check if the mouse is positioned above + // an element + var me = this; + var checkShow = function() { + me._checkShowPopup(pointer); + }; + if (this.popupTimer) { + clearInterval(this.popupTimer); // stop any running calculationTimer } - else { - util.removeClassName(this.dom.inner, 'hidden'); + if (!this.drag.dragging) { + this.popupTimer = setTimeout(checkShow, this.constants.tooltip.delay); } - // update className - var className = data && data.className || null; - if (className != this.className) { - if (this.className) { - util.removeClassName(this.dom.label, className); - util.removeClassName(this.dom.foreground, className); - util.removeClassName(this.dom.background, className); - util.removeClassName(this.dom.axis, className); + + /** + * Adding hover highlights + */ + if (this.constants.hover == true) { + // removing all hover highlights + for (var edgeId in this.hoverObj.edges) { + if (this.hoverObj.edges.hasOwnProperty(edgeId)) { + this.hoverObj.edges[edgeId].hover = false; + delete this.hoverObj.edges[edgeId]; + } } - util.addClassName(this.dom.label, className); - util.addClassName(this.dom.foreground, className); - util.addClassName(this.dom.background, className); - util.addClassName(this.dom.axis, className); - } - }; - /** - * Get the width of the group label - * @return {number} width - */ - Group.prototype.getLabelWidth = function() { - return this.props.label.width; - }; + // adding hover highlights + var obj = this._getNodeAt(pointer); + if (obj == null) { + obj = this._getEdgeAt(pointer); + } + if (obj != null) { + this._hoverObject(obj); + } + // removing all node hover highlights except for the selected one. + for (var nodeId in this.hoverObj.nodes) { + if (this.hoverObj.nodes.hasOwnProperty(nodeId)) { + if (obj instanceof Node && obj.id != nodeId || obj instanceof Edge || obj == null) { + this._blurObject(this.hoverObj.nodes[nodeId]); + delete this.hoverObj.nodes[nodeId]; + } + } + } + this.redraw(); + } + }; /** - * Repaint this group - * @param {{start: number, end: number}} range - * @param {{item: {horizontal: number, vertical: number}, axis: number}} margin - * @param {boolean} [restack=false] Force restacking of all items - * @return {boolean} Returns true if the group is resized + * Check if there is an element on the given position in the network + * (a node or edge). If so, and if this element has a title, + * show a popup window with its title. + * + * @param {{x:Number, y:Number}} pointer + * @private */ - Group.prototype.redraw = function(range, margin, restack) { - var resized = false; - - this.visibleItems = this._updateVisibleItems(this.orderedItems, this.visibleItems, range); - - // force recalculation of the height of the items when the marker height changed - // (due to the Timeline being attached to the DOM or changed from display:none to visible) - var markerHeight = this.dom.marker.clientHeight; - if (markerHeight != this.lastMarkerHeight) { - this.lastMarkerHeight = markerHeight; + Network.prototype._checkShowPopup = function (pointer) { + var obj = { + left: this._XconvertDOMtoCanvas(pointer.x), + top: this._YconvertDOMtoCanvas(pointer.y), + right: this._XconvertDOMtoCanvas(pointer.x), + bottom: this._YconvertDOMtoCanvas(pointer.y) + }; - util.forEach(this.items, function (item) { - item.dirty = true; - if (item.displayed) item.redraw(); - }); + var id; + var lastPopupNode = this.popupObj; - restack = true; + if (this.popupObj == undefined) { + // search the nodes for overlap, select the top one in case of multiple nodes + var nodes = this.nodes; + for (id in nodes) { + if (nodes.hasOwnProperty(id)) { + var node = nodes[id]; + if (node.getTitle() !== undefined && node.isOverlappingWith(obj)) { + this.popupObj = node; + break; + } + } + } } - // reposition visible items vertically - if (this.itemSet.options.stack) { // TODO: ugly way to access options... - stack.stack(this.visibleItems, margin, restack); - } - else { // no stacking - stack.nostack(this.visibleItems, margin); + if (this.popupObj === undefined) { + // search the edges for overlap + var edges = this.edges; + for (id in edges) { + if (edges.hasOwnProperty(id)) { + var edge = edges[id]; + if (edge.connected && (edge.getTitle() !== undefined) && + edge.isOverlappingWith(obj)) { + this.popupObj = edge; + break; + } + } + } } - // recalculate the height of the group - var height; - var visibleItems = this.visibleItems; - if (visibleItems.length) { - var min = visibleItems[0].top; - var max = visibleItems[0].top + visibleItems[0].height; - util.forEach(visibleItems, function (item) { - min = Math.min(min, item.top); - max = Math.max(max, (item.top + item.height)); - }); - if (min > margin.axis) { - // there is an empty gap between the lowest item and the axis - var offset = min - margin.axis; - max -= offset; - util.forEach(visibleItems, function (item) { - item.top -= offset; - }); + if (this.popupObj) { + // show popup message window + if (this.popupObj != lastPopupNode) { + var me = this; + if (!me.popup) { + me.popup = new Popup(me.frame, me.constants.tooltip); + } + + // adjust a small offset such that the mouse cursor is located in the + // bottom left location of the popup, and you can easily move over the + // popup area + me.popup.setPosition(pointer.x - 3, pointer.y - 3); + me.popup.setText(me.popupObj.getTitle()); + me.popup.show(); } - height = max + margin.item.vertical / 2; } else { - height = margin.axis + margin.item.vertical; + if (this.popup) { + this.popup.hide(); + } } - height = Math.max(height, this.props.label.height); - - // calculate actual size and position - var foreground = this.dom.foreground; - this.top = foreground.offsetTop; - this.left = foreground.offsetLeft; - this.width = foreground.offsetWidth; - resized = util.updateProperty(this, 'height', height) || resized; - - // recalculate size of label - resized = util.updateProperty(this.props.label, 'width', this.dom.inner.clientWidth) || resized; - resized = util.updateProperty(this.props.label, 'height', this.dom.inner.clientHeight) || resized; + }; - // apply new height - this.dom.background.style.height = height + 'px'; - this.dom.foreground.style.height = height + 'px'; - this.dom.label.style.height = height + 'px'; - // update vertical position of items after they are re-stacked and the height of the group is calculated - for (var i = 0, ii = this.visibleItems.length; i < ii; i++) { - var item = this.visibleItems[i]; - item.repositionY(); + /** + * Check if the popup must be hided, which is the case when the mouse is no + * longer hovering on the object + * @param {{x:Number, y:Number}} pointer + * @private + */ + Network.prototype._checkHidePopup = function (pointer) { + if (!this.popupObj || !this._getNodeAt(pointer) ) { + this.popupObj = undefined; + if (this.popup) { + this.popup.hide(); + } } - - return resized; }; + /** - * Show this group: attach to the DOM + * Set a new size for the network + * @param {string} width Width in pixels or percentage (for example '800px' + * or '50%') + * @param {string} height Height in pixels or percentage (for example '400px' + * or '30%') */ - Group.prototype.show = function() { - if (!this.dom.label.parentNode) { - this.itemSet.dom.labelSet.appendChild(this.dom.label); - } + Network.prototype.setSize = function(width, height) { + this.frame.style.width = width; + this.frame.style.height = height; - if (!this.dom.foreground.parentNode) { - this.itemSet.dom.foreground.appendChild(this.dom.foreground); - } + this.frame.canvas.style.width = '100%'; + this.frame.canvas.style.height = '100%'; - if (!this.dom.background.parentNode) { - this.itemSet.dom.background.appendChild(this.dom.background); - } + this.frame.canvas.width = this.frame.canvas.clientWidth; + this.frame.canvas.height = this.frame.canvas.clientHeight; - if (!this.dom.axis.parentNode) { - this.itemSet.dom.axis.appendChild(this.dom.axis); + if (this.manipulationDiv !== undefined) { + this.manipulationDiv.style.width = this.frame.canvas.clientWidth + "px"; + } + if (this.navigationDivs !== undefined) { + if (this.navigationDivs['wrapper'] !== undefined) { + this.navigationDivs['wrapper'].style.width = this.frame.canvas.clientWidth + "px"; + this.navigationDivs['wrapper'].style.height = this.frame.canvas.clientHeight + "px"; + } } + + this.emit('resize', {width:this.frame.canvas.width,height:this.frame.canvas.height}); }; /** - * Hide this group: remove from the DOM + * Set a data set with nodes for the network + * @param {Array | DataSet | DataView} nodes The data containing the nodes. + * @private */ - Group.prototype.hide = function() { - var label = this.dom.label; - if (label.parentNode) { - label.parentNode.removeChild(label); - } + Network.prototype._setNodes = function(nodes) { + var oldNodesData = this.nodesData; - var foreground = this.dom.foreground; - if (foreground.parentNode) { - foreground.parentNode.removeChild(foreground); + if (nodes instanceof DataSet || nodes instanceof DataView) { + this.nodesData = nodes; } - - var background = this.dom.background; - if (background.parentNode) { - background.parentNode.removeChild(background); + else if (nodes instanceof Array) { + this.nodesData = new DataSet(); + this.nodesData.add(nodes); } - - var axis = this.dom.axis; - if (axis.parentNode) { - axis.parentNode.removeChild(axis); + else if (!nodes) { + this.nodesData = new DataSet(); + } + else { + throw new TypeError('Array or DataSet expected'); } - }; - - /** - * Add an item to the group - * @param {Item} item - */ - Group.prototype.add = function(item) { - this.items[item.id] = item; - item.setParent(this); - if (this.visibleItems.indexOf(item) == -1) { - var range = this.itemSet.body.range; // TODO: not nice accessing the range like this - this._checkIfVisible(item, this.visibleItems, range); + if (oldNodesData) { + // unsubscribe from old dataset + util.forEach(this.nodesListeners, function (callback, event) { + oldNodesData.off(event, callback); + }); } - }; - /** - * Remove an item from the group - * @param {Item} item - */ - Group.prototype.remove = function(item) { - delete this.items[item.id]; - item.setParent(this.itemSet); + // remove drawn nodes + this.nodes = {}; - // remove from visible items - var index = this.visibleItems.indexOf(item); - if (index != -1) this.visibleItems.splice(index, 1); + if (this.nodesData) { + // subscribe to new dataset + var me = this; + util.forEach(this.nodesListeners, function (callback, event) { + me.nodesData.on(event, callback); + }); - // TODO: also remove from ordered items? + // draw all new nodes + var ids = this.nodesData.getIds(); + this._addNodes(ids); + } + this._updateSelection(); }; /** - * Remove an item from the corresponding DataSet - * @param {Item} item + * Add nodes + * @param {Number[] | String[]} ids + * @private */ - Group.prototype.removeFromDataSet = function(item) { - this.itemSet.removeItem(item.id); + Network.prototype._addNodes = function(ids) { + var id; + for (var i = 0, len = ids.length; i < len; i++) { + id = ids[i]; + var data = this.nodesData.get(id); + var node = new Node(data, this.images, this.groups, this.constants); + this.nodes[id] = node; // note: this may replace an existing node + if ((node.xFixed == false || node.yFixed == false) && (node.x === null || node.y === null)) { + var radius = 10 * 0.1*ids.length + 10; + var angle = 2 * Math.PI * Math.random(); + if (node.xFixed == false) {node.x = radius * Math.cos(angle);} + if (node.yFixed == false) {node.y = radius * Math.sin(angle);} + } + this.moving = true; + } + this._updateNodeIndexList(); + if (this.constants.hierarchicalLayout.enabled == true && this.initializing == false) { + this._resetLevels(); + this._setupHierarchicalLayout(); + } + this._updateCalculationNodes(); + this._reconnectEdges(); + this._updateValueRange(this.nodes); + this.updateLabels(); }; /** - * Reorder the items + * Update existing nodes, or create them when not yet existing + * @param {Number[] | String[]} ids + * @private */ - Group.prototype.order = function() { - var array = util.toArray(this.items); - this.orderedItems.byStart = array; - this.orderedItems.byEnd = this._constructByEndArray(array); - - stack.orderByStart(this.orderedItems.byStart); - stack.orderByEnd(this.orderedItems.byEnd); + Network.prototype._updateNodes = function(ids) { + var nodes = this.nodes, + nodesData = this.nodesData; + for (var i = 0, len = ids.length; i < len; i++) { + var id = ids[i]; + var node = nodes[id]; + var data = nodesData.get(id); + if (node) { + // update node + node.setProperties(data, this.constants); + } + else { + // create node + node = new Node(properties, this.images, this.groups, this.constants); + nodes[id] = node; + } + } + this.moving = true; + if (this.constants.hierarchicalLayout.enabled == true && this.initializing == false) { + this._resetLevels(); + this._setupHierarchicalLayout(); + } + this._updateNodeIndexList(); + this._reconnectEdges(); + this._updateValueRange(nodes); }; /** - * Create an array containing all items being a range (having an end date) - * @param {Item[]} array - * @returns {ItemRange[]} + * Remove existing nodes. If nodes do not exist, the method will just ignore it. + * @param {Number[] | String[]} ids * @private */ - Group.prototype._constructByEndArray = function(array) { - var endArray = []; - - for (var i = 0; i < array.length; i++) { - if (array[i] instanceof ItemRange) { - endArray.push(array[i]); - } + Network.prototype._removeNodes = function(ids) { + var nodes = this.nodes; + for (var i = 0, len = ids.length; i < len; i++) { + var id = ids[i]; + delete nodes[id]; } - return endArray; + this._updateNodeIndexList(); + if (this.constants.hierarchicalLayout.enabled == true && this.initializing == false) { + this._resetLevels(); + this._setupHierarchicalLayout(); + } + this._updateCalculationNodes(); + this._reconnectEdges(); + this._updateSelection(); + this._updateValueRange(nodes); }; /** - * Update the visible items - * @param {{byStart: Item[], byEnd: Item[]}} orderedItems All items ordered by start date and by end date - * @param {Item[]} visibleItems The previously visible items. - * @param {{start: number, end: number}} range Visible range - * @return {Item[]} visibleItems The new visible items. + * Load edges by reading the data table + * @param {Array | DataSet | DataView} edges The data containing the edges. + * @private * @private */ - Group.prototype._updateVisibleItems = function(orderedItems, visibleItems, range) { - var initialPosByStart, - newVisibleItems = [], - i; + Network.prototype._setEdges = function(edges) { + var oldEdgesData = this.edgesData; - // first check if the items that were in view previously are still in view. - // this handles the case for the ItemRange that is both before and after the current one. - if (visibleItems.length > 0) { - for (i = 0; i < visibleItems.length; i++) { - this._checkIfVisible(visibleItems[i], newVisibleItems, range); - } + if (edges instanceof DataSet || edges instanceof DataView) { + this.edgesData = edges; } - - // If there were no visible items previously, use binarySearch to find a visible ItemPoint or ItemRange (based on startTime) - if (newVisibleItems.length == 0) { - initialPosByStart = util.binarySearch(orderedItems.byStart, range, 'data','start'); + else if (edges instanceof Array) { + this.edgesData = new DataSet(); + this.edgesData.add(edges); + } + else if (!edges) { + this.edgesData = new DataSet(); } else { - initialPosByStart = orderedItems.byStart.indexOf(newVisibleItems[0]); + throw new TypeError('Array or DataSet expected'); } - // use visible search to find a visible ItemRange (only based on endTime) - var initialPosByEnd = util.binarySearch(orderedItems.byEnd, range, 'data','end'); - - // if we found a initial ID to use, trace it up and down until we meet an invisible item. - if (initialPosByStart != -1) { - for (i = initialPosByStart; i >= 0; i--) { - if (this._checkIfInvisible(orderedItems.byStart[i], newVisibleItems, range)) {break;} - } - for (i = initialPosByStart + 1; i < orderedItems.byStart.length; i++) { - if (this._checkIfInvisible(orderedItems.byStart[i], newVisibleItems, range)) {break;} - } + if (oldEdgesData) { + // unsubscribe from old dataset + util.forEach(this.edgesListeners, function (callback, event) { + oldEdgesData.off(event, callback); + }); } - // if we found a initial ID to use, trace it up and down until we meet an invisible item. - if (initialPosByEnd != -1) { - for (i = initialPosByEnd; i >= 0; i--) { - if (this._checkIfInvisible(orderedItems.byEnd[i], newVisibleItems, range)) {break;} - } - for (i = initialPosByEnd + 1; i < orderedItems.byEnd.length; i++) { - if (this._checkIfInvisible(orderedItems.byEnd[i], newVisibleItems, range)) {break;} - } - } + // remove drawn edges + this.edges = {}; - return newVisibleItems; - }; + if (this.edgesData) { + // subscribe to new dataset + var me = this; + util.forEach(this.edgesListeners, function (callback, event) { + me.edgesData.on(event, callback); + }); + // draw all new nodes + var ids = this.edgesData.getIds(); + this._addEdges(ids); + } + this._reconnectEdges(); + }; /** - * this function checks if an item is invisible. If it is NOT we make it visible - * and add it to the global visible items. If it is, return true. - * - * @param {Item} item - * @param {Item[]} visibleItems - * @param {{start:number, end:number}} range - * @returns {boolean} + * Add edges + * @param {Number[] | String[]} ids * @private */ - Group.prototype._checkIfInvisible = function(item, visibleItems, range) { - if (item.isVisible(range)) { - if (!item.displayed) item.show(); - item.repositionX(); - if (visibleItems.indexOf(item) == -1) { - visibleItems.push(item); - } - return false; - } - else { - if (item.displayed) item.hide(); - return true; + Network.prototype._addEdges = function (ids) { + var edges = this.edges, + edgesData = this.edgesData; + + for (var i = 0, len = ids.length; i < len; i++) { + var id = ids[i]; + + var oldEdge = edges[id]; + if (oldEdge) { + oldEdge.disconnect(); + } + + var data = edgesData.get(id, {"showInternalIds" : true}); + edges[id] = new Edge(data, this, this.constants); } + + this.moving = true; + this._updateValueRange(edges); + this._createBezierNodes(); + if (this.constants.hierarchicalLayout.enabled == true && this.initializing == false) { + this._resetLevels(); + this._setupHierarchicalLayout(); + } + this._updateCalculationNodes(); }; /** - * this function is very similar to the _checkIfInvisible() but it does not - * return booleans, hides the item if it should not be seen and always adds to - * the visibleItems. - * this one is for brute forcing and hiding. - * - * @param {Item} item - * @param {Array} visibleItems - * @param {{start:number, end:number}} range + * Update existing edges, or create them when not yet existing + * @param {Number[] | String[]} ids * @private */ - Group.prototype._checkIfVisible = function(item, visibleItems, range) { - if (item.isVisible(range)) { - if (!item.displayed) item.show(); - // reposition item horizontally - item.repositionX(); - visibleItems.push(item); + Network.prototype._updateEdges = function (ids) { + var edges = this.edges, + edgesData = this.edgesData; + for (var i = 0, len = ids.length; i < len; i++) { + var id = ids[i]; + + var data = edgesData.get(id); + var edge = edges[id]; + if (edge) { + // update edge + edge.disconnect(); + edge.setProperties(data, this.constants); + edge.connect(); + } + else { + // create edge + edge = new Edge(data, this, this.constants); + this.edges[id] = edge; + } } - else { - if (item.displayed) item.hide(); + + this._createBezierNodes(); + if (this.constants.hierarchicalLayout.enabled == true && this.initializing == false) { + this._resetLevels(); + this._setupHierarchicalLayout(); } + this.moving = true; + this._updateValueRange(edges); }; - module.exports = Group; - - -/***/ }, -/* 30 */ -/***/ function(module, exports, __webpack_require__) { - - // Utility functions for ordering and stacking of items - var EPSILON = 0.001; // used when checking collisions, to prevent round-off errors - /** - * Order items by their start data - * @param {Item[]} items + * Remove existing edges. Non existing ids will be ignored + * @param {Number[] | String[]} ids + * @private */ - exports.orderByStart = function(items) { - items.sort(function (a, b) { - return a.data.start - b.data.start; - }); + Network.prototype._removeEdges = function (ids) { + var edges = this.edges; + for (var i = 0, len = ids.length; i < len; i++) { + var id = ids[i]; + var edge = edges[id]; + if (edge) { + if (edge.via != null) { + delete this.sectors['support']['nodes'][edge.via.id]; + } + edge.disconnect(); + delete edges[id]; + } + } + + this.moving = true; + this._updateValueRange(edges); + if (this.constants.hierarchicalLayout.enabled == true && this.initializing == false) { + this._resetLevels(); + this._setupHierarchicalLayout(); + } + this._updateCalculationNodes(); }; /** - * Order items by their end date. If they have no end date, their start date - * is used. - * @param {Item[]} items + * Reconnect all edges + * @private */ - exports.orderByEnd = function(items) { - items.sort(function (a, b) { - var aTime = ('end' in a.data) ? a.data.end : a.data.start, - bTime = ('end' in b.data) ? b.data.end : b.data.start; + Network.prototype._reconnectEdges = function() { + var id, + nodes = this.nodes, + edges = this.edges; + for (id in nodes) { + if (nodes.hasOwnProperty(id)) { + nodes[id].edges = []; + } + } - return aTime - bTime; - }); + for (id in edges) { + if (edges.hasOwnProperty(id)) { + var edge = edges[id]; + edge.from = null; + edge.to = null; + edge.connect(); + } + } }; /** - * Adjust vertical positions of the items such that they don't overlap each - * other. - * @param {Item[]} items - * All visible items - * @param {{item: {horizontal: number, vertical: number}, axis: number}} margin - * Margins between items and between items and the axis. - * @param {boolean} [force=false] - * If true, all items will be repositioned. If false (default), only - * items having a top===null will be re-stacked + * 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 */ - exports.stack = function(items, margin, force) { - var i, iMax; + Network.prototype._updateValueRange = function(obj) { + var id; - if (force) { - // reset top position of all items - for (i = 0, iMax = items.length; i < iMax; i++) { - items[i].top = null; + // determine the range of the objects + var valueMin = undefined; + var valueMax = undefined; + 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); + } } } - // calculate new, non-overlapping positions - for (i = 0, iMax = items.length; i < iMax; i++) { - var item = items[i]; - if (item.top === null) { - // initialize top position - item.top = margin.axis; - - do { - // TODO: optimize checking for overlap. when there is a gap without items, - // you only need to check for items from the next item on, not from zero - var collidingItem = null; - for (var j = 0, jj = items.length; j < jj; j++) { - var other = items[j]; - if (other.top !== null && other !== item && exports.collision(item, other, margin.item)) { - collidingItem = other; - break; - } - } - - if (collidingItem != null) { - // There is a collision. Reposition the items above the colliding element - item.top = collidingItem.top + collidingItem.height + margin.item.vertical; - } - } while (collidingItem); + // adjust the range of all objects + if (valueMin !== undefined && valueMax !== undefined) { + for (id in obj) { + if (obj.hasOwnProperty(id)) { + obj[id].setValueRange(valueMin, valueMax); + } } } }; /** - * Adjust vertical positions of the items without stacking them - * @param {Item[]} items - * All visible items - * @param {{item: {horizontal: number, vertical: number}, axis: number}} margin - * Margins between items and between items and the axis. + * Redraw the network with the current data + * chart will be resized too. */ - exports.nostack = function(items, margin) { - var i, iMax; - - // reset top position of all items - for (i = 0, iMax = items.length; i < iMax; i++) { - items[i].top = margin.axis; - } + Network.prototype.redraw = function() { + this.setSize(this.constants.width, this.constants.height); + this._redraw(); }; /** - * Test if the two provided items collide - * The items must have parameters left, width, top, and height. - * @param {Item} a The first item - * @param {Item} b The second item - * @param {{horizontal: number, vertical: number}} margin - * An object containing a horizontal and vertical - * minimum required margin. - * @return {boolean} true if a and b collide, else false + * Redraw the network with the current data + * @private */ - exports.collision = function(a, b, margin) { - return ((a.left - margin.horizontal + EPSILON) < (b.left + b.width) && - (a.left + a.width + margin.horizontal - EPSILON) > b.left && - (a.top - margin.vertical + EPSILON) < (b.top + b.height) && - (a.top + a.height + margin.vertical - EPSILON) > b.top); - }; + Network.prototype._redraw = function() { + var ctx = this.frame.canvas.getContext('2d'); + // clear the canvas + var w = this.frame.canvas.width; + var h = this.frame.canvas.height; + ctx.clearRect(0, 0, w, h); + // set scaling and translation + ctx.save(); + ctx.translate(this.translation.x, this.translation.y); + ctx.scale(this.scale, this.scale); -/***/ }, -/* 31 */ -/***/ function(module, exports, __webpack_require__) { + this.canvasTopLeft = { + "x": this._XconvertDOMtoCanvas(0), + "y": this._YconvertDOMtoCanvas(0) + }; + this.canvasBottomRight = { + "x": this._XconvertDOMtoCanvas(this.frame.canvas.clientWidth), + "y": this._YconvertDOMtoCanvas(this.frame.canvas.clientHeight) + }; - var Hammer = __webpack_require__(18); - var Item = __webpack_require__(32); - /** - * @constructor ItemRange - * @extends Item - * @param {Object} data Object containing parameters start, end - * content, className. - * @param {{toScreen: function, toTime: function}} conversion - * Conversion functions from time to screen and vice versa - * @param {Object} [options] Configuration options - * // TODO: describe options - */ - function ItemRange (data, conversion, options) { - this.props = { - content: { - width: 0 - } - }; - this.overflow = false; // if contents can overflow (css styling), this flag is set to true - - // validate data - if (data) { - if (data.start == undefined) { - throw new Error('Property "start" missing in item ' + data.id); - } - if (data.end == undefined) { - throw new Error('Property "end" missing in item ' + data.id); - } + this._doInAllSectors("_drawAllSectorNodes",ctx); + if (this.drag.dragging == false || this.drag.dragging === undefined || this.constants.hideEdgesOnDrag == false) { + this._doInAllSectors("_drawEdges",ctx); } - Item.call(this, data, conversion, options); - } + if (this.drag.dragging == false || this.drag.dragging === undefined || this.constants.hideNodesOnDrag == false) { + this._doInAllSectors("_drawNodes",ctx,false); + } - ItemRange.prototype = new Item (null, null, null); + if (this.controlNodesActive == true) { + this._doInAllSectors("_drawControlNodes",ctx); + } - ItemRange.prototype.baseClassName = 'item range'; + // this._doInSupportSector("_drawNodes",ctx,true); + // this._drawTree(ctx,"#F00F0F"); - /** - * Check whether this item is visible inside given range - * @returns {{start: Number, end: Number}} range with a timestamp for start and end - * @returns {boolean} True if visible - */ - ItemRange.prototype.isVisible = function(range) { - // determine visibility - return (this.data.start < range.end) && (this.data.end > range.start); + // restore original scaling and translation + ctx.restore(); }; /** - * Repaint the item + * Set the translation of the network + * @param {Number} offsetX Horizontal offset + * @param {Number} offsetY Vertical offset + * @private */ - ItemRange.prototype.redraw = function() { - var dom = this.dom; - if (!dom) { - // create DOM - this.dom = {}; - dom = this.dom; - - // background box - dom.box = document.createElement('div'); - // className is updated in redraw() - - // contents box - dom.content = document.createElement('div'); - dom.content.className = 'content'; - dom.box.appendChild(dom.content); - - // attach this item as attribute - dom.box['timeline-item'] = this; - } - - // append DOM to parent DOM - if (!this.parent) { - throw new Error('Cannot redraw item: no parent attached'); - } - if (!dom.box.parentNode) { - var foreground = this.parent.dom.foreground; - if (!foreground) { - throw new Error('Cannot redraw time axis: parent has no foreground container element'); - } - foreground.appendChild(dom.box); - } - this.displayed = true; - - // update contents - if (this.data.content != this.content) { - this.content = this.data.content; - if (this.content instanceof Element) { - dom.content.innerHTML = ''; - dom.content.appendChild(this.content); - } - else if (this.data.content != undefined) { - dom.content.innerHTML = this.content; - } - else { - throw new Error('Property "content" missing in item ' + this.data.id); - } - - this.dirty = true; - } - - // update title - if (this.data.title != this.title) { - dom.box.title = this.data.title; - this.title = this.data.title; + Network.prototype._setTranslation = function(offsetX, offsetY) { + if (this.translation === undefined) { + this.translation = { + x: 0, + y: 0 + }; } - // update class - var className = (this.data.className ? (' ' + this.data.className) : '') + - (this.selected ? ' selected' : ''); - if (this.className != className) { - this.className = className; - dom.box.className = this.baseClassName + className; - - this.dirty = true; + if (offsetX !== undefined) { + this.translation.x = offsetX; } - - // recalculate size - if (this.dirty) { - // determine from css whether this box has overflow - this.overflow = window.getComputedStyle(dom.content).overflow !== 'hidden'; - - this.props.content.width = this.dom.content.offsetWidth; - this.height = this.dom.box.offsetHeight; - - this.dirty = false; + if (offsetY !== undefined) { + this.translation.y = offsetY; } - this._repaintDeleteButton(dom.box); - this._repaintDragLeft(); - this._repaintDragRight(); + this.emit('viewChanged'); }; /** - * Show the item in the DOM (when not already visible). The items DOM will - * be created when needed. + * Get the translation of the network + * @return {Object} translation An object with parameters x and y, both a number + * @private */ - ItemRange.prototype.show = function() { - if (!this.displayed) { - this.redraw(); - } + Network.prototype._getTranslation = function() { + return { + x: this.translation.x, + y: this.translation.y + }; }; /** - * Hide the item from the DOM (when visible) - * @return {Boolean} changed + * Scale the network + * @param {Number} scale Scaling factor 1.0 is unscaled + * @private */ - ItemRange.prototype.hide = function() { - if (this.displayed) { - var box = this.dom.box; - - if (box.parentNode) { - box.parentNode.removeChild(box); - } - - this.top = null; - this.left = null; - - this.displayed = false; - } + Network.prototype._setScale = function(scale) { + this.scale = scale; }; /** - * Reposition the item horizontally - * @Override + * Get the current scale of the network + * @return {Number} scale Scaling factor 1.0 is unscaled + * @private */ - ItemRange.prototype.repositionX = function() { - var props = this.props, - parentWidth = this.parent.width, - start = this.conversion.toScreen(this.data.start), - end = this.conversion.toScreen(this.data.end), - padding = this.options.padding, - contentLeft; - - // limit the width of the this, as browsers cannot draw very wide divs - if (start < -parentWidth) { - start = -parentWidth; - } - if (end > 2 * parentWidth) { - end = 2 * parentWidth; - } - var boxWidth = Math.max(end - start, 1); - - if (this.overflow) { - // when range exceeds left of the window, position the contents at the left of the visible area - contentLeft = Math.max(-start, 0); - - this.left = start; - this.width = boxWidth + this.props.content.width; - // Note: The calculation of width is an optimistic calculation, giving - // a width which will not change when moving the Timeline - // So no restacking needed, which is nicer for the eye; - } - else { // no overflow - // when range exceeds left of the window, position the contents at the left of the visible area - if (start < 0) { - contentLeft = Math.min(-start, - (end - start - props.content.width - 2 * padding)); - // TODO: remove the need for options.padding. it's terrible. - } - else { - contentLeft = 0; - } - - this.left = start; - this.width = boxWidth; - } - - this.dom.box.style.left = this.left + 'px'; - this.dom.box.style.width = boxWidth + 'px'; - this.dom.content.style.left = contentLeft + 'px'; + Network.prototype._getScale = function() { + return this.scale; }; /** - * Reposition the item vertically - * @Override + * Convert the X coordinate in DOM-space (coordinate point in browser relative to the container div) to + * the X coordinate in canvas-space (the simulation sandbox, which the camera looks upon) + * @param {number} x + * @returns {number} + * @private */ - ItemRange.prototype.repositionY = function() { - var orientation = this.options.orientation, - box = this.dom.box; - - if (orientation == 'top') { - box.style.top = this.top + 'px'; - } - else { - box.style.top = (this.parent.height - this.top - this.height) + 'px'; - } + Network.prototype._XconvertDOMtoCanvas = function(x) { + return (x - this.translation.x) / this.scale; }; /** - * Repaint a drag area on the left side of the range when the range is selected - * @protected + * Convert the X coordinate in canvas-space (the simulation sandbox, which the camera looks upon) to + * the X coordinate in DOM-space (coordinate point in browser relative to the container div) + * @param {number} x + * @returns {number} + * @private */ - ItemRange.prototype._repaintDragLeft = function () { - if (this.selected && this.options.editable.updateTime && !this.dom.dragLeft) { - // create and show drag area - var dragLeft = document.createElement('div'); - dragLeft.className = 'drag-left'; - dragLeft.dragLeftItem = this; - - // TODO: this should be redundant? - Hammer(dragLeft, { - preventDefault: true - }).on('drag', function () { - //console.log('drag left') - }); - - this.dom.box.appendChild(dragLeft); - this.dom.dragLeft = dragLeft; - } - else if (!this.selected && this.dom.dragLeft) { - // delete drag area - if (this.dom.dragLeft.parentNode) { - this.dom.dragLeft.parentNode.removeChild(this.dom.dragLeft); - } - this.dom.dragLeft = null; - } + Network.prototype._XconvertCanvasToDOM = function(x) { + return x * this.scale + this.translation.x; }; /** - * Repaint a drag area on the right side of the range when the range is selected - * @protected + * Convert the Y coordinate in DOM-space (coordinate point in browser relative to the container div) to + * the Y coordinate in canvas-space (the simulation sandbox, which the camera looks upon) + * @param {number} y + * @returns {number} + * @private */ - ItemRange.prototype._repaintDragRight = function () { - if (this.selected && this.options.editable.updateTime && !this.dom.dragRight) { - // create and show drag area - var dragRight = document.createElement('div'); - dragRight.className = 'drag-right'; - dragRight.dragRightItem = this; - - // TODO: this should be redundant? - Hammer(dragRight, { - preventDefault: true - }).on('drag', function () { - //console.log('drag right') - }); - - this.dom.box.appendChild(dragRight); - this.dom.dragRight = dragRight; - } - else if (!this.selected && this.dom.dragRight) { - // delete drag area - if (this.dom.dragRight.parentNode) { - this.dom.dragRight.parentNode.removeChild(this.dom.dragRight); - } - this.dom.dragRight = null; - } + Network.prototype._YconvertDOMtoCanvas = function(y) { + return (y - this.translation.y) / this.scale; }; - module.exports = ItemRange; - - -/***/ }, -/* 32 */ -/***/ function(module, exports, __webpack_require__) { - - var Hammer = __webpack_require__(18); - /** - * @constructor Item - * @param {Object} data Object containing (optional) parameters type, - * start, end, content, group, className. - * @param {{toScreen: function, toTime: function}} conversion - * Conversion functions from time to screen and vice versa - * @param {Object} options Configuration options - * // TODO: describe available options + * Convert the Y coordinate in canvas-space (the simulation sandbox, which the camera looks upon) to + * the Y coordinate in DOM-space (coordinate point in browser relative to the container div) + * @param {number} y + * @returns {number} + * @private */ - function Item (data, conversion, options) { - this.id = null; - this.parent = null; - this.data = data; - this.dom = null; - this.conversion = conversion || {}; - this.options = options || {}; - - this.selected = false; - this.displayed = false; - this.dirty = true; + Network.prototype._YconvertCanvasToDOM = function(y) { + return y * this.scale + this.translation.y ; + }; - this.top = null; - this.left = null; - this.width = null; - this.height = null; - } /** - * Select current item + * + * @param {object} pos = {x: number, y: number} + * @returns {{x: number, y: number}} + * @constructor */ - Item.prototype.select = function() { - this.selected = true; - if (this.displayed) this.redraw(); - }; + Network.prototype.canvasToDOM = function(pos) { + return {x:this._XconvertCanvasToDOM(pos.x),y:this._YconvertCanvasToDOM(pos.y)}; + } /** - * Unselect current item + * + * @param {object} pos = {x: number, y: number} + * @returns {{x: number, y: number}} + * @constructor */ - Item.prototype.unselect = function() { - this.selected = false; - if (this.displayed) this.redraw(); - }; + Network.prototype.DOMtoCanvas = function(pos) { + return {x:this._XconvertDOMtoCanvas(pos.x),y:this._YconvertDOMtoCanvas(pos.y)}; + } /** - * Set a parent for the item - * @param {ItemSet | Group} parent + * Redraw all nodes + * The 2d context of a HTML canvas can be retrieved by canvas.getContext('2d'); + * @param {CanvasRenderingContext2D} ctx + * @param {Boolean} [alwaysShow] + * @private */ - Item.prototype.setParent = function(parent) { - if (this.displayed) { - this.hide(); - this.parent = parent; - if (this.parent) { - this.show(); + Network.prototype._drawNodes = function(ctx,alwaysShow) { + if (alwaysShow === undefined) { + alwaysShow = false; + } + + // first draw the unselected nodes + var nodes = this.nodes; + var selected = []; + + for (var id in nodes) { + if (nodes.hasOwnProperty(id)) { + nodes[id].setScaleAndPos(this.scale,this.canvasTopLeft,this.canvasBottomRight); + if (nodes[id].isSelected()) { + selected.push(id); + } + else { + if (nodes[id].inArea() || alwaysShow) { + nodes[id].draw(ctx); + } + } } } - else { - this.parent = parent; + + // draw the selected nodes on top + for (var s = 0, sMax = selected.length; s < sMax; s++) { + if (nodes[selected[s]].inArea() || alwaysShow) { + nodes[selected[s]].draw(ctx); + } } }; /** - * Check whether this item is visible inside given range - * @returns {{start: Number, end: Number}} range with a timestamp for start and end - * @returns {boolean} True if visible + * Redraw all edges + * The 2d context of a HTML canvas can be retrieved by canvas.getContext('2d'); + * @param {CanvasRenderingContext2D} ctx + * @private */ - Item.prototype.isVisible = function(range) { - // Should be implemented by Item implementations - return false; + Network.prototype._drawEdges = function(ctx) { + var edges = this.edges; + for (var id in edges) { + if (edges.hasOwnProperty(id)) { + var edge = edges[id]; + edge.setScale(this.scale); + if (edge.connected) { + edges[id].draw(ctx); + } + } + } }; /** - * Show the Item in the DOM (when not already visible) - * @return {Boolean} changed + * Redraw all edges + * The 2d context of a HTML canvas can be retrieved by canvas.getContext('2d'); + * @param {CanvasRenderingContext2D} ctx + * @private */ - Item.prototype.show = function() { - return false; + Network.prototype._drawControlNodes = function(ctx) { + var edges = this.edges; + for (var id in edges) { + if (edges.hasOwnProperty(id)) { + edges[id]._drawControlNodes(ctx); + } + } }; /** - * Hide the Item from the DOM (when visible) - * @return {Boolean} changed + * Find a stable position for all nodes + * @private */ - Item.prototype.hide = function() { - return false; + Network.prototype._stabilize = function() { + if (this.constants.freezeForStabilization == true) { + this._freezeDefinedNodes(); + } + + // find stable position + var count = 0; + while (this.moving && count < this.constants.stabilizationIterations) { + this._physicsTick(); + count++; + } + this.zoomExtent(false,true); + if (this.constants.freezeForStabilization == true) { + this._restoreFrozenNodes(); + } + this.emit("stabilized",{iterations:count}); }; /** - * Repaint the item + * 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 */ - Item.prototype.redraw = function() { - // should be implemented by the item + Network.prototype._freezeDefinedNodes = function() { + var nodes = this.nodes; + for (var id in nodes) { + if (nodes.hasOwnProperty(id)) { + if (nodes[id].x != null && nodes[id].y != null) { + nodes[id].fixedData.x = nodes[id].xFixed; + nodes[id].fixedData.y = nodes[id].yFixed; + nodes[id].xFixed = true; + nodes[id].yFixed = true; + } + } + } }; /** - * Reposition the Item horizontally + * Unfreezes the nodes that have been frozen by _freezeDefinedNodes. + * + * @private */ - Item.prototype.repositionX = function() { - // should be implemented by the item + Network.prototype._restoreFrozenNodes = function() { + var nodes = this.nodes; + for (var id in nodes) { + if (nodes.hasOwnProperty(id)) { + if (nodes[id].fixedData.x != null) { + nodes[id].xFixed = nodes[id].fixedData.x; + nodes[id].yFixed = nodes[id].fixedData.y; + } + } + } }; + /** - * Reposition the Item vertically - */ - Item.prototype.repositionY = function() { - // should be implemented by the item - }; - - /** - * Repaint a delete button on the top right of the item when the item is selected - * @param {HTMLElement} anchor - * @protected + * Check if any of the nodes is still moving + * @param {number} vmin the minimum velocity considered as 'moving' + * @return {boolean} true if moving, false if non of the nodes is moving + * @private */ - Item.prototype._repaintDeleteButton = function (anchor) { - if (this.selected && this.options.editable.remove && !this.dom.deleteButton) { - // create and show button - var me = this; - - var deleteButton = document.createElement('div'); - deleteButton.className = 'delete'; - deleteButton.title = 'Delete this item'; - - Hammer(deleteButton, { - preventDefault: true - }).on('tap', function (event) { - me.parent.removeFromDataSet(me); - event.stopPropagation(); - }); - - anchor.appendChild(deleteButton); - this.dom.deleteButton = deleteButton; - } - else if (!this.selected && this.dom.deleteButton) { - // remove button - if (this.dom.deleteButton.parentNode) { - this.dom.deleteButton.parentNode.removeChild(this.dom.deleteButton); + Network.prototype._isMoving = function(vmin) { + var nodes = this.nodes; + for (var id in nodes) { + if (nodes.hasOwnProperty(id) && nodes[id].isMoving(vmin)) { + return true; } - this.dom.deleteButton = null; } + return false; }; - module.exports = Item; - - -/***/ }, -/* 33 */ -/***/ function(module, exports, __webpack_require__) { - - var Item = __webpack_require__(32); /** - * @constructor ItemBox - * @extends Item - * @param {Object} data Object containing parameters start - * content, className. - * @param {{toScreen: function, toTime: function}} conversion - * Conversion functions from time to screen and vice versa - * @param {Object} [options] Configuration options - * // TODO: describe available options + * /** + * Perform one discrete step for all nodes + * + * @private */ - function ItemBox (data, conversion, options) { - this.props = { - dot: { - width: 0, - height: 0 - }, - line: { - width: 0, - height: 0 - } - }; + Network.prototype._discreteStepNodes = function(checkMovement) { + var interval = this.physicsDiscreteStepsize; + var nodes = this.nodes; + var nodeId; + var nodesPresent = false; - // validate data - if (data) { - if (data.start == undefined) { - throw new Error('Property "start" missing in item ' + data); + if (this.constants.maxVelocity > 0) { + for (nodeId in nodes) { + if (nodes.hasOwnProperty(nodeId)) { + nodes[nodeId].discreteStepLimited(interval, this.constants.maxVelocity); + nodesPresent = true; + } + } + } + else { + for (nodeId in nodes) { + if (nodes.hasOwnProperty(nodeId)) { + nodes[nodeId].discreteStep(interval); + nodesPresent = true; + } } } - Item.call(this, data, conversion, options); - } + if (nodesPresent == true && (checkMovement === undefined || checkMovement == true)) { + var vminCorrected = this.constants.minVelocity / Math.max(this.scale,0.05); + if (vminCorrected > 0.5*this.constants.maxVelocity) { + this.moving = true; + } + else { + this.moving = this._isMoving(vminCorrected); + if (this.moving == false) { + this.emit("stabilized",{iterations:null}); + } + this.moving = this.moving || this.configurePhysics; - ItemBox.prototype = new Item (null, null, null); + } + } + }; /** - * Check whether this item is visible inside given range - * @returns {{start: Number, end: Number}} range with a timestamp for start and end - * @returns {boolean} True if visible + * A single simulation step (or "tick") in the physics simulation + * + * @private */ - ItemBox.prototype.isVisible = function(range) { - // determine visibility - // TODO: account for the real width of the item. Right now we just add 1/4 to the window - var interval = (range.end - range.start) / 4; - return (this.data.start > range.start - interval) && (this.data.start < range.end + interval); + Network.prototype._physicsTick = function() { + if (!this.freezeSimulation) { + if (this.moving == true) { + this._doInAllActiveSectors("_initializeForceCalculation"); + this._doInAllActiveSectors("_discreteStepNodes"); + if (this.constants.smoothCurves.enabled == true && this.constants.smoothCurves.dynamic == true) { + this._doInSupportSector("_discreteStepNodes", false); + } + this._findCenter(this._getRange()) + } + } }; + /** - * Repaint the item + * This function runs one step of the animation. It calls an x amount of physics ticks and one render tick. + * It reschedules itself at the beginning of the function + * + * @private */ - ItemBox.prototype.redraw = function() { - var dom = this.dom; - if (!dom) { - // create DOM - this.dom = {}; - dom = this.dom; + Network.prototype._animationStep = function() { + // reset the timer so a new scheduled animation step can be set + this.timer = undefined; + // handle the keyboad movement + this._handleNavigation(); - // create main box - dom.box = document.createElement('DIV'); + // this schedules a new animation step + this.start(); - // contents box (inside the background box). used for making margins - dom.content = document.createElement('DIV'); - dom.content.className = 'content'; - dom.box.appendChild(dom.content); + // start the physics simulation + var calculationTime = Date.now(); + var maxSteps = 1; + this._physicsTick(); + var timeRequired = Date.now() - calculationTime; + while (timeRequired < 0.9*(this.renderTimestep - this.renderTime) && maxSteps < this.maxPhysicsTicksPerRender) { + this._physicsTick(); + timeRequired = Date.now() - calculationTime; + maxSteps++; + } + // start the rendering process + var renderTime = Date.now(); + this._redraw(); + this.renderTime = Date.now() - renderTime; - // line to axis - dom.line = document.createElement('DIV'); - dom.line.className = 'line'; + }; - // dot on axis - dom.dot = document.createElement('DIV'); - dom.dot.className = 'dot'; + if (typeof window !== 'undefined') { + window.requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || + window.webkitRequestAnimationFrame || window.msRequestAnimationFrame; + } - // attach this item as attribute - dom.box['timeline-item'] = this; - } + /** + * Schedule a animation step with the refreshrate interval. + */ + Network.prototype.start = function() { + if (this.moving == true || this.xIncrement != 0 || this.yIncrement != 0 || this.zoomIncrement != 0) { + if (!this.timer) { + var ua = navigator.userAgent.toLowerCase(); - // append DOM to parent DOM - if (!this.parent) { - throw new Error('Cannot redraw item: no parent attached'); - } - if (!dom.box.parentNode) { - var foreground = this.parent.dom.foreground; - if (!foreground) throw new Error('Cannot redraw time axis: parent has no foreground container element'); - foreground.appendChild(dom.box); - } - if (!dom.line.parentNode) { - var background = this.parent.dom.background; - if (!background) throw new Error('Cannot redraw time axis: parent has no background container element'); - background.appendChild(dom.line); - } - if (!dom.dot.parentNode) { - var axis = this.parent.dom.axis; - if (!background) throw new Error('Cannot redraw time axis: parent has no axis container element'); - axis.appendChild(dom.dot); - } - this.displayed = true; + var requiresTimeout = false; + if (ua.indexOf('msie 9.0') != -1) { // IE 9 + requiresTimeout = true; + } + else if (ua.indexOf('safari') != -1) { // safari + if (ua.indexOf('chrome') <= -1) { + requiresTimeout = true; + } + } - // update contents - if (this.data.content != this.content) { - this.content = this.data.content; - if (this.content instanceof Element) { - dom.content.innerHTML = ''; - dom.content.appendChild(this.content); - } - else if (this.data.content != undefined) { - dom.content.innerHTML = this.content; - } - else { - throw new Error('Property "content" missing in item ' + this.data.id); + if (requiresTimeout == true) { + this.timer = window.setTimeout(this._animationStep.bind(this), this.renderTimestep); // wait this.renderTimeStep milliseconds and perform the animation step function + } + else{ + this.timer = window.requestAnimationFrame(this._animationStep.bind(this), this.renderTimestep); // wait this.renderTimeStep milliseconds and perform the animation step function + } } - - this.dirty = true; } - - // update title - if (this.data.title != this.title) { - dom.box.title = this.data.title; - this.title = this.data.title; + else { + this._redraw(); } + }; - // update class - var className = (this.data.className? ' ' + this.data.className : '') + - (this.selected ? ' selected' : ''); - if (this.className != className) { - this.className = className; - dom.box.className = 'item box' + className; - dom.line.className = 'item line' + className; - dom.dot.className = 'item dot' + className; - this.dirty = true; + /** + * Move the network according to the keyboard presses. + * + * @private + */ + Network.prototype._handleNavigation = function() { + if (this.xIncrement != 0 || this.yIncrement != 0) { + var translation = this._getTranslation(); + this._setTranslation(translation.x+this.xIncrement, translation.y+this.yIncrement); } - - // recalculate size - if (this.dirty) { - this.props.dot.height = dom.dot.offsetHeight; - this.props.dot.width = dom.dot.offsetWidth; - this.props.line.width = dom.line.offsetWidth; - this.width = dom.box.offsetWidth; - this.height = dom.box.offsetHeight; - - this.dirty = false; + if (this.zoomIncrement != 0) { + var center = { + x: this.frame.canvas.clientWidth / 2, + y: this.frame.canvas.clientHeight / 2 + }; + this._zoom(this.scale*(1 + this.zoomIncrement), center); } - - this._repaintDeleteButton(dom.box); }; + /** - * Show the item in the DOM (when not already displayed). The items DOM will - * be created when needed. + * Freeze the _animationStep */ - ItemBox.prototype.show = function() { - if (!this.displayed) { - this.redraw(); + Network.prototype.toggleFreeze = function() { + if (this.freezeSimulation == false) { + this.freezeSimulation = true; + } + else { + this.freezeSimulation = false; + this.start(); } }; + /** - * Hide the item from the DOM (when visible) + * This function cleans the support nodes if they are not needed and adds them when they are. + * + * @param {boolean} [disableStart] + * @private */ - ItemBox.prototype.hide = function() { - if (this.displayed) { - var dom = this.dom; - - if (dom.box.parentNode) dom.box.parentNode.removeChild(dom.box); - if (dom.line.parentNode) dom.line.parentNode.removeChild(dom.line); - if (dom.dot.parentNode) dom.dot.parentNode.removeChild(dom.dot); + Network.prototype._configureSmoothCurves = function(disableStart) { + if (disableStart === undefined) { + disableStart = true; + } + if (this.constants.smoothCurves.enabled == true && this.constants.smoothCurves.dynamic == true) { + this._createBezierNodes(); + // cleanup unused support nodes + for (var nodeId in this.sectors['support']['nodes']) { + if (this.sectors['support']['nodes'].hasOwnProperty(nodeId)) { + if (this.edges[this.sectors['support']['nodes'][nodeId].parentEdgeId] === undefined) { + delete this.sectors['support']['nodes'][nodeId]; + } + } + } + } + else { + // delete the support nodes + this.sectors['support']['nodes'] = {}; + for (var edgeId in this.edges) { + if (this.edges.hasOwnProperty(edgeId)) { + this.edges[edgeId].via = null; + } + } + } - this.top = null; - this.left = null; - this.displayed = false; + this._updateCalculationNodes(); + if (!disableStart) { + this.moving = true; + this.start(); } }; + /** - * Reposition the item horizontally - * @Override + * Bezier curves require an anchor point to calculate the smooth flow. These points are nodes. These nodes are invisible but + * are used for the force calculation. + * + * @private */ - ItemBox.prototype.repositionX = function() { - var start = this.conversion.toScreen(this.data.start), - align = this.options.align, - left, - box = this.dom.box, - line = this.dom.line, - dot = this.dom.dot; - - // calculate left position of the box - if (align == 'right') { - this.left = start - this.width; - } - else if (align == 'left') { - this.left = start; - } - else { - // default or 'center' - this.left = start - this.width / 2; + Network.prototype._createBezierNodes = function() { + if (this.constants.smoothCurves.enabled == true && this.constants.smoothCurves.dynamic == true) { + for (var edgeId in this.edges) { + if (this.edges.hasOwnProperty(edgeId)) { + var edge = this.edges[edgeId]; + if (edge.via == null) { + var nodeId = "edgeId:".concat(edge.id); + this.sectors['support']['nodes'][nodeId] = new Node( + {id:nodeId, + mass:1, + shape:'circle', + image:"", + internalMultiplier:1 + },{},{},this.constants); + edge.via = this.sectors['support']['nodes'][nodeId]; + edge.via.parentEdgeId = edge.id; + edge.positionBezierNode(); + } + } + } } + }; - // reposition box - box.style.left = this.left + 'px'; - - // reposition line - line.style.left = (start - this.props.line.width / 2) + 'px'; + /** + * load the functions that load the mixins into the prototype. + * + * @private + */ + Network.prototype._initializeMixinLoaders = function () { + for (var mixin in MixinLoader) { + if (MixinLoader.hasOwnProperty(mixin)) { + Network.prototype[mixin] = MixinLoader[mixin]; + } + } + }; - // reposition dot - dot.style.left = (start - this.props.dot.width / 2) + 'px'; + /** + * Load the XY positions of the nodes into the dataset. + */ + Network.prototype.storePosition = function() { + var dataArray = []; + for (var nodeId in this.nodes) { + if (this.nodes.hasOwnProperty(nodeId)) { + var node = this.nodes[nodeId]; + var allowedToMoveX = !this.nodes.xFixed; + var allowedToMoveY = !this.nodes.yFixed; + if (this.nodesData._data[nodeId].x != Math.round(node.x) || this.nodesData._data[nodeId].y != Math.round(node.y)) { + dataArray.push({id:nodeId,x:Math.round(node.x),y:Math.round(node.y),allowedToMoveX:allowedToMoveX,allowedToMoveY:allowedToMoveY}); + } + } + } + this.nodesData.update(dataArray); }; + /** - * Reposition the item vertically - * @Override + * Center a node in view. + * + * @param {Number} nodeId + * @param {Number} [zoomLevel] */ - ItemBox.prototype.repositionY = function() { - var orientation = this.options.orientation, - box = this.dom.box, - line = this.dom.line, - dot = this.dom.dot; + Network.prototype.focusOnNode = function (nodeId, zoomLevel) { + if (this.nodes.hasOwnProperty(nodeId)) { + if (zoomLevel === undefined) { + zoomLevel = this._getScale(); + } + var nodePosition= {x: this.nodes[nodeId].x, y: this.nodes[nodeId].y}; - if (orientation == 'top') { - box.style.top = (this.top || 0) + 'px'; + var requiredScale = zoomLevel; + this._setScale(requiredScale); - line.style.top = '0'; - line.style.height = (this.parent.top + this.top + 1) + 'px'; - line.style.bottom = ''; - } - else { // orientation 'bottom' - var itemSetHeight = this.parent.itemSet.props.height; // TODO: this is nasty - var lineHeight = itemSetHeight - this.parent.top - this.parent.height + this.top; + var canvasCenter = this.DOMtoCanvas({x:0.5 * this.frame.canvas.width,y:0.5 * this.frame.canvas.height}); + var translation = this._getTranslation(); - box.style.top = (this.parent.height - this.top - this.height || 0) + 'px'; - line.style.top = (itemSetHeight - lineHeight) + 'px'; - line.style.bottom = '0'; - } + var distanceFromCenter = {x:canvasCenter.x - nodePosition.x, + y:canvasCenter.y - nodePosition.y}; - dot.style.top = (-this.props.dot.height / 2) + 'px'; + this._setTranslation(translation.x + requiredScale * distanceFromCenter.x, + translation.y + requiredScale * distanceFromCenter.y); + this.redraw(); + } + else { + console.log("This nodeId cannot be found.") + } }; - module.exports = ItemBox; + module.exports = Network; /***/ }, -/* 34 */ +/* 33 */ /***/ function(module, exports, __webpack_require__) { - var Item = __webpack_require__(32); + var util = __webpack_require__(1); + var Node = __webpack_require__(36); /** - * @constructor ItemPoint - * @extends Item - * @param {Object} data Object containing parameters start - * content, className. - * @param {{toScreen: function, toTime: function}} conversion - * Conversion functions from time to screen and vice versa - * @param {Object} [options] Configuration options - * // TODO: describe available options + * @class Edge + * + * A edge connects two nodes + * @param {Object} properties Object with properties. Must contain + * At least properties from and to. + * Available properties: from (number), + * to (number), label (string, color (string), + * width (number), style (string), + * length (number), title (string) + * @param {Network} network A Network object, used to find and edge to + * nodes. + * @param {Object} constants An object with default values for + * example for the color */ - function ItemPoint (data, conversion, options) { - this.props = { - dot: { - top: 0, - width: 0, - height: 0 - }, - content: { - height: 0, - marginLeft: 0 - } - }; - - // validate data - if (data) { - if (data.start == undefined) { - throw new Error('Property "start" missing in item ' + data); - } - } - - Item.call(this, data, conversion, options); - } + function Edge (properties, network, networkConstants) { + if (!network) { + throw "No network provided"; + } + var fields = ['edges','physics']; + var constants = util.selectiveBridgeObject(fields,networkConstants); + this.options = constants.edges; + this.physics = constants.physics; + this.options['smoothCurves'] = networkConstants['smoothCurves']; - ItemPoint.prototype = new Item (null, null, null); - /** - * Check whether this item is visible inside given range - * @returns {{start: Number, end: Number}} range with a timestamp for start and end - * @returns {boolean} True if visible - */ - ItemPoint.prototype.isVisible = function(range) { - // determine visibility - // TODO: account for the real width of the item. Right now we just add 1/4 to the window - var interval = (range.end - range.start) / 4; - return (this.data.start > range.start - interval) && (this.data.start < range.end + interval); - }; + this.network = network; - /** - * Repaint the item - */ - ItemPoint.prototype.redraw = function() { - var dom = this.dom; - if (!dom) { - // create DOM - this.dom = {}; - dom = this.dom; + // initialize variables + this.id = undefined; + this.fromId = undefined; + this.toId = undefined; + this.title = undefined; + this.widthSelected = this.options.width * this.options.widthSelectionMultiplier; + this.value = undefined; + this.selected = false; + this.hover = false; - // background box - dom.point = document.createElement('div'); - // className is updated in redraw() + this.from = null; // a node + this.to = null; // a node + this.via = null; // a temp node - // contents box, right from the dot - dom.content = document.createElement('div'); - dom.content.className = 'content'; - dom.point.appendChild(dom.content); + // we use this to be able to reconnect the edge to a cluster if its node is put into a cluster + // by storing the original information we can revert to the original connection when the cluser is opened. + this.originalFromId = []; + this.originalToId = []; - // dot at start - dom.dot = document.createElement('div'); - dom.point.appendChild(dom.dot); + this.connected = false; - // attach this item as attribute - dom.point['timeline-item'] = this; - } + this.widthFixed = false; + this.lengthFixed = false; - // append DOM to parent DOM - if (!this.parent) { - throw new Error('Cannot redraw item: no parent attached'); - } - if (!dom.point.parentNode) { - var foreground = this.parent.dom.foreground; - if (!foreground) { - throw new Error('Cannot redraw time axis: parent has no foreground container element'); - } - foreground.appendChild(dom.point); - } - this.displayed = true; + this.setProperties(properties); - // update contents - if (this.data.content != this.content) { - this.content = this.data.content; - if (this.content instanceof Element) { - dom.content.innerHTML = ''; - dom.content.appendChild(this.content); - } - else if (this.data.content != undefined) { - dom.content.innerHTML = this.content; - } - else { - throw new Error('Property "content" missing in item ' + this.data.id); - } + this.controlNodesEnabled = false; + this.controlNodes = {from:null, to:null, positions:{}}; + this.connectedNode = null; + } - this.dirty = true; + /** + * Set or overwrite properties for the edge + * @param {Object} properties an object with properties + * @param {Object} constants and object with default, global properties + */ + Edge.prototype.setProperties = function(properties) { + if (!properties) { + return; } - // update title - if (this.data.title != this.title) { - dom.point.title = this.data.title; - this.title = this.data.title; - } + var fields = ['style','fontSize','fontFace','fontColor','fontFill','width', + 'widthSelectionMultiplier','hoverWidth','arrowScaleFactor','dash' + ]; + util.selectiveDeepExtend(fields, this.options, properties); - // update class - var className = (this.data.className? ' ' + this.data.className : '') + - (this.selected ? ' selected' : ''); - if (this.className != className) { - this.className = className; - dom.point.className = 'item point' + className; - dom.dot.className = 'item dot' + className; + if (properties.from !== undefined) {this.fromId = properties.from;} + if (properties.to !== undefined) {this.toId = properties.to;} - this.dirty = true; - } + if (properties.id !== undefined) {this.id = properties.id;} + if (properties.label !== undefined) {this.label = properties.label;} - // recalculate size - if (this.dirty) { - this.width = dom.point.offsetWidth; - this.height = dom.point.offsetHeight; - this.props.dot.width = dom.dot.offsetWidth; - this.props.dot.height = dom.dot.offsetHeight; - this.props.content.height = dom.content.offsetHeight; + if (properties.title !== undefined) {this.title = properties.title;} + if (properties.value !== undefined) {this.value = properties.value;} + if (properties.length !== undefined) {this.physics.springLength = properties.length;} - // resize contents - dom.content.style.marginLeft = 2 * this.props.dot.width + 'px'; - //dom.content.style.marginRight = ... + 'px'; // TODO: margin right + // scale the arrow + if (properties.arrowScaleFactor !== undefined) {this.options.arrowScaleFactor = properties.arrowScaleFactor;} - dom.dot.style.top = ((this.height - this.props.dot.height) / 2) + 'px'; - dom.dot.style.left = (this.props.dot.width / 2) + 'px'; + if (properties.inheritColor !== undefined) {this.options.inheritColor = properties.inheritColor;} - this.dirty = false; + if (properties.color !== undefined) { + this.options.inheritColor = false; + if (util.isString(properties.color)) { + this.options.color.color = properties.color; + this.options.color.highlight = properties.color; + } + else { + if (properties.color.color !== undefined) {this.options.color.color = properties.color.color;} + if (properties.color.highlight !== undefined) {this.options.color.highlight = properties.color.highlight;} + if (properties.color.hover !== undefined) {this.options.color.hover = properties.color.hover;} + } } - this._repaintDeleteButton(dom.point); - }; + // A node is connected when it has a from and to node. + this.connect(); - /** - * Show the item in the DOM (when not already visible). The items DOM will - * be created when needed. - */ - ItemPoint.prototype.show = function() { - if (!this.displayed) { - this.redraw(); + this.widthFixed = this.widthFixed || (properties.width !== undefined); + this.lengthFixed = this.lengthFixed || (properties.length !== undefined); + + this.widthSelected = this.options.width* this.options.widthSelectionMultiplier; + + // set draw method based on style + switch (this.options.style) { + case 'line': this.draw = this._drawLine; break; + case 'arrow': this.draw = this._drawArrow; break; + case 'arrow-center': this.draw = this._drawArrowCenter; break; + case 'dash-line': this.draw = this._drawDashLine; break; + default: this.draw = this._drawLine; break; } }; /** - * Hide the item from the DOM (when visible) + * Connect an edge to its nodes */ - ItemPoint.prototype.hide = function() { - if (this.displayed) { - if (this.dom.point.parentNode) { - this.dom.point.parentNode.removeChild(this.dom.point); - } + Edge.prototype.connect = function () { + this.disconnect(); - this.top = null; - this.left = null; + this.from = this.network.nodes[this.fromId] || null; + this.to = this.network.nodes[this.toId] || null; + this.connected = (this.from && this.to); - this.displayed = false; + if (this.connected) { + this.from.attachEdge(this); + this.to.attachEdge(this); + } + else { + if (this.from) { + this.from.detachEdge(this); + } + if (this.to) { + this.to.detachEdge(this); + } } }; /** - * Reposition the item horizontally - * @Override + * Disconnect an edge from its nodes */ - ItemPoint.prototype.repositionX = function() { - var start = this.conversion.toScreen(this.data.start); - - this.left = start - this.props.dot.width; + Edge.prototype.disconnect = function () { + if (this.from) { + this.from.detachEdge(this); + this.from = null; + } + if (this.to) { + this.to.detachEdge(this); + this.to = null; + } - // reposition point - this.dom.point.style.left = this.left + 'px'; + this.connected = false; }; /** - * Reposition the item vertically - * @Override + * get the title of this edge. + * @return {string} title The title of the edge, or undefined when no title + * has been set. */ - ItemPoint.prototype.repositionY = function() { - var orientation = this.options.orientation, - point = this.dom.point; - - if (orientation == 'top') { - point.style.top = this.top + 'px'; - } - else { - point.style.top = (this.parent.height - this.top - this.height) + 'px'; - } + Edge.prototype.getTitle = function() { + return typeof this.title === "function" ? this.title() : this.title; }; - module.exports = ItemPoint; - - -/***/ }, -/* 35 */ -/***/ function(module, exports, __webpack_require__) { - var Emitter = __webpack_require__(10); - var Hammer = __webpack_require__(18); - var util = __webpack_require__(1); - var DataSet = __webpack_require__(7); - var DataView = __webpack_require__(8); - var Range = __webpack_require__(20); - var Core = __webpack_require__(23); - var TimeAxis = __webpack_require__(24); - var CurrentTime = __webpack_require__(26); - var CustomTime = __webpack_require__(27); - var LineGraph = __webpack_require__(36); + /** + * Retrieve the value of the edge. Can be undefined + * @return {Number} value + */ + Edge.prototype.getValue = function() { + return this.value; + }; /** - * Create a timeline visualization - * @param {HTMLElement} container - * @param {vis.DataSet | Array | google.visualization.DataTable} [items] - * @param {Object} [options] See Graph2d.setOptions for the available options. - * @constructor + * Adjust the value range of the edge. The edge will adjust it's width + * based on its value. + * @param {Number} min + * @param {Number} max */ - function Graph2d (container, items, options, groups) { - for (var coreProp in Core.prototype) { - if (Core.prototype.hasOwnProperty(coreProp) && !Graph2d.prototype.hasOwnProperty(coreProp)) { - Graph2d.prototype[coreProp] = Core.prototype[coreProp]; - } + Edge.prototype.setValueRange = function(min, max) { + if (!this.widthFixed && this.value !== undefined) { + var scale = (this.options.widthMax - this.options.widthMin) / (max - min); + this.options.width= (this.value - min) * scale + this.options.widthMin; + this.widthSelected = this.options.width* this.options.widthSelectionMultiplier; } + }; - var me = this; - this.defaultOptions = { - start: null, - end: null, - - autoResize: true, - - orientation: 'bottom', - width: null, - height: null, - maxHeight: null, - minHeight: null - }; - this.options = util.deepExtend({}, this.defaultOptions); - - // Create the DOM, props, and emitter - this._create(container); - - // all components listed here will be repainted automatically - this.components = []; - - this.body = { - dom: this.dom, - domProps: this.props, - emitter: { - on: this.on.bind(this), - off: this.off.bind(this), - emit: this.emit.bind(this) - }, - util: { - snap: null, // will be specified after TimeAxis is created - toScreen: me._toScreen.bind(me), - toGlobalScreen: me._toGlobalScreen.bind(me), // this refers to the root.width - toTime: me._toTime.bind(me), - toGlobalTime : me._toGlobalTime.bind(me) - } - }; - - // range - this.range = new Range(this.body); - this.components.push(this.range); - this.body.range = this.range; - - // time axis - this.timeAxis = new TimeAxis(this.body); - this.components.push(this.timeAxis); - this.body.util.snap = this.timeAxis.snap.bind(this.timeAxis); - - // current time bar - this.currentTime = new CurrentTime(this.body); - this.components.push(this.currentTime); - - // custom time bar - // Note: time bar will be attached in this.setOptions when selected - this.customTime = new CustomTime(this.body); - this.components.push(this.customTime); + /** + * Redraw a edge + * Draw this edge in the given canvas + * The 2d context of a HTML canvas can be retrieved by canvas.getContext("2d"); + * @param {CanvasRenderingContext2D} ctx + */ + Edge.prototype.draw = function(ctx) { + throw "Method draw not initialized in edge"; + }; - // item set - this.linegraph = new LineGraph(this.body); - this.components.push(this.linegraph); + /** + * Check if this object is overlapping with the provided object + * @param {Object} obj an object with parameters left, top + * @return {boolean} True if location is located on the edge + */ + Edge.prototype.isOverlappingWith = function(obj) { + if (this.connected) { + var distMax = 10; + var xFrom = this.from.x; + var yFrom = this.from.y; + var xTo = this.to.x; + var yTo = this.to.y; + var xObj = obj.left; + var yObj = obj.top; - this.itemsData = null; // DataSet - this.groupsData = null; // DataSet + var dist = this._getDistanceToEdge(xFrom, yFrom, xTo, yTo, xObj, yObj); - // apply options - if (options) { - this.setOptions(options); + return (dist < distMax); } - - // IMPORTANT: THIS HAPPENS BEFORE SET ITEMS! - if (groups) { - this.setGroups(groups); + else { + return false } + }; - // create itemset - if (items) { - this.setItems(items); + Edge.prototype._getColor = function() { + var colorObj = this.options.color; + if (this.options.inheritColor == "to") { + colorObj = { + highlight: this.to.options.color.highlight.border, + hover: this.to.options.color.hover.border, + color: this.to.options.color.border + }; } - else { - this.redraw(); + else if (this.options.inheritColor == "from" || this.options.inheritColor == true) { + colorObj = { + highlight: this.from.options.color.highlight.border, + hover: this.from.options.color.hover.border, + color: this.from.options.color.border + }; } + + if (this.selected == true) {return colorObj.highlight;} + else if (this.hover == true) {return colorObj.hover;} + else {return colorObj.color;} } + /** - * Set options. Options will be passed to all components loaded in the Graph2d. - * @param {Object} [options] - * {String} orientation - * Vertical orientation for the Graph2d, - * can be 'bottom' (default) or 'top'. - * {String | Number} width - * Width for the timeline, a number in pixels or - * a css string like '1000px' or '75%'. '100%' by default. - * {String | Number} height - * Fixed height for the Graph2d, a number in pixels or - * a css string like '400px' or '75%'. If undefined, - * The Graph2d will automatically size such that - * its contents fit. - * {String | Number} minHeight - * Minimum height for the Graph2d, a number in pixels or - * a css string like '400px' or '75%'. - * {String | Number} maxHeight - * Maximum height for the Graph2d, a number in pixels or - * a css string like '400px' or '75%'. - * {Number | Date | String} start - * Start date for the visible window - * {Number | Date | String} end - * End date for the visible window + * Redraw a edge as a line + * Draw this edge in the given canvas + * The 2d context of a HTML canvas can be retrieved by canvas.getContext("2d"); + * @param {CanvasRenderingContext2D} ctx + * @private */ - Graph2d.prototype.setOptions = function (options) { - if (options) { - // copy the known options - var fields = ['width', 'height', 'minHeight', 'maxHeight', 'autoResize', 'start', 'end', 'orientation']; - util.selectiveExtend(fields, this.options, options); - - // enable/disable autoResize - this._initAutoResize(); - } + Edge.prototype._drawLine = function(ctx) { + // set style + ctx.strokeStyle = this._getColor(); + ctx.lineWidth = this._getLineWidth(); - // propagate options to all components - this.components.forEach(function (component) { - component.setOptions(options); - }); + if (this.from != this.to) { + // draw line + var via = this._line(ctx); - // TODO: remove deprecation error one day (deprecated since version 0.8.0) - if (options && options.order) { - throw new Error('Option order is deprecated. There is no replacement for this feature.'); + // draw label + var point; + if (this.label) { + if (this.options.smoothCurves.enabled == true && via != null) { + var midpointX = 0.5*(0.5*(this.from.x + via.x) + 0.5*(this.to.x + via.x)); + var midpointY = 0.5*(0.5*(this.from.y + via.y) + 0.5*(this.to.y + via.y)); + point = {x:midpointX, y:midpointY}; + } + else { + point = this._pointOnLine(0.5); + } + this._label(ctx, this.label, point.x, point.y); + } + } + else { + var x, y; + var radius = this.physics.springLength / 4; + var node = this.from; + if (!node.width) { + node.resize(ctx); + } + if (node.width > node.height) { + x = node.x + node.width / 2; + y = node.y - radius; + } + else { + x = node.x + radius; + y = node.y - node.height / 2; + } + this._circle(ctx, x, y, radius); + point = this._pointOnCircle(x, y, radius, 0.5); + this._label(ctx, this.label, point.x, point.y); } - - // redraw everything - this.redraw(); }; - /** - * Set items - * @param {vis.DataSet | Array | google.visualization.DataTable | null} items + * Get the line width of the edge. Depends on width and whether one of the + * connected nodes is selected. + * @return {Number} width + * @private */ - Graph2d.prototype.setItems = function(items) { - var initialLoad = (this.itemsData == null); - - // convert to type DataSet when needed - var newDataSet; - if (!items) { - newDataSet = null; - } - else if (items instanceof DataSet || items instanceof DataView) { - newDataSet = items; + Edge.prototype._getLineWidth = function() { + if (this.selected == true) { + return Math.min(this.widthSelected, this.options.widthMax)*this.networkScaleInv; } else { - // turn an array into a dataset - newDataSet = new DataSet(items, { - type: { - start: 'Date', - end: 'Date' - } - }); - } - - // set items - this.itemsData = newDataSet; - this.linegraph && this.linegraph.setItems(newDataSet); - - if (initialLoad && ('start' in this.options || 'end' in this.options)) { - this.fit(); - - var start = ('start' in this.options) ? util.convert(this.options.start, 'Date') : null; - var end = ('end' in this.options) ? util.convert(this.options.end, 'Date') : null; - - this.setWindow(start, end); + if (this.hover == true) { + return Math.min(this.options.hoverWidth, this.options.widthMax)*this.networkScaleInv; + } + else { + return this.options.width*this.networkScaleInv; + } } }; - /** - * Set groups - * @param {vis.DataSet | Array | google.visualization.DataTable} groups - */ - Graph2d.prototype.setGroups = function(groups) { - // convert to type DataSet when needed - var newDataSet; - if (!groups) { - newDataSet = null; + Edge.prototype._getViaCoordinates = function () { + var xVia = null; + var yVia = null; + var factor = this.options.smoothCurves.roundness; + var type = this.options.smoothCurves.type; + + var dx = Math.abs(this.from.x - this.to.x); + var dy = Math.abs(this.from.y - this.to.y); + if (type == 'discrete' || type == 'diagonalCross') { + if (Math.abs(this.from.x - this.to.x) < Math.abs(this.from.y - this.to.y)) { + if (this.from.y > this.to.y) { + if (this.from.x < this.to.x) { + xVia = this.from.x + factor * dy; + yVia = this.from.y - factor * dy; + } + else if (this.from.x > this.to.x) { + xVia = this.from.x - factor * dy; + yVia = this.from.y - factor * dy; + } + } + else if (this.from.y < this.to.y) { + if (this.from.x < this.to.x) { + xVia = this.from.x + factor * dy; + yVia = this.from.y + factor * dy; + } + else if (this.from.x > this.to.x) { + xVia = this.from.x - factor * dy; + yVia = this.from.y + factor * dy; + } + } + if (type == "discrete") { + xVia = dx < factor * dy ? this.from.x : xVia; + } + } + else if (Math.abs(this.from.x - this.to.x) > Math.abs(this.from.y - this.to.y)) { + if (this.from.y > this.to.y) { + if (this.from.x < this.to.x) { + xVia = this.from.x + factor * dx; + yVia = this.from.y - factor * dx; + } + else if (this.from.x > this.to.x) { + xVia = this.from.x - factor * dx; + yVia = this.from.y - factor * dx; + } + } + else if (this.from.y < this.to.y) { + if (this.from.x < this.to.x) { + xVia = this.from.x + factor * dx; + yVia = this.from.y + factor * dx; + } + else if (this.from.x > this.to.x) { + xVia = this.from.x - factor * dx; + yVia = this.from.y + factor * dx; + } + } + if (type == "discrete") { + yVia = dy < factor * dx ? this.from.y : yVia; + } + } } - else if (groups instanceof DataSet || groups instanceof DataView) { - newDataSet = groups; + else if (type == "straightCross") { + if (Math.abs(this.from.x - this.to.x) < Math.abs(this.from.y - this.to.y)) { // up - down + xVia = this.from.x; + if (this.from.y < this.to.y) { + yVia = this.to.y - (1-factor) * dy; + } + else { + yVia = this.to.y + (1-factor) * dy; + } + } + else if (Math.abs(this.from.x - this.to.x) > Math.abs(this.from.y - this.to.y)) { // left - right + if (this.from.x < this.to.x) { + xVia = this.to.x - (1-factor) * dx; + } + else { + xVia = this.to.x + (1-factor) * dx; + } + yVia = this.from.y; + } } - else { - // turn an array into a dataset - newDataSet = new DataSet(groups); + else if (type == 'horizontal') { + if (this.from.x < this.to.x) { + xVia = this.to.x - (1-factor) * dx; + } + else { + xVia = this.to.x + (1-factor) * dx; + } + yVia = this.from.y; } - - this.groupsData = newDataSet; - this.linegraph.setGroups(newDataSet); - }; - - /** - * Returns an object containing an SVG element with the icon of the group (size determined by iconWidth and iconHeight), the label of the group (content) and the yAxisOrientation of the group (left or right). - * @param groupId - * @param width - * @param height - */ - Graph2d.prototype.getLegend = function(groupId, width, height) { - if (width === undefined) {width = 15;} - if (height === undefined) {height = 15;} - if (this.linegraph.groups[groupId] !== undefined) { - return this.linegraph.groups[groupId].getLegend(width,height); + else if (type == 'vertical') { + xVia = this.from.x; + if (this.from.y < this.to.y) { + yVia = this.to.y - (1-factor) * dy; + } + else { + yVia = this.to.y + (1-factor) * dy; + } } - else { - return "cannot find group:" + groupId; + else { // continuous + if (Math.abs(this.from.x - this.to.x) < Math.abs(this.from.y - this.to.y)) { + if (this.from.y > this.to.y) { + if (this.from.x < this.to.x) { + // console.log(1) + xVia = this.from.x + factor * dy; + yVia = this.from.y - factor * dy; + xVia = this.to.x < xVia ? this.to.x : xVia; + } + else if (this.from.x > this.to.x) { + // console.log(2) + xVia = this.from.x - factor * dy; + yVia = this.from.y - factor * dy; + xVia = this.to.x > xVia ? this.to.x :xVia; + } + } + else if (this.from.y < this.to.y) { + if (this.from.x < this.to.x) { + // console.log(3) + xVia = this.from.x + factor * dy; + yVia = this.from.y + factor * dy; + xVia = this.to.x < xVia ? this.to.x : xVia; + } + else if (this.from.x > this.to.x) { + // console.log(4, this.from.x, this.to.x) + xVia = this.from.x - factor * dy; + yVia = this.from.y + factor * dy; + xVia = this.to.x > xVia ? this.to.x : xVia; + } + } + } + else if (Math.abs(this.from.x - this.to.x) > Math.abs(this.from.y - this.to.y)) { + if (this.from.y > this.to.y) { + if (this.from.x < this.to.x) { + // console.log(5) + xVia = this.from.x + factor * dx; + yVia = this.from.y - factor * dx; + yVia = this.to.y > yVia ? this.to.y : yVia; + } + else if (this.from.x > this.to.x) { + // console.log(6) + xVia = this.from.x - factor * dx; + yVia = this.from.y - factor * dx; + yVia = this.to.y > yVia ? this.to.y : yVia; + } + } + else if (this.from.y < this.to.y) { + if (this.from.x < this.to.x) { + // console.log(7) + xVia = this.from.x + factor * dx; + yVia = this.from.y + factor * dx; + yVia = this.to.y < yVia ? this.to.y : yVia; + } + else if (this.from.x > this.to.x) { + // console.log(8) + xVia = this.from.x - factor * dx; + yVia = this.from.y + factor * dx; + yVia = this.to.y < yVia ? this.to.y : yVia; + } + } + } } + + + return {x:xVia, y:yVia}; } /** - * This checks if the visible option of the supplied group (by ID) is true or false. - * @param groupId - * @returns {*} + * Draw a line between two nodes + * @param {CanvasRenderingContext2D} ctx + * @private */ - Graph2d.prototype.isGroupVisible = function(groupId) { - if (this.linegraph.groups[groupId] !== undefined) { - return this.linegraph.groups[groupId].visible; + Edge.prototype._line = function (ctx) { + // draw a straight line + ctx.beginPath(); + ctx.moveTo(this.from.x, this.from.y); + if (this.options.smoothCurves.enabled == true) { + if (this.options.smoothCurves.dynamic == false) { + var via = this._getViaCoordinates(); + if (via.x == null) { + ctx.lineTo(this.to.x, this.to.y); + ctx.stroke(); + return null; + } + else { + // this.via.x = via.x; + // this.via.y = via.y; + ctx.quadraticCurveTo(via.x,via.y,this.to.x, this.to.y); + ctx.stroke(); + return via; + } + } + else { + ctx.quadraticCurveTo(this.via.x,this.via.y,this.to.x, this.to.y); + ctx.stroke(); + return this.via; + } } else { - return false; + ctx.lineTo(this.to.x, this.to.y); + ctx.stroke(); + return null; } - } - + }; /** - * Get the data range of the item set. - * @returns {{min: Date, max: Date}} range A range with a start and end Date. - * When no minimum is found, min==null - * When no maximum is found, max==null - */ - Graph2d.prototype.getItemRange = function() { - var min = null; - var max = null; - - // calculate min from start filed - for (var groupId in this.linegraph.groups) { - if (this.linegraph.groups.hasOwnProperty(groupId)) { - if (this.linegraph.groups[groupId].visible == true) { - for (var i = 0; i < this.linegraph.groups[groupId].itemsData.length; i++) { - var item = this.linegraph.groups[groupId].itemsData[i]; - var value = util.convert(item.x, 'Date').valueOf(); - min = min == null ? value : min > value ? value : min; - max = max == null ? value : max < value ? value : max; - } - } - } - } - - return { - min: (min != null) ? new Date(min) : null, - max: (max != null) ? new Date(max) : null - }; + * Draw a line from a node to itself, a circle + * @param {CanvasRenderingContext2D} ctx + * @param {Number} x + * @param {Number} y + * @param {Number} radius + * @private + */ + Edge.prototype._circle = function (ctx, x, y, radius) { + // draw a circle + ctx.beginPath(); + ctx.arc(x, y, radius, 0, 2 * Math.PI, false); + ctx.stroke(); }; + /** + * Draw label with white background and with the middle at (x, y) + * @param {CanvasRenderingContext2D} ctx + * @param {String} text + * @param {Number} x + * @param {Number} y + * @private + */ + Edge.prototype._label = function (ctx, text, x, y) { + if (text) { + // TODO: cache the calculated size + ctx.font = ((this.from.selected || this.to.selected) ? "bold " : "") + + this.options.fontSize + "px " + this.options.fontFace; + ctx.fillStyle = this.options.fontFill; + var width = ctx.measureText(text).width; + var height = this.options.fontSize; + var left = x - width / 2; + var top = y - height / 2; + ctx.fillRect(left, top, width, height); - module.exports = Graph2d; - + // draw text + ctx.fillStyle = this.options.fontColor || "black"; + ctx.textAlign = "left"; + ctx.textBaseline = "top"; + ctx.fillText(text, left, top); + } + }; -/***/ }, -/* 36 */ -/***/ function(module, exports, __webpack_require__) { + /** + * Redraw a edge as a dashed line + * Draw this edge in the given canvas + * @author David Jordan + * @date 2012-08-08 + * The 2d context of a HTML canvas can be retrieved by canvas.getContext("2d"); + * @param {CanvasRenderingContext2D} ctx + * @private + */ + Edge.prototype._drawDashLine = function(ctx) { + // set style + if (this.selected == true) {ctx.strokeStyle = this.options.color.highlight;} + else if (this.hover == true) {ctx.strokeStyle = this.options.color.hover;} + else {ctx.strokeStyle = this.options.color.color;} - var util = __webpack_require__(1); - var DOMutil = __webpack_require__(6); - var DataSet = __webpack_require__(7); - var DataView = __webpack_require__(8); - var Component = __webpack_require__(22); - var DataAxis = __webpack_require__(38); - var GraphGroup = __webpack_require__(39); - var Legend = __webpack_require__(40); + ctx.lineWidth = this._getLineWidth(); - var UNGROUPED = '__ungrouped__'; // reserved group id for ungrouped items + var via = null; + // only firefox and chrome support this method, else we use the legacy one. + if (ctx.mozDash !== undefined || ctx.setLineDash !== undefined) { + // configure the dash pattern + var pattern = [0]; + if (this.options.dash.length !== undefined && this.options.dash.gap !== undefined) { + pattern = [this.options.dash.length,this.options.dash.gap]; + } + else { + pattern = [5,5]; + } - /** - * This is the constructor of the LineGraph. It requires a Timeline body and options. - * - * @param body - * @param options - * @constructor - */ - function LineGraph(body, options) { - this.id = util.randomUUID(); - this.body = body; + // set dash settings for chrome or firefox + if (typeof ctx.setLineDash !== 'undefined') { //Chrome + ctx.setLineDash(pattern); + ctx.lineDashOffset = 0; - this.defaultOptions = { - yAxisOrientation: 'left', - defaultGroup: 'default', - sort: true, - sampling: true, - graphHeight: '400px', - shaded: { - enabled: false, - orientation: 'bottom' // top, bottom - }, - style: 'line', // line, bar - barChart: { - width: 50, - allowOverlap: true, - align: 'center' // left, center, right - }, - catmullRom: { - enabled: true, - parametrization: 'centripetal', // uniform (alpha = 0.0), chordal (alpha = 1.0), centripetal (alpha = 0.5) - alpha: 0.5 - }, - drawPoints: { - enabled: true, - size: 6, - style: 'square' // square, circle - }, - dataAxis: { - showMinorLabels: true, - showMajorLabels: true, - icons: false, - width: '40px', - visible: true - }, - legend: { - enabled: false, - icons: true, - left: { - visible: true, - position: 'top-left' // top/bottom - left,right - }, - right: { - visible: true, - position: 'top-right' // top/bottom - left,right - } + } else { //Firefox + ctx.mozDash = pattern; + ctx.mozDashOffset = 0; } - }; - // options is shared by this ItemSet and all its items - this.options = util.extend({}, this.defaultOptions); - this.dom = {}; - this.props = {}; - this.hammer = null; - this.groups = {}; + // draw the line + via = this._line(ctx); - var me = this; - this.itemsData = null; // DataSet - this.groupsData = null; // DataSet + // restore the dash settings. + if (typeof ctx.setLineDash !== 'undefined') { //Chrome + ctx.setLineDash([0]); + ctx.lineDashOffset = 0; - // listeners for the DataSet of the items - this.itemListeners = { - 'add': function (event, params, senderId) { - me._onAdd(params.items); - }, - 'update': function (event, params, senderId) { - me._onUpdate(params.items); - }, - 'remove': function (event, params, senderId) { - me._onRemove(params.items); + } else { //Firefox + ctx.mozDash = [0]; + ctx.mozDashOffset = 0; } - }; - - // listeners for the DataSet of the groups - this.groupListeners = { - 'add': function (event, params, senderId) { - me._onAddGroups(params.items); - }, - 'update': function (event, params, senderId) { - me._onUpdateGroups(params.items); - }, - 'remove': function (event, params, senderId) { - me._onRemoveGroups(params.items); + } + else { // unsupporting smooth lines + // draw dashed line + ctx.beginPath(); + ctx.lineCap = 'round'; + if (this.options.dash.altLength !== undefined) //If an alt dash value has been set add to the array this value + { + ctx.dashedLine(this.from.x,this.from.y,this.to.x,this.to.y, + [this.options.dash.length,this.options.dash.gap,this.options.dash.altLength,this.options.dash.gap]); } - }; + else if (this.options.dash.length !== undefined && this.options.dash.gap !== undefined) //If a dash and gap value has been set add to the array this value + { + ctx.dashedLine(this.from.x,this.from.y,this.to.x,this.to.y, + [this.options.dash.length,this.options.dash.gap]); + } + else //If all else fails draw a line + { + ctx.moveTo(this.from.x, this.from.y); + ctx.lineTo(this.to.x, this.to.y); + } + ctx.stroke(); + } - this.items = {}; // object with an Item for every data item - this.selection = []; // list with the ids of all selected nodes - this.lastStart = this.body.range.start; - this.touchParams = {}; // stores properties while dragging + // draw label + if (this.label) { + var point; + if (this.options.smoothCurves.enabled == true && via != null) { + var midpointX = 0.5*(0.5*(this.from.x + via.x) + 0.5*(this.to.x + via.x)); + var midpointY = 0.5*(0.5*(this.from.y + via.y) + 0.5*(this.to.y + via.y)); + point = {x:midpointX, y:midpointY}; + } + else { + point = this._pointOnLine(0.5); + } + this._label(ctx, this.label, point.x, point.y); + } + }; - this.svgElements = {}; - this.setOptions(options); - this.groupsUsingDefaultStyles = [0]; - - this.body.emitter.on("rangechange",function() { - if (me.lastStart != 0) { - var offset = me.body.range.start - me.lastStart; - var range = me.body.range.end - me.body.range.start; - if (me.width != 0) { - var rangePerPixelInv = me.width/range; - var xOffset = offset * rangePerPixelInv; - me.svg.style.left = (-me.width - xOffset) + "px"; - } - } - }); - this.body.emitter.on("rangechanged", function() { - me.lastStart = me.body.range.start; - me.svg.style.left = util.option.asSize(-me.width); - me._updateGraph.apply(me); - }); - - // create the HTML DOM - this._create(); - this.body.emitter.emit("change"); - } - - LineGraph.prototype = new Component(); + /** + * Get a point on a line + * @param {Number} percentage. Value between 0 (line start) and 1 (line end) + * @return {Object} point + * @private + */ + Edge.prototype._pointOnLine = function (percentage) { + return { + x: (1 - percentage) * this.from.x + percentage * this.to.x, + y: (1 - percentage) * this.from.y + percentage * this.to.y + } + }; /** - * Create the HTML DOM for the ItemSet + * Get a point on a circle + * @param {Number} x + * @param {Number} y + * @param {Number} radius + * @param {Number} percentage. Value between 0 (line start) and 1 (line end) + * @return {Object} point + * @private */ - LineGraph.prototype._create = function(){ - var frame = document.createElement('div'); - frame.className = 'LineGraph'; - this.dom.frame = frame; - - // create svg element for graph drawing. - this.svg = document.createElementNS('http://www.w3.org/2000/svg',"svg"); - this.svg.style.position = "relative"; - this.svg.style.height = ('' + this.options.graphHeight).replace("px",'') + 'px'; - this.svg.style.display = "block"; - frame.appendChild(this.svg); - - // data axis - this.options.dataAxis.orientation = 'left'; - this.yAxisLeft = new DataAxis(this.body, this.options.dataAxis, this.svg); - - this.options.dataAxis.orientation = 'right'; - this.yAxisRight = new DataAxis(this.body, this.options.dataAxis, this.svg); - delete this.options.dataAxis.orientation; - - // legends - this.legendLeft = new Legend(this.body, this.options.legend, 'left'); - this.legendRight = new Legend(this.body, this.options.legend, 'right'); - - this.show(); + Edge.prototype._pointOnCircle = function (x, y, radius, percentage) { + var angle = (percentage - 3/8) * 2 * Math.PI; + return { + x: x + radius * Math.cos(angle), + y: y - radius * Math.sin(angle) + } }; /** - * set the options of the LineGraph. the mergeOptions is used for subObjects that have an enabled element. - * @param options + * Redraw a edge as a line with an arrow halfway the line + * Draw this edge in the given canvas + * The 2d context of a HTML canvas can be retrieved by canvas.getContext("2d"); + * @param {CanvasRenderingContext2D} ctx + * @private */ - LineGraph.prototype.setOptions = function(options) { - if (options) { - var fields = ['sampling','defaultGroup','graphHeight','yAxisOrientation','style','barChart','dataAxis','sort']; - util.selectiveDeepExtend(fields, this.options, options); - util.mergeOptions(this.options, options,'catmullRom'); - util.mergeOptions(this.options, options,'drawPoints'); - util.mergeOptions(this.options, options,'shaded'); - util.mergeOptions(this.options, options,'legend'); + Edge.prototype._drawArrowCenter = function(ctx) { + var point; + // set style + if (this.selected == true) {ctx.strokeStyle = this.options.color.highlight; ctx.fillStyle = this.options.color.highlight;} + else if (this.hover == true) {ctx.strokeStyle = this.options.color.hover; ctx.fillStyle = this.options.color.hover;} + else {ctx.strokeStyle = this.options.color.color; ctx.fillStyle = this.options.color.color;} + ctx.lineWidth = this._getLineWidth(); - if (options.catmullRom) { - if (typeof options.catmullRom == 'object') { - if (options.catmullRom.parametrization) { - if (options.catmullRom.parametrization == 'uniform') { - this.options.catmullRom.alpha = 0; - } - else if (options.catmullRom.parametrization == 'chordal') { - this.options.catmullRom.alpha = 1.0; - } - else { - this.options.catmullRom.parametrization = 'centripetal'; - this.options.catmullRom.alpha = 0.5; - } - } - } - } + if (this.from != this.to) { + // draw line + var via = this._line(ctx); - if (this.yAxisLeft) { - if (options.dataAxis !== undefined) { - this.yAxisLeft.setOptions(this.options.dataAxis); - this.yAxisRight.setOptions(this.options.dataAxis); - } + var angle = Math.atan2((this.to.y - this.from.y), (this.to.x - this.from.x)); + var length = (10 + 5 * this.options.width) * this.options.arrowScaleFactor; + // draw an arrow halfway the line + if (this.options.smoothCurves.enabled == true && via != null) { + var midpointX = 0.5*(0.5*(this.from.x + via.x) + 0.5*(this.to.x + via.x)); + var midpointY = 0.5*(0.5*(this.from.y + via.y) + 0.5*(this.to.y + via.y)); + point = {x:midpointX, y:midpointY}; } - - if (this.legendLeft) { - if (options.legend !== undefined) { - this.legendLeft.setOptions(this.options.legend); - this.legendRight.setOptions(this.options.legend); - } + else { + point = this._pointOnLine(0.5); } - if (this.groups.hasOwnProperty(UNGROUPED)) { - this.groups[UNGROUPED].setOptions(options); + ctx.arrow(point.x, point.y, angle, length); + ctx.fill(); + ctx.stroke(); + + // draw label + if (this.label) { + this._label(ctx, this.label, point.x, point.y); } } - if (this.dom.frame) { - this._updateGraph(); - } - }; + else { + // draw circle + var x, y; + var radius = 0.25 * Math.max(100,this.physics.springLength); + var node = this.from; + if (!node.width) { + node.resize(ctx); + } + if (node.width > node.height) { + x = node.x + node.width * 0.5; + y = node.y - radius; + } + else { + x = node.x + radius; + y = node.y - node.height * 0.5; + } + this._circle(ctx, x, y, radius); - /** - * Hide the component from the DOM - */ - LineGraph.prototype.hide = function() { - // remove the frame containing the items - if (this.dom.frame.parentNode) { - this.dom.frame.parentNode.removeChild(this.dom.frame); - } - }; + // draw all arrows + var angle = 0.2 * Math.PI; + var length = (10 + 5 * this.options.width) * this.options.arrowScaleFactor; + point = this._pointOnCircle(x, y, radius, 0.5); + ctx.arrow(point.x, point.y, angle, length); + ctx.fill(); + ctx.stroke(); - /** - * Show the component in the DOM (when not already visible). - * @return {Boolean} changed - */ - LineGraph.prototype.show = function() { - // show frame containing the items - if (!this.dom.frame.parentNode) { - this.body.dom.center.appendChild(this.dom.frame); + // draw label + if (this.label) { + point = this._pointOnCircle(x, y, radius, 0.5); + this._label(ctx, this.label, point.x, point.y); + } } }; + /** - * Set items - * @param {vis.DataSet | null} items + * Redraw a edge as a line with an arrow + * Draw this edge in the given canvas + * The 2d context of a HTML canvas can be retrieved by canvas.getContext("2d"); + * @param {CanvasRenderingContext2D} ctx + * @private */ - LineGraph.prototype.setItems = function(items) { - var me = this, - ids, - oldItemsData = this.itemsData; + Edge.prototype._drawArrow = function(ctx) { + // set style + if (this.selected == true) {ctx.strokeStyle = this.options.color.highlight; ctx.fillStyle = this.options.color.highlight;} + else if (this.hover == true) {ctx.strokeStyle = this.options.color.hover; ctx.fillStyle = this.options.color.hover;} + else {ctx.strokeStyle = this.options.color.color; ctx.fillStyle = this.options.color.color;} - // replace the dataset - if (!items) { - this.itemsData = null; - } - else if (items instanceof DataSet || items instanceof DataView) { - this.itemsData = items; - } - else { - throw new TypeError('Data must be an instance of DataSet or DataView'); - } + ctx.lineWidth = this._getLineWidth(); - if (oldItemsData) { - // unsubscribe from old dataset - util.forEach(this.itemListeners, function (callback, event) { - oldItemsData.off(event, callback); - }); + var angle, length; + //draw a line + if (this.from != this.to) { + angle = Math.atan2((this.to.y - this.from.y), (this.to.x - this.from.x)); + var dx = (this.to.x - this.from.x); + var dy = (this.to.y - this.from.y); + var edgeSegmentLength = Math.sqrt(dx * dx + dy * dy); - // remove all drawn items - ids = oldItemsData.getIds(); - this._onRemove(ids); - } + var fromBorderDist = this.from.distanceToBorder(ctx, angle + Math.PI); + var fromBorderPoint = (edgeSegmentLength - fromBorderDist) / edgeSegmentLength; + var xFrom = (fromBorderPoint) * this.from.x + (1 - fromBorderPoint) * this.to.x; + var yFrom = (fromBorderPoint) * this.from.y + (1 - fromBorderPoint) * this.to.y; - if (this.itemsData) { - // subscribe to new dataset - var id = this.id; - util.forEach(this.itemListeners, function (callback, event) { - me.itemsData.on(event, callback, id); - }); + var via; + if (this.options.smoothCurves.dynamic == true && this.options.smoothCurves.enabled == true ) { + via = this.via; + } + else if (this.options.smoothCurves.enabled == true) { + via = this._getViaCoordinates(); + } - // add all new items - ids = this.itemsData.getIds(); - this._onAdd(ids); - } - this._updateUngrouped(); - this._updateGraph(); - this.redraw(); - }; + if (this.options.smoothCurves.enabled == true && via.x != null) { + angle = Math.atan2((this.to.y - via.y), (this.to.x - via.x)); + dx = (this.to.x - via.x); + dy = (this.to.y - via.y); + edgeSegmentLength = Math.sqrt(dx * dx + dy * dy); + } + var toBorderDist = this.to.distanceToBorder(ctx, angle); + var toBorderPoint = (edgeSegmentLength - toBorderDist) / edgeSegmentLength; - /** - * Set groups - * @param {vis.DataSet} groups - */ - LineGraph.prototype.setGroups = function(groups) { - var me = this, - ids; + var xTo,yTo; + if (this.options.smoothCurves.enabled == true && via.x != null) { + xTo = (1 - toBorderPoint) * via.x + toBorderPoint * this.to.x; + yTo = (1 - toBorderPoint) * via.y + toBorderPoint * this.to.y; + } + else { + xTo = (1 - toBorderPoint) * this.from.x + toBorderPoint * this.to.x; + yTo = (1 - toBorderPoint) * this.from.y + toBorderPoint * this.to.y; + } - // unsubscribe from current dataset - if (this.groupsData) { - util.forEach(this.groupListeners, function (callback, event) { - me.groupsData.unsubscribe(event, callback); - }); + ctx.beginPath(); + ctx.moveTo(xFrom,yFrom); + if (this.options.smoothCurves.enabled == true && via.x != null) { + ctx.quadraticCurveTo(via.x,via.y,xTo, yTo); + } + else { + ctx.lineTo(xTo, yTo); + } + ctx.stroke(); - // remove all drawn groups - ids = this.groupsData.getIds(); - this.groupsData = null; - this._onRemoveGroups(ids); // note: this will cause a redraw - } + // draw arrow at the end of the line + length = (10 + 5 * this.options.width) * this.options.arrowScaleFactor; + ctx.arrow(xTo, yTo, angle, length); + ctx.fill(); + ctx.stroke(); - // replace the dataset - if (!groups) { - this.groupsData = null; - } - else if (groups instanceof DataSet || groups instanceof DataView) { - this.groupsData = groups; + // draw label + if (this.label) { + var point; + if (this.options.smoothCurves.enabled == true && via != null) { + var midpointX = 0.5*(0.5*(this.from.x + via.x) + 0.5*(this.to.x + via.x)); + var midpointY = 0.5*(0.5*(this.from.y + via.y) + 0.5*(this.to.y + via.y)); + point = {x:midpointX, y:midpointY}; + } + else { + point = this._pointOnLine(0.5); + } + this._label(ctx, this.label, point.x, point.y); + } } else { - throw new TypeError('Data must be an instance of DataSet or DataView'); - } + // draw circle + var node = this.from; + var x, y, arrow; + var radius = 0.25 * Math.max(100,this.physics.springLength); + if (!node.width) { + node.resize(ctx); + } + if (node.width > node.height) { + x = node.x + node.width * 0.5; + y = node.y - radius; + arrow = { + x: x, + y: node.y, + angle: 0.9 * Math.PI + }; + } + else { + x = node.x + radius; + y = node.y - node.height * 0.5; + arrow = { + x: node.x, + y: y, + angle: 0.6 * Math.PI + }; + } + ctx.beginPath(); + // TODO: similarly, for a line without arrows, draw to the border of the nodes instead of the center + ctx.arc(x, y, radius, 0, 2 * Math.PI, false); + ctx.stroke(); - if (this.groupsData) { - // subscribe to new dataset - var id = this.id; - util.forEach(this.groupListeners, function (callback, event) { - me.groupsData.on(event, callback, id); - }); + // draw all arrows + var length = (10 + 5 * this.options.width) * this.options.arrowScaleFactor; + ctx.arrow(arrow.x, arrow.y, arrow.angle, length); + ctx.fill(); + ctx.stroke(); - // draw all ms - ids = this.groupsData.getIds(); - this._onAddGroups(ids); + // draw label + if (this.label) { + point = this._pointOnCircle(x, y, radius, 0.5); + this._label(ctx, this.label, point.x, point.y); + } } - this._onUpdate(); - }; - - - - LineGraph.prototype._onUpdate = function(ids) { - this._updateUngrouped(); - this._updateAllGroupData(); - this._updateGraph(); - this.redraw(); }; - LineGraph.prototype._onAdd = function (ids) {this._onUpdate(ids);}; - LineGraph.prototype._onRemove = function (ids) {this._onUpdate(ids);}; - LineGraph.prototype._onUpdateGroups = function (groupIds) { - for (var i = 0; i < groupIds.length; i++) { - var group = this.groupsData.get(groupIds[i]); - this._updateGroup(group, groupIds[i]); - } - this._updateGraph(); - this.redraw(); - }; - LineGraph.prototype._onAddGroups = function (groupIds) {this._onUpdateGroups(groupIds);}; - LineGraph.prototype._onRemoveGroups = function (groupIds) { - for (var i = 0; i < groupIds.length; i++) { - if (!this.groups.hasOwnProperty(groupIds[i])) { - if (this.groups[groupIds[i]].options.yAxisOrientation == 'right') { - this.yAxisRight.removeGroup(groupIds[i]); - this.legendRight.removeGroup(groupIds[i]); - this.legendRight.redraw(); - } - else { - this.yAxisLeft.removeGroup(groupIds[i]); - this.legendLeft.removeGroup(groupIds[i]); - this.legendLeft.redraw(); - } - delete this.groups[groupIds[i]]; - } - } - this._updateUngrouped(); - this._updateGraph(); - this.redraw(); - }; /** - * update a group object - * - * @param group - * @param groupId + * Calculate the distance between a point (x3,y3) and a line segment from + * (x1,y1) to (x2,y2). + * http://stackoverflow.com/questions/849211/shortest-distancae-between-a-point-and-a-line-segment + * @param {number} x1 + * @param {number} y1 + * @param {number} x2 + * @param {number} y2 + * @param {number} x3 + * @param {number} y3 * @private */ - LineGraph.prototype._updateGroup = function (group, groupId) { - if (!this.groups.hasOwnProperty(groupId)) { - this.groups[groupId] = new GraphGroup(group, groupId, this.options, this.groupsUsingDefaultStyles); - if (this.groups[groupId].options.yAxisOrientation == 'right') { - this.yAxisRight.addGroup(groupId, this.groups[groupId]); - this.legendRight.addGroup(groupId, this.groups[groupId]); + Edge.prototype._getDistanceToEdge = function (x1,y1, x2,y2, x3,y3) { // x3,y3 is the point + if (this.from != this.to) { + if (this.options.smoothCurves.enabled == true) { + var xVia, yVia; + if (this.options.smoothCurves.enabled == true && this.options.smoothCurves.dynamic == true) { + xVia = this.via.x; + yVia = this.via.y; + } + else { + var via = this._getViaCoordinates(); + xVia = via.x; + yVia = via.y; + } + var minDistance = 1e9; + var distance; + var i,t,x,y, lastX, lastY; + for (i = 0; i < 10; i++) { + t = 0.1*i; + x = Math.pow(1-t,2)*x1 + (2*t*(1 - t))*xVia + Math.pow(t,2)*x2; + y = Math.pow(1-t,2)*y1 + (2*t*(1 - t))*yVia + Math.pow(t,2)*y2; + if (i > 0) { + distance = this._getDistanceToLine(lastX,lastY,x,y, x3,y3); + minDistance = distance < minDistance ? distance : minDistance; + } + lastX = x; lastY = y; + } + return minDistance } else { - this.yAxisLeft.addGroup(groupId, this.groups[groupId]); - this.legendLeft.addGroup(groupId, this.groups[groupId]); + return this._getDistanceToLine(x1,y1,x2,y2,x3,y3); } } else { - this.groups[groupId].update(group); - if (this.groups[groupId].options.yAxisOrientation == 'right') { - this.yAxisRight.updateGroup(groupId, this.groups[groupId]); - this.legendRight.updateGroup(groupId, this.groups[groupId]); + var x, y, dx, dy; + var radius = this.physics.springLength / 4; + var node = this.from; + if (!node.width) { + node.resize(ctx); + } + if (node.width > node.height) { + x = node.x + node.width / 2; + y = node.y - radius; } else { - this.yAxisLeft.updateGroup(groupId, this.groups[groupId]); - this.legendLeft.updateGroup(groupId, this.groups[groupId]); + x = node.x + radius; + y = node.y - node.height / 2; } + dx = x - x3; + dy = y - y3; + return Math.abs(Math.sqrt(dx*dx + dy*dy) - radius); } - this.legendLeft.redraw(); - this.legendRight.redraw(); }; - LineGraph.prototype._updateAllGroupData = function () { - if (this.itemsData != null) { - var groupsContent = {}; - for (var groupId in this.groups) { - if (this.groups.hasOwnProperty(groupId)) { - groupsContent[groupId] = []; - } - } - for (var itemId in this.itemsData._data) { - if (this.itemsData._data.hasOwnProperty(itemId)) { - var item = this.itemsData._data[itemId]; - item.x = util.convert(item.x,"Date"); - groupsContent[item.group].push(item); - } - } - for (var groupId in this.groups) { - if (this.groups.hasOwnProperty(groupId)) { - this.groups[groupId].setItems(groupsContent[groupId]); - } - } + Edge.prototype._getDistanceToLine = function(x1,y1,x2,y2,x3,y3) { + var px = x2-x1, + py = y2-y1, + something = px*px + py*py, + u = ((x3 - x1) * px + (y3 - y1) * py) / something; + + if (u > 1) { + u = 1; + } + else if (u < 0) { + u = 0; } - }; - /** - * Create or delete the group holding all ungrouped items. This group is used when - * there are no groups specified. This anonymous group is called 'graph'. - * @protected - */ - LineGraph.prototype._updateUngrouped = function() { - if (this.itemsData != null) { - // var t0 = new Date(); - var group = {id: UNGROUPED, content: this.options.defaultGroup}; - this._updateGroup(group, UNGROUPED); - var ungroupedCounter = 0; - if (this.itemsData) { - for (var itemId in this.itemsData._data) { - if (this.itemsData._data.hasOwnProperty(itemId)) { - var item = this.itemsData._data[itemId]; - if (item != undefined) { - if (item.hasOwnProperty('group')) { - if (item.group === undefined) { - item.group = UNGROUPED; - } - } - else { - item.group = UNGROUPED; - } - ungroupedCounter = item.group == UNGROUPED ? ungroupedCounter + 1 : ungroupedCounter; - } - } - } + var x = x1 + u * px, + y = y1 + u * py, + dx = x - x3, + dy = y - y3; + + //# Note: If the actual distance does not matter, + //# if you only want to compare what this function + //# returns to other results of this function, you + //# can just return the squared distance instead + //# (i.e. remove the sqrt) to gain a little performance + + return Math.sqrt(dx*dx + dy*dy); + } + + /** + * This allows the zoom level of the network to influence the rendering + * + * @param scale + */ + Edge.prototype.setScale = function(scale) { + this.networkScaleInv = 1.0/scale; + }; + + + Edge.prototype.select = function() { + this.selected = true; + }; + + Edge.prototype.unselect = function() { + this.selected = false; + }; + + Edge.prototype.positionBezierNode = function() { + if (this.via !== null && this.from !== null && this.to !== null) { + this.via.x = 0.5 * (this.from.x + this.to.x); + this.via.y = 0.5 * (this.from.y + this.to.y); + } + }; + + /** + * This function draws the control nodes for the manipulator. In order to enable this, only set the this.controlNodesEnabled to true. + * @param ctx + */ + Edge.prototype._drawControlNodes = function(ctx) { + if (this.controlNodesEnabled == true) { + if (this.controlNodes.from === null && this.controlNodes.to === null) { + var nodeIdFrom = "edgeIdFrom:".concat(this.id); + var nodeIdTo = "edgeIdTo:".concat(this.id); + var constants = { + nodes:{group:'', radius:8}, + physics:{damping:0}, + clustering: {maxNodeSizeIncrements: 0 ,nodeScaling: {width:0, height: 0, radius:0}} + }; + this.controlNodes.from = new Node( + {id:nodeIdFrom, + shape:'dot', + color:{background:'#ff4e00', border:'#3c3c3c', highlight: {background:'#07f968'}} + },{},{},constants); + this.controlNodes.to = new Node( + {id:nodeIdTo, + shape:'dot', + color:{background:'#ff4e00', border:'#3c3c3c', highlight: {background:'#07f968'}} + },{},{},constants); } - // much much slower - // var datapoints = this.itemsData.get({ - // filter: function (item) {return item.group === undefined;}, - // showInternalIds:true - // }); - // if (datapoints.length > 0) { - // var updateQuery = []; - // for (var i = 0; i < datapoints.length; i++) { - // updateQuery.push({id:datapoints[i].id, group: UNGROUPED}); - // } - // this.itemsData.update(updateQuery, true); - // } - // var t1 = new Date(); - // var pointInUNGROUPED = this.itemsData.get({filter: function (item) {return item.group == UNGROUPED;}}); - if (ungroupedCounter == 0) { - delete this.groups[UNGROUPED]; - this.legendLeft.removeGroup(UNGROUPED); - this.legendRight.removeGroup(UNGROUPED); - this.yAxisLeft.removeGroup(UNGROUPED); - this.yAxisRight.removeGroup(UNGROUPED); + if (this.controlNodes.from.selected == false && this.controlNodes.to.selected == false) { + this.controlNodes.positions = this.getControlNodePositions(ctx); + this.controlNodes.from.x = this.controlNodes.positions.from.x; + this.controlNodes.from.y = this.controlNodes.positions.from.y; + this.controlNodes.to.x = this.controlNodes.positions.to.x; + this.controlNodes.to.y = this.controlNodes.positions.to.y; } - // console.log("getting amount ungrouped",new Date() - t1); - // console.log("putting in ungrouped",new Date() - t0); + + this.controlNodes.from.draw(ctx); + this.controlNodes.to.draw(ctx); } else { - delete this.groups[UNGROUPED]; - this.legendLeft.removeGroup(UNGROUPED); - this.legendRight.removeGroup(UNGROUPED); - this.yAxisLeft.removeGroup(UNGROUPED); - this.yAxisRight.removeGroup(UNGROUPED); + this.controlNodes = {from:null, to:null, positions:{}}; } + }; - this.legendLeft.redraw(); - this.legendRight.redraw(); + /** + * Enable control nodes. + * @private + */ + Edge.prototype._enableControlNodes = function() { + this.controlNodesEnabled = true; }; + /** + * disable control nodes + * @private + */ + Edge.prototype._disableControlNodes = function() { + this.controlNodesEnabled = false; + }; /** - * Redraw the component, mandatory function - * @return {boolean} Returns true if the component is resized + * This checks if one of the control nodes is selected and if so, returns the control node object. Else it returns null. + * @param x + * @param y + * @returns {null} + * @private */ - LineGraph.prototype.redraw = function() { - var resized = false; + Edge.prototype._getSelectedControlNode = function(x,y) { + var positions = this.controlNodes.positions; + var fromDistance = Math.sqrt(Math.pow(x - positions.from.x,2) + Math.pow(y - positions.from.y,2)); + var toDistance = Math.sqrt(Math.pow(x - positions.to.x ,2) + Math.pow(y - positions.to.y ,2)); - this.svg.style.height = ('' + this.options.graphHeight).replace('px','') + 'px'; - if (this.lastWidth === undefined && this.width || this.lastWidth != this.width) { - resized = true; + if (fromDistance < 15) { + this.connectedNode = this.from; + this.from = this.controlNodes.from; + return this.controlNodes.from; } - // check if this component is resized - resized = this._isResized() || resized; - // check whether zoomed (in that case we need to re-stack everything) - var visibleInterval = this.body.range.end - this.body.range.start; - var zoomed = (visibleInterval != this.lastVisibleInterval) || (this.width != this.lastWidth); - this.lastVisibleInterval = visibleInterval; - this.lastWidth = this.width; - - // calculate actual size and position - this.width = this.dom.frame.offsetWidth; - - // the svg element is three times as big as the width, this allows for fully dragging left and right - // without reloading the graph. the controls for this are bound to events in the constructor - if (resized == true) { - this.svg.style.width = util.option.asSize(3*this.width); - this.svg.style.left = util.option.asSize(-this.width); + else if (toDistance < 15) { + this.connectedNode = this.to; + this.to = this.controlNodes.to; + return this.controlNodes.to; } - if (zoomed == true) { - this._updateGraph(); + else { + return null; } + }; - this.legendLeft.redraw(); - this.legendRight.redraw(); - return resized; + /** + * this resets the control nodes to their original position. + * @private + */ + Edge.prototype._restoreControlNodes = function() { + if (this.controlNodes.from.selected == true) { + this.from = this.connectedNode; + this.connectedNode = null; + this.controlNodes.from.unselect(); + } + if (this.controlNodes.to.selected == true) { + this.to = this.connectedNode; + this.connectedNode = null; + this.controlNodes.to.unselect(); + } }; /** - * Update and redraw the graph. + * this calculates the position of the control nodes on the edges of the parent nodes. * + * @param ctx + * @returns {{from: {x: number, y: number}, to: {x: *, y: *}}} */ - LineGraph.prototype._updateGraph = function () { - // reset the svg elements - DOMutil.prepareElements(this.svgElements); + Edge.prototype.getControlNodePositions = function(ctx) { + var angle = Math.atan2((this.to.y - this.from.y), (this.to.x - this.from.x)); + var dx = (this.to.x - this.from.x); + var dy = (this.to.y - this.from.y); + var edgeSegmentLength = Math.sqrt(dx * dx + dy * dy); + var fromBorderDist = this.from.distanceToBorder(ctx, angle + Math.PI); + var fromBorderPoint = (edgeSegmentLength - fromBorderDist) / edgeSegmentLength; + var xFrom = (fromBorderPoint) * this.from.x + (1 - fromBorderPoint) * this.to.x; + var yFrom = (fromBorderPoint) * this.from.y + (1 - fromBorderPoint) * this.to.y; - if (this.width != 0 && this.itemsData != null) { - var group, groupData, preprocessedGroup, i; - var preprocessedGroupData = []; - var processedGroupData = []; - var groupRanges = []; - var changeCalled = false; + var via; + if (this.options.smoothCurves.dynamic == true && this.options.smoothCurves.enabled == true) { + via = this.via; + } + else if (this.options.smoothCurves.enabled == true) { + via = this._getViaCoordinates(); + } - // getting group Ids - var groupIds = []; - for (var groupId in this.groups) { - if (this.groups.hasOwnProperty(groupId)) { - groupIds.push(groupId); - } - } + if (this.options.smoothCurves.enabled == true && via.x != null) { + angle = Math.atan2((this.to.y - via.y), (this.to.x - via.x)); + dx = (this.to.x - via.x); + dy = (this.to.y - via.y); + edgeSegmentLength = Math.sqrt(dx * dx + dy * dy); + } + var toBorderDist = this.to.distanceToBorder(ctx, angle); + var toBorderPoint = (edgeSegmentLength - toBorderDist) / edgeSegmentLength; - // this is the range of the SVG canvas - var minDate = this.body.util.toGlobalTime(- this.body.domProps.root.width); - var maxDate = this.body.util.toGlobalTime(2 * this.body.domProps.root.width); + var xTo,yTo; + if (this.options.smoothCurves.enabled == true && via.x != null) { + xTo = (1 - toBorderPoint) * via.x + toBorderPoint * this.to.x; + yTo = (1 - toBorderPoint) * via.y + toBorderPoint * this.to.y; + } + else { + xTo = (1 - toBorderPoint) * this.from.x + toBorderPoint * this.to.x; + yTo = (1 - toBorderPoint) * this.from.y + toBorderPoint * this.to.y; + } - // first select and preprocess the data from the datasets. - // the groups have their preselection of data, we now loop over this data to see - // what data we need to draw. Sorted data is much faster. - // more optimization is possible by doing the sampling before and using the binary search - // to find the end date to determine the increment. - if (groupIds.length > 0) { - for (i = 0; i < groupIds.length; i++) { - group = this.groups[groupIds[i]]; - if (group.visible == true) { - groupData = []; - // optimization for sorted data - if (group.options.sort == true) { - var guess = Math.max(0,util.binarySearchGeneric(group.itemsData, minDate, 'x', 'before')); + return {from:{x:xFrom,y:yFrom},to:{x:xTo,y:yTo}}; + }; - for (var j = guess; j < group.itemsData.length; j++) { - var item = group.itemsData[j]; - if (item !== undefined) { - if (item.x > maxDate) { - groupData.push(item); - break; - } - else { - groupData.push(item); - } - } - } - } - else { - for (var j = 0; j < group.itemsData.length; j++) { - var item = group.itemsData[j]; - if (item !== undefined) { - if (item.x > minDate && item.x < maxDate) { - groupData.push(item); - } - } - } - } - // preprocess, split into ranges and data - if (groupData.length > 0) { - preprocessedGroup = this._preprocessData(groupData, group); - groupRanges.push({min: preprocessedGroup.min, max: preprocessedGroup.max}); - preprocessedGroupData.push(preprocessedGroup.data); - } - else { - groupRanges.push({}); - preprocessedGroupData.push([]); - } - } - else { - groupRanges.push({}); - preprocessedGroupData.push([]); - } - } + module.exports = Edge; - // update the Y axis first, we use this data to draw at the correct Y points - // changeCalled is required to clean the SVG on a change emit. - changeCalled = this._updateYAxis(groupIds, groupRanges); - if (changeCalled == true) { - DOMutil.cleanupElements(this.svgElements); - this.body.emitter.emit("change"); - return; - } +/***/ }, +/* 34 */ +/***/ function(module, exports, __webpack_require__) { - // with the yAxis scaled correctly, use this to get the Y values of the points. - for (i = 0; i < groupIds.length; i++) { - group = this.groups[groupIds[i]]; - processedGroupData.push(this._convertYvalues(preprocessedGroupData[i],group)) - } + var util = __webpack_require__(1); - // draw the groups - for (i = 0; i < groupIds.length; i++) { - group = this.groups[groupIds[i]]; - if (group.visible == true) { - if (group.options.style == 'line') { - this._drawLineGraph(processedGroupData[i], group); - } - else { - this._drawBarGraph (processedGroupData[i], group); - } - } - } - } - } + /** + * @class Groups + * This class can store groups and properties specific for groups. + */ + function Groups() { + this.clear(); + this.defaultIndex = 0; + } - // cleanup unused svg elements - DOMutil.cleanupElements(this.svgElements); - }; /** - * this sets the Y ranges for the Y axis. It also determines which of the axis should be shown or hidden. - * @param {array} groupIds - * @private + * default constants for group colors */ - LineGraph.prototype._updateYAxis = function (groupIds, groupRanges) { - var changeCalled = false; - var yAxisLeftUsed = false; - var yAxisRightUsed = false; - var minLeft = 1e9, minRight = 1e9, maxLeft = -1e9, maxRight = -1e9, minVal, maxVal; - var orientation = 'left'; - - // if groups are present - if (groupIds.length > 0) { - for (var i = 0; i < groupIds.length; i++) { - orientation = 'left'; - var group = this.groups[groupIds[i]]; - if (group.visible == true) { - if (group.options.yAxisOrientation == 'right') { - orientation = 'right'; - } + Groups.DEFAULT = [ + {border: "#2B7CE9", background: "#97C2FC", highlight: {border: "#2B7CE9", background: "#D2E5FF"}, hover: {border: "#2B7CE9", background: "#D2E5FF"}}, // blue + {border: "#FFA500", background: "#FFFF00", highlight: {border: "#FFA500", background: "#FFFFA3"}, hover: {border: "#FFA500", background: "#FFFFA3"}}, // yellow + {border: "#FA0A10", background: "#FB7E81", highlight: {border: "#FA0A10", background: "#FFAFB1"}, hover: {border: "#FA0A10", background: "#FFAFB1"}}, // red + {border: "#41A906", background: "#7BE141", highlight: {border: "#41A906", background: "#A1EC76"}, hover: {border: "#41A906", background: "#A1EC76"}}, // green + {border: "#E129F0", background: "#EB7DF4", highlight: {border: "#E129F0", background: "#F0B3F5"}, hover: {border: "#E129F0", background: "#F0B3F5"}}, // magenta + {border: "#7C29F0", background: "#AD85E4", highlight: {border: "#7C29F0", background: "#D3BDF0"}, hover: {border: "#7C29F0", background: "#D3BDF0"}}, // purple + {border: "#C37F00", background: "#FFA807", highlight: {border: "#C37F00", background: "#FFCA66"}, hover: {border: "#C37F00", background: "#FFCA66"}}, // orange + {border: "#4220FB", background: "#6E6EFD", highlight: {border: "#4220FB", background: "#9B9BFD"}, hover: {border: "#4220FB", background: "#9B9BFD"}}, // darkblue + {border: "#FD5A77", background: "#FFC0CB", highlight: {border: "#FD5A77", background: "#FFD1D9"}, hover: {border: "#FD5A77", background: "#FFD1D9"}}, // pink + {border: "#4AD63A", background: "#C2FABC", highlight: {border: "#4AD63A", background: "#E6FFE3"}, hover: {border: "#4AD63A", background: "#E6FFE3"}} // mint + ]; - minVal = groupRanges[i].min; - maxVal = groupRanges[i].max; - if (orientation == 'left') { - yAxisLeftUsed = true; - minLeft = minLeft > minVal ? minVal : minLeft; - maxLeft = maxLeft < maxVal ? maxVal : maxLeft; - } - else { - yAxisRightUsed = true; - minRight = minRight > minVal ? minVal : minRight; - maxRight = maxRight < maxVal ? maxVal : maxRight; - } + /** + * Clear all groups + */ + Groups.prototype.clear = function () { + this.groups = {}; + this.groups.length = function() + { + var i = 0; + for ( var p in this ) { + if (this.hasOwnProperty(p)) { + i++; } } - if (yAxisLeftUsed == true) { - this.yAxisLeft.setRange(minLeft, maxLeft); - } - if (yAxisRightUsed == true) { - this.yAxisRight.setRange(minRight, maxRight); - } + return i; } + }; - changeCalled = this._toggleAxisVisiblity(yAxisLeftUsed , this.yAxisLeft) || changeCalled; - changeCalled = this._toggleAxisVisiblity(yAxisRightUsed, this.yAxisRight) || changeCalled; - if (yAxisRightUsed == true && yAxisLeftUsed == true) { - this.yAxisLeft.drawIcons = true; - this.yAxisRight.drawIcons = true; - } - else { - this.yAxisLeft.drawIcons = false; - this.yAxisRight.drawIcons = false; + /** + * get group properties of a groupname. If groupname is not found, a new group + * is added. + * @param {*} groupname Can be a number, string, Date, etc. + * @return {Object} group The created group, containing all group properties + */ + Groups.prototype.get = function (groupname) { + var group = this.groups[groupname]; + if (group == undefined) { + // create new group + var index = this.defaultIndex % Groups.DEFAULT.length; + this.defaultIndex++; + group = {}; + group.color = Groups.DEFAULT[index]; + this.groups[groupname] = group; } - this.yAxisRight.master = !yAxisLeftUsed; - - if (this.yAxisRight.master == false) { - if (yAxisRightUsed == true) {this.yAxisLeft.lineOffset = this.yAxisRight.width;} - else {this.yAxisLeft.lineOffset = 0;} - - changeCalled = this.yAxisLeft.redraw() || changeCalled; - this.yAxisRight.stepPixelsForced = this.yAxisLeft.stepPixels; - changeCalled = this.yAxisRight.redraw() || changeCalled; - } - else { - changeCalled = this.yAxisRight.redraw() || changeCalled; - } - return changeCalled; + return group; }; /** - * This shows or hides the Y axis if needed. If there is a change, the changed event is emitted by the updateYAxis function - * - * @param {boolean} axisUsed - * @returns {boolean} - * @private - * @param axis + * Add a custom group style + * @param {String} groupname + * @param {Object} style An object containing borderColor, + * backgroundColor, etc. + * @return {Object} group The created group object */ - LineGraph.prototype._toggleAxisVisiblity = function (axisUsed, axis) { - var changed = false; - if (axisUsed == false) { - if (axis.dom.frame.parentNode) { - axis.hide(); - changed = true; - } - } - else { - if (!axis.dom.frame.parentNode) { - axis.show(); - changed = true; - } + Groups.prototype.add = function (groupname, style) { + this.groups[groupname] = style; + if (style.color) { + style.color = util.parseColor(style.color); } - return changed; + return style; }; + module.exports = Groups; + + +/***/ }, +/* 35 */ +/***/ function(module, exports, __webpack_require__) { /** - * draw a bar graph - * @param datapoints - * @param group + * @class Images + * This class loads images and keeps them stored. */ - LineGraph.prototype._drawBarGraph = function (dataset, group) { - if (dataset != null) { - if (dataset.length > 0) { - var coreDistance; - var minWidth = 0.1 * group.options.barChart.width; - var offset = 0; + function Images() { + this.images = {}; - // check for intersections - var intersections = {}; + this.callback = undefined; + } - for (var i = 0; i < dataset.length; i++) { - if (i+1 < dataset.length) {coreDistance = Math.abs(dataset[i+1].x - dataset[i].x);} - if (i > 0) {coreDistance = Math.min(coreDistance,Math.abs(dataset[i-1].x - dataset[i].x));} - if (coreDistance == 0) { - if (intersections[dataset[i].x] === undefined) { - intersections[dataset[i].x] = {amount:0, resolved:0}; - } - intersections[dataset[i].x].amount += 1; - } - } - - // plot the bargraph - var key; - for (var i = 0; i < dataset.length; i++) { - key = dataset[i].x; - if (intersections[key] === undefined) { - if (i+1 < dataset.length) {coreDistance = Math.abs(dataset[i+1].x - key);} - if (i > 0) {coreDistance = Math.min(coreDistance,Math.abs(dataset[i-1].x - key));} - var drawData = this._getSafeDrawData(coreDistance, group, minWidth); - } - else { - var nextKey = i + (intersections[key].amount - intersections[key].resolved); - var prevKey = i - (intersections[key].resolved + 1); - if (nextKey < dataset.length) {coreDistance = Math.abs(dataset[nextKey].x - key);} - if (prevKey > 0) {coreDistance = Math.min(coreDistance,Math.abs(dataset[prevKey].x - key));} - var drawData = this._getSafeDrawData(coreDistance, group, minWidth); - intersections[key].resolved += 1; - - if (group.options.barChart.allowOverlap == false) { - drawData.width = drawData.width / intersections[key].amount; - drawData.offset += (intersections[key].resolved) * drawData.width - (0.5*drawData.width * (intersections[key].amount+1)); - if (group.options.barChart.align == 'left') {offset -= 0.5*drawData.width;} - else if (group.options.barChart.align == 'right') {offset += 0.5*drawData.width;} - } - } - DOMutil.drawBar(dataset[i].x + drawData.offset, dataset[i].y, drawData.width, group.zeroPosition - dataset[i].y, group.className + ' bar', this.svgElements, this.svg); + /** + * Set an onload callback function. This will be called each time an image + * is loaded + * @param {function} callback + */ + Images.prototype.setOnloadCallback = function(callback) { + this.callback = callback; + }; - // draw points - if (group.options.drawPoints.enabled == true) { - DOMutil.drawPoint(dataset[i].x + drawData.offset, dataset[i].y, group, this.svgElements, this.svg); - } + /** + * + * @param {string} url Url of the image + * @return {Image} img The image object + */ + Images.prototype.load = function(url) { + var img = this.images[url]; + if (img == undefined) { + // create the image + var images = this; + img = new Image(); + this.images[url] = img; + img.onload = function() { + if (images.callback) { + images.callback(this); } - } + }; + img.src = url; } + + return img; }; - LineGraph.prototype._getSafeDrawData = function (coreDistance, group, minWidth) { - var width, offset; - if (coreDistance < group.options.barChart.width && coreDistance > 0) { - width = coreDistance < minWidth ? minWidth : coreDistance; + module.exports = Images; - offset = 0; // recalculate offset with the new width; - if (group.options.slots) { // recalculate the shared width and offset if these options are set. - width = (width / group.options.slots.total); - offset = group.options.slots.slot * width - (0.5*width * (group.options.slots.total+1)); - } - if (group.options.barChart.align == 'left') {offset -= 0.5*coreDistance;} - else if (group.options.barChart.align == 'right') {offset += 0.5*coreDistance;} - } - else { - // no collisions, plot with default settings - width = group.options.barChart.width; - offset = 0; - if (group.options.slots) { - // if the groups are sharing the same points, this allows them to be plotted side by side - width = width / group.options.slots.total; - offset = group.options.slots.slot * width - (0.5*width * (group.options.slots.total+1)); - } - if (group.options.barChart.align == 'left') {offset -= 0.5*group.options.barChart.width;} - else if (group.options.barChart.align == 'right') {offset += 0.5*group.options.barChart.width;} - } - return {width: width, offset: offset}; - } +/***/ }, +/* 36 */ +/***/ function(module, exports, __webpack_require__) { + var util = __webpack_require__(1); /** - * draw a line graph + * @class Node + * A node. A node can be connected to other nodes via one or multiple edges. + * @param {object} properties An object containing properties for the node. All + * properties are optional, except for the id. + * {number} id Id of the node. Required + * {string} label Text label for the node + * {number} x Horizontal position of the node + * {number} y Vertical position of the node + * {string} shape Node shape, available: + * "database", "circle", "ellipse", + * "box", "image", "text", "dot", + * "star", "triangle", "triangleDown", + * "square" + * {string} image An image url + * {string} title An title text, can be HTML + * {anytype} group A group name or number + * @param {Network.Images} imagelist A list with images. Only needed + * when the node has an image + * @param {Network.Groups} grouplist A list with groups. Needed for + * retrieving group properties + * @param {Object} constants An object with default values for + * example for the color * - * @param datapoints - * @param group */ - LineGraph.prototype._drawLineGraph = function (dataset, group) { - if (dataset != null) { - if (dataset.length > 0) { - var path, d; - var svgHeight = Number(this.svg.style.height.replace("px","")); - path = DOMutil.getSVGElement('path', this.svgElements, this.svg); - path.setAttributeNS(null, "class", group.className); - - // construct path from dataset - if (group.options.catmullRom.enabled == true) { - d = this._catmullRom(dataset, group); - } - else { - d = this._linear(dataset); - } + function Node(properties, imagelist, grouplist, networkConstants) { + var constants = util.selectiveBridgeObject(['nodes'],networkConstants); + this.options = constants.nodes; - // append with points for fill and finalize the path - if (group.options.shaded.enabled == true) { - var fillPath = DOMutil.getSVGElement('path',this.svgElements, this.svg); - var dFill; - if (group.options.shaded.orientation == 'top') { - dFill = "M" + dataset[0].x + "," + 0 + " " + d + "L" + dataset[dataset.length - 1].x + "," + 0; - } - else { - dFill = "M" + dataset[0].x + "," + svgHeight + " " + d + "L" + dataset[dataset.length - 1].x + "," + svgHeight; - } - fillPath.setAttributeNS(null, "class", group.className + " fill"); - fillPath.setAttributeNS(null, "d", dFill); - } - // copy properties to path for drawing. - path.setAttributeNS(null, "d", "M" + d); + this.selected = false; + this.hover = false; - // draw points - if (group.options.drawPoints.enabled == true) { - this._drawPoints(dataset, group, this.svgElements, this.svg); - } - } - } - }; + this.edges = []; // all edges connected to this node + this.dynamicEdges = []; + this.reroutedEdges = {}; - /** - * draw the data points - * - * @param dataset - * @param JSONcontainer - * @param svg - * @param group - */ - LineGraph.prototype._drawPoints = function (dataset, group, JSONcontainer, svg, offset) { - if (offset === undefined) {offset = 0;} - for (var i = 0; i < dataset.length; i++) { - DOMutil.drawPoint(dataset[i].x + offset, dataset[i].y, group, JSONcontainer, svg); - } - }; + this.fontDrawThreshold = 3; + // set defaults for the properties + this.id = undefined; + this.x = null; + this.y = null; + this.xFixed = false; + this.yFixed = false; + this.horizontalAlignLeft = true; // these are for the navigation controls + this.verticalAlignTop = true; // these are for the navigation controls + this.baseRadiusValue = networkConstants.nodes.radius; + this.radiusFixed = false; + this.level = -1; + this.preassignedLevel = false; - /** - * This uses the DataAxis object to generate the correct X coordinate on the SVG window. It uses the - * util function toScreen to get the x coordinate from the timestamp. It also pre-filters the data and get the minMax ranges for - * the yAxis. - * - * @param datapoints - * @returns {Array} - * @private - */ - LineGraph.prototype._preprocessData = function (datapoints, group) { - var extractedData = []; - var xValue, yValue; - var toScreen = this.body.util.toScreen; + this.imagelist = imagelist; + this.grouplist = grouplist; - var increment = 1; - var amountOfPoints = datapoints.length; + // physics properties + this.fx = 0.0; // external force x + this.fy = 0.0; // external force y + this.vx = 0.0; // velocity x + this.vy = 0.0; // velocity y + this.damping = networkConstants.physics.damping; // written every time gravity is calculated + this.fixedData = {x:null,y:null}; - var yMin = datapoints[0].y; - var yMax = datapoints[0].y; - // the global screen is used because changing the width of the yAxis may affect the increment, resulting in an endless loop - // of width changing of the yAxis. - if (group.options.sampling == true) { - var xDistance = this.body.util.toGlobalScreen(datapoints[datapoints.length-1].x) - this.body.util.toGlobalScreen(datapoints[0].x); - var pointsPerPixel = amountOfPoints/xDistance; - increment = Math.min(Math.ceil(0.2 * amountOfPoints), Math.max(1,Math.round(pointsPerPixel))); - } + this.setProperties(properties, constants); - for (var i = 0; i < amountOfPoints; i += increment) { - xValue = toScreen(datapoints[i].x) + this.width - 1; - yValue = datapoints[i].y; - extractedData.push({x: xValue, y: yValue}); - yMin = yMin > yValue ? yValue : yMin; - yMax = yMax < yValue ? yValue : yMax; - } + // creating the variables for clustering + this.resetCluster(); + this.dynamicEdgesLength = 0; + this.clusterSession = 0; + this.clusterSizeWidthFactor = networkConstants.clustering.nodeScaling.width; + this.clusterSizeHeightFactor = networkConstants.clustering.nodeScaling.height; + this.clusterSizeRadiusFactor = networkConstants.clustering.nodeScaling.radius; + this.maxNodeSizeIncrements = networkConstants.clustering.maxNodeSizeIncrements; + this.growthIndicator = 0; - // extractedData.sort(function (a,b) {return a.x - b.x;}); - return {min: yMin, max: yMax, data: extractedData}; - }; + // variables to tell the node about the network. + this.networkScaleInv = 1; + this.networkScale = 1; + this.canvasTopLeft = {"x": -300, "y": -300}; + this.canvasBottomRight = {"x": 300, "y": 300}; + this.parentEdgeId = null; + } /** - * This uses the DataAxis object to generate the correct Y coordinate on the SVG window. It uses the - * util function toScreen to get the x coordinate from the timestamp. - * - * @param datapoints - * @param options - * @returns {Array} - * @private + * (re)setting the clustering variables and objects */ - LineGraph.prototype._convertYvalues = function (datapoints, group) { - var extractedData = []; - var xValue, yValue; - var axis = this.yAxisLeft; - var svgHeight = Number(this.svg.style.height.replace("px","")); + Node.prototype.resetCluster = function() { + // clustering variables + this.formationScale = undefined; // this is used to determine when to open the cluster + this.clusterSize = 1; // this signifies the total amount of nodes in this cluster + this.containedNodes = {}; + this.containedEdges = {}; + this.clusterSessions = []; + }; - if (group.options.yAxisOrientation == 'right') { - axis = this.yAxisRight; + /** + * Attach a edge to the node + * @param {Edge} edge + */ + Node.prototype.attachEdge = function(edge) { + if (this.edges.indexOf(edge) == -1) { + this.edges.push(edge); } - - for (var i = 0; i < datapoints.length; i++) { - xValue = datapoints[i].x; - yValue = Math.round(axis.convertValue(datapoints[i].y)); - extractedData.push({x: xValue, y: yValue}); + if (this.dynamicEdges.indexOf(edge) == -1) { + this.dynamicEdges.push(edge); } - - group.setZeroPosition(Math.min(svgHeight, axis.convertValue(0))); - - // extractedData.sort(function (a,b) {return a.x - b.x;}); - return extractedData; + this.dynamicEdgesLength = this.dynamicEdges.length; }; - /** - * This uses an uniform parametrization of the CatmullRom algorithm: - * "On the Parameterization of Catmull-Rom Curves" by Cem Yuksel et al. - * @param data - * @returns {string} - * @private + * Detach a edge from the node + * @param {Edge} edge */ - LineGraph.prototype._catmullRomUniform = function(data) { - // catmull rom - var p0, p1, p2, p3, bp1, bp2; - var d = Math.round(data[0].x) + "," + Math.round(data[0].y) + " "; - var normalization = 1/6; - var length = data.length; - for (var i = 0; i < length - 1; i++) { - - p0 = (i == 0) ? data[0] : data[i-1]; - p1 = data[i]; - p2 = data[i+1]; - p3 = (i + 2 < length) ? data[i+2] : p2; - - - // Catmull-Rom to Cubic Bezier conversion matrix - // 0 1 0 0 - // -1/6 1 1/6 0 - // 0 1/6 1 -1/6 - // 0 0 1 0 - - // bp0 = { x: p1.x, y: p1.y }; - bp1 = { x: ((-p0.x + 6*p1.x + p2.x) *normalization), y: ((-p0.y + 6*p1.y + p2.y) *normalization)}; - bp2 = { x: (( p1.x + 6*p2.x - p3.x) *normalization), y: (( p1.y + 6*p2.y - p3.y) *normalization)}; - // bp0 = { x: p2.x, y: p2.y }; - - d += "C" + - bp1.x + "," + - bp1.y + " " + - bp2.x + "," + - bp2.y + " " + - p2.x + "," + - p2.y + " "; + Node.prototype.detachEdge = function(edge) { + var index = this.edges.indexOf(edge); + if (index != -1) { + this.edges.splice(index, 1); + this.dynamicEdges.splice(index, 1); } - - return d; + this.dynamicEdgesLength = this.dynamicEdges.length; }; + /** - * This uses either the chordal or centripetal parameterization of the catmull-rom algorithm. - * By default, the centripetal parameterization is used because this gives the nicest results. - * These parameterizations are relatively heavy because the distance between 4 points have to be calculated. - * - * One optimization can be used to reuse distances since this is a sliding window approach. - * @param data - * @returns {string} - * @private + * Set or overwrite properties for the node + * @param {Object} properties an object with properties + * @param {Object} constants and object with default, global properties */ - LineGraph.prototype._catmullRom = function(data, group) { - var alpha = group.options.catmullRom.alpha; - if (alpha == 0 || alpha === undefined) { - return this._catmullRomUniform(data); + Node.prototype.setProperties = function(properties, constants) { + if (!properties) { + return; } - else { - var p0, p1, p2, p3, bp1, bp2, d1,d2,d3, A, B, N, M; - var d3powA, d2powA, d3pow2A, d2pow2A, d1pow2A, d1powA; - var d = Math.round(data[0].x) + "," + Math.round(data[0].y) + " "; - var length = data.length; - for (var i = 0; i < length - 1; i++) { - - p0 = (i == 0) ? data[0] : data[i-1]; - p1 = data[i]; - p2 = data[i+1]; - p3 = (i + 2 < length) ? data[i+2] : p2; - d1 = Math.sqrt(Math.pow(p0.x - p1.x,2) + Math.pow(p0.y - p1.y,2)); - d2 = Math.sqrt(Math.pow(p1.x - p2.x,2) + Math.pow(p1.y - p2.y,2)); - d3 = Math.sqrt(Math.pow(p2.x - p3.x,2) + Math.pow(p2.y - p3.y,2)); + var fields = ['borderWidth','borderWidthSelected','shape','image','radius','fontColor', + 'fontSize','fontFace','group','mass' + ]; + util.selectiveDeepExtend(fields, this.options, properties); - // Catmull-Rom to Cubic Bezier conversion matrix - // - // A = 2d1^2a + 3d1^a * d2^a + d3^2a - // B = 2d3^2a + 3d3^a * d2^a + d2^2a - // - // [ 0 1 0 0 ] - // [ -d2^2a/N A/N d1^2a/N 0 ] - // [ 0 d3^2a/M B/M -d2^2a/M ] - // [ 0 0 1 0 ] + this.originalLabel = undefined; + // basic properties + if (properties.id !== undefined) {this.id = properties.id;} + if (properties.label !== undefined) {this.label = properties.label; this.originalLabel = properties.label;} + if (properties.title !== undefined) {this.title = properties.title;} + if (properties.x !== undefined) {this.x = properties.x;} + if (properties.y !== undefined) {this.y = properties.y;} + if (properties.value !== undefined) {this.value = properties.value;} + if (properties.level !== undefined) {this.level = properties.level; this.preassignedLevel = true;} - // [ 0 1 0 0 ] - // [ -d2pow2a/N A/N d1pow2a/N 0 ] - // [ 0 d3pow2a/M B/M -d2pow2a/M ] - // [ 0 0 1 0 ] + // navigation controls properties + if (properties.horizontalAlignLeft !== undefined) {this.horizontalAlignLeft = properties.horizontalAlignLeft;} + if (properties.verticalAlignTop !== undefined) {this.verticalAlignTop = properties.verticalAlignTop;} + if (properties.triggerFunction !== undefined) {this.triggerFunction = properties.triggerFunction;} - d3powA = Math.pow(d3, alpha); - d3pow2A = Math.pow(d3,2*alpha); - d2powA = Math.pow(d2, alpha); - d2pow2A = Math.pow(d2,2*alpha); - d1powA = Math.pow(d1, alpha); - d1pow2A = Math.pow(d1,2*alpha); + if (this.id === undefined) { + throw "Node must have an id"; + } - A = 2*d1pow2A + 3*d1powA * d2powA + d2pow2A; - B = 2*d3pow2A + 3*d3powA * d2powA + d2pow2A; - N = 3*d1powA * (d1powA + d2powA); - if (N > 0) {N = 1 / N;} - M = 3*d3powA * (d3powA + d2powA); - if (M > 0) {M = 1 / M;} + // copy group properties + if (typeof this.options.group === 'number' || (typeof this.options.group === 'string' && this.options.group != '')) { + var groupObj = this.grouplist.get(this.options.group); + for (var prop in groupObj) { + if (groupObj.hasOwnProperty(prop)) { + this.options[prop] = groupObj[prop]; + } + } + } - bp1 = { x: ((-d2pow2A * p0.x + A*p1.x + d1pow2A * p2.x) * N), - y: ((-d2pow2A * p0.y + A*p1.y + d1pow2A * p2.y) * N)}; - bp2 = { x: (( d3pow2A * p1.x + B*p2.x - d2pow2A * p3.x) * M), - y: (( d3pow2A * p1.y + B*p2.y - d2pow2A * p3.y) * M)}; + // individual shape properties + if (properties.radius !== undefined) {this.baseRadiusValue = this.options.radius;} + if (properties.color !== undefined) {this.options.color = util.parseColor(properties.color);} - if (bp1.x == 0 && bp1.y == 0) {bp1 = p1;} - if (bp2.x == 0 && bp2.y == 0) {bp2 = p2;} - d += "C" + - bp1.x + "," + - bp1.y + " " + - bp2.x + "," + - bp2.y + " " + - p2.x + "," + - p2.y + " "; + if (this.options.image!== undefined && this.options.image!= "") { + if (this.imagelist) { + this.imageObj = this.imagelist.load(this.options.image); + } + else { + throw "No imagelist provided"; } + } - return d; + this.xFixed = this.xFixed || (properties.x !== undefined && !properties.allowedToMoveX); + this.yFixed = this.yFixed || (properties.y !== undefined && !properties.allowedToMoveY); + this.radiusFixed = this.radiusFixed || (properties.radius !== undefined); + + if (this.options.shape == 'image') { + this.options.radiusMin = constants.nodes.widthMin; + this.options.radiusMax = constants.nodes.widthMax; + } + + + // choose draw method depending on the shape + switch (this.options.shape) { + case 'database': this.draw = this._drawDatabase; this.resize = this._resizeDatabase; break; + case 'box': this.draw = this._drawBox; this.resize = this._resizeBox; break; + case 'circle': this.draw = this._drawCircle; this.resize = this._resizeCircle; break; + case 'ellipse': this.draw = this._drawEllipse; this.resize = this._resizeEllipse; break; + // TODO: add diamond shape + case 'image': this.draw = this._drawImage; this.resize = this._resizeImage; break; + case 'text': this.draw = this._drawText; this.resize = this._resizeText; break; + case 'dot': this.draw = this._drawDot; this.resize = this._resizeShape; break; + case 'square': this.draw = this._drawSquare; this.resize = this._resizeShape; break; + case 'triangle': this.draw = this._drawTriangle; this.resize = this._resizeShape; break; + case 'triangleDown': this.draw = this._drawTriangleDown; this.resize = this._resizeShape; break; + case 'star': this.draw = this._drawStar; this.resize = this._resizeShape; break; + default: this.draw = this._drawEllipse; this.resize = this._resizeEllipse; break; } + // reset the size of the node, this can be changed + this._reset(); }; /** - * this generates the SVG path for a linear drawing between datapoints. - * @param data - * @returns {string} - * @private + * select this node */ - LineGraph.prototype._linear = function(data) { - // linear - var d = ""; - for (var i = 0; i < data.length; i++) { - if (i == 0) { - d += data[i].x + "," + data[i].y; - } - else { - d += " " + data[i].x + "," + data[i].y; - } - } - return d; + Node.prototype.select = function() { + this.selected = true; + this._reset(); }; - module.exports = LineGraph; - + /** + * unselect this node + */ + Node.prototype.unselect = function() { + this.selected = false; + this._reset(); + }; -/***/ }, -/* 37 */ -/***/ function(module, exports, __webpack_require__) { /** - * @constructor DataStep - * The class DataStep is an iterator for data for the lineGraph. You provide a start data point and an - * end data point. The class itself determines the best scale (step size) based on the - * provided start Date, end Date, and minimumStep. - * - * If minimumStep is provided, the step size is chosen as close as possible - * to the minimumStep but larger than minimumStep. If minimumStep is not - * provided, the scale is set to 1 DAY. - * The minimumStep should correspond with the onscreen size of about 6 characters - * - * Alternatively, you can set a scale by hand. - * After creation, you can initialize the class by executing first(). Then you - * can iterate from the start date to the end date via next(). You can check if - * the end date is reached with the function hasNext(). After each step, you can - * retrieve the current date via getCurrent(). - * The DataStep has scales ranging from milliseconds, seconds, minutes, hours, - * days, to years. - * - * Version: 1.2 - * - * @param {Date} [start] The start date, for example new Date(2010, 9, 21) - * or new Date(2010, 9, 21, 23, 45, 00) - * @param {Date} [end] The end date - * @param {Number} [minimumStep] Optional. Minimum step size in milliseconds + * Reset the calculated size of the node, forces it to recalculate its size */ - function DataStep(start, end, minimumStep, containerHeight, forcedStepSize) { - // variables - this.current = 0; - - this.autoScale = true; - this.stepIndex = 0; - this.step = 1; - this.scale = 1; - - this.marginStart; - this.marginEnd; - - this.majorSteps = [1, 2, 5, 10]; - this.minorSteps = [0.25, 0.5, 1, 2]; - - this.setRange(start, end, minimumStep, containerHeight, forcedStepSize); - } - - + Node.prototype.clearSizeCache = function() { + this._reset(); + }; /** - * Set a new range - * If minimumStep is provided, the step size is chosen as close as possible - * to the minimumStep but larger than minimumStep. If minimumStep is not - * provided, the scale is set to 1 DAY. - * The minimumStep should correspond with the onscreen size of about 6 characters - * @param {Number} [start] The start date and time. - * @param {Number} [end] The end date and time. - * @param {Number} [minimumStep] Optional. Minimum step size in milliseconds + * Reset the calculated size of the node, forces it to recalculate its size + * @private */ - DataStep.prototype.setRange = function(start, end, minimumStep, containerHeight, forcedStepSize) { - this._start = start; - this._end = end; - - if (start == end) { - this._start = start - 0.75; - this._end = end + 1; - } - - if (this.autoScale) { - this.setMinimumStep(minimumStep, containerHeight, forcedStepSize); - } - this.setFirst(); + Node.prototype._reset = function() { + this.width = undefined; + this.height = undefined; }; /** - * Automatically determine the scale that bests fits the provided minimum step - * @param {Number} [minimumStep] The minimum step size in milliseconds + * get the title of this node. + * @return {string} title The title of the node, or undefined when no title + * has been set. */ - DataStep.prototype.setMinimumStep = function(minimumStep, containerHeight) { - // round to floor - var size = this._end - this._start; - var safeSize = size * 1.1; - var minimumStepValue = minimumStep * (safeSize / containerHeight); - var orderOfMagnitude = Math.round(Math.log(safeSize)/Math.LN10); + Node.prototype.getTitle = function() { + return typeof this.title === "function" ? this.title() : this.title; + }; - var minorStepIdx = -1; - var magnitudefactor = Math.pow(10,orderOfMagnitude); + /** + * Calculate the distance to the border of the Node + * @param {CanvasRenderingContext2D} ctx + * @param {Number} angle Angle in radians + * @returns {number} distance Distance to the border in pixels + */ + Node.prototype.distanceToBorder = function (ctx, angle) { + var borderWidth = 1; - var start = 0; - if (orderOfMagnitude < 0) { - start = orderOfMagnitude; + if (!this.width) { + this.resize(ctx); } - var solutionFound = false; - for (var i = start; Math.abs(i) <= Math.abs(orderOfMagnitude); i++) { - magnitudefactor = Math.pow(10,i); - for (var j = 0; j < this.minorSteps.length; j++) { - var stepSize = magnitudefactor * this.minorSteps[j]; - if (stepSize >= minimumStepValue) { - solutionFound = true; - minorStepIdx = j; - break; + switch (this.options.shape) { + case 'circle': + case 'dot': + return this.options.radius+ borderWidth; + + case 'ellipse': + var a = this.width / 2; + var b = this.height / 2; + var w = (Math.sin(angle) * a); + var h = (Math.cos(angle) * b); + return a * b / Math.sqrt(w * w + h * h); + + // TODO: implement distanceToBorder for database + // TODO: implement distanceToBorder for triangle + // TODO: implement distanceToBorder for triangleDown + + case 'box': + case 'image': + case 'text': + default: + if (this.width) { + return Math.min( + Math.abs(this.width / 2 / Math.cos(angle)), + Math.abs(this.height / 2 / Math.sin(angle))) + borderWidth; + // TODO: reckon with border radius too in case of box } - } - if (solutionFound == true) { - break; - } + else { + return 0; + } + } - this.stepIndex = minorStepIdx; - this.scale = magnitudefactor; - this.step = magnitudefactor * this.minorSteps[minorStepIdx]; + // TODO: implement calculation of distance to border for all shapes }; + /** + * Set forces acting on the node + * @param {number} fx Force in horizontal direction + * @param {number} fy Force in vertical direction + */ + Node.prototype._setForce = function(fx, fy) { + this.fx = fx; + this.fy = fy; + }; /** - * Set the range iterator to the start date. + * Add forces acting on the node + * @param {number} fx Force in horizontal direction + * @param {number} fy Force in vertical direction + * @private */ - DataStep.prototype.first = function() { - this.setFirst(); + Node.prototype._addForce = function(fx, fy) { + this.fx += fx; + this.fy += fy; }; /** - * Round the current date to the first minor date value - * This must be executed once when the current date is set to start Date + * Perform one discrete step for the node + * @param {number} interval Time interval in seconds */ - DataStep.prototype.setFirst = function() { - var niceStart = this._start - (this.scale * this.minorSteps[this.stepIndex]); - var niceEnd = this._end + (this.scale * this.minorSteps[this.stepIndex]); + Node.prototype.discreteStep = function(interval) { + if (!this.xFixed) { + var dx = this.damping * this.vx; // damping force + var ax = (this.fx - dx) / this.options.mass; // acceleration + this.vx += ax * interval; // velocity + this.x += this.vx * interval; // position + } - this.marginEnd = this.roundToMinor(niceEnd); - this.marginStart = this.roundToMinor(niceStart); - this.marginRange = this.marginEnd - this.marginStart; + if (!this.yFixed) { + var dy = this.damping * this.vy; // damping force + var ay = (this.fy - dy) / this.options.mass; // acceleration + this.vy += ay * interval; // velocity + this.y += this.vy * interval; // position + } + }; - this.current = this.marginEnd; - }; - DataStep.prototype.roundToMinor = function(value) { - var rounded = value - (value % (this.scale * this.minorSteps[this.stepIndex])); - if (value % (this.scale * this.minorSteps[this.stepIndex]) > 0.5 * (this.scale * this.minorSteps[this.stepIndex])) { - return rounded + (this.scale * this.minorSteps[this.stepIndex]); + /** + * Perform one discrete step for the node + * @param {number} interval Time interval in seconds + * @param {number} maxVelocity The speed limit imposed on the velocity + */ + Node.prototype.discreteStepLimited = function(interval, maxVelocity) { + if (!this.xFixed) { + var dx = this.damping * this.vx; // damping force + var ax = (this.fx - dx) / this.options.mass; // acceleration + this.vx += ax * interval; // velocity + this.vx = (Math.abs(this.vx) > maxVelocity) ? ((this.vx > 0) ? maxVelocity : -maxVelocity) : this.vx; + this.x += this.vx * interval; // position } else { - return rounded; + this.fx = 0; } - } + if (!this.yFixed) { + var dy = this.damping * this.vy; // damping force + var ay = (this.fy - dy) / this.options.mass; // acceleration + this.vy += ay * interval; // velocity + this.vy = (Math.abs(this.vy) > maxVelocity) ? ((this.vy > 0) ? maxVelocity : -maxVelocity) : this.vy; + this.y += this.vy * interval; // position + } + else { + this.fy = 0; + } + }; /** - * Check if the there is a next step - * @return {boolean} true if the current date has not passed the end date + * Check if this node has a fixed x and y position + * @return {boolean} true if fixed, false if not */ - DataStep.prototype.hasNext = function () { - return (this.current >= this.marginStart); + Node.prototype.isFixed = function() { + return (this.xFixed && this.yFixed); }; /** - * Do the next step + * Check if this node is moving + * @param {number} vmin the minimum velocity considered as "moving" + * @return {boolean} true if moving, false if it has no velocity */ - DataStep.prototype.next = function() { - var prev = this.current; - this.current -= this.step; - - // safety mechanism: if current time is still unchanged, move to the end - if (this.current == prev) { - this.current = this._end; - } + Node.prototype.isMoving = function(vmin) { + var velocity = Math.sqrt(Math.pow(this.vx,2) + Math.pow(this.vy,2)); + // this.velocity = Math.sqrt(Math.pow(this.vx,2) + Math.pow(this.vy,2)) + return (velocity > vmin); }; /** - * Do the next step + * check if this node is selecte + * @return {boolean} selected True if node is selected, else false */ - DataStep.prototype.previous = function() { - this.current += this.step; - this.marginEnd += this.step; - this.marginRange = this.marginEnd - this.marginStart; + Node.prototype.isSelected = function() { + return this.selected; }; - - /** - * Get the current datetime - * @return {String} current The current date + * Retrieve the value of the node. Can be undefined + * @return {Number} value */ - DataStep.prototype.getCurrent = function() { - var toPrecision = '' + Number(this.current).toPrecision(5); - for (var i = toPrecision.length-1; i > 0; i--) { - if (toPrecision[i] == "0") { - toPrecision = toPrecision.slice(0,i); - } - else if (toPrecision[i] == "." || toPrecision[i] == ",") { - toPrecision = toPrecision.slice(0,i); - break; - } - else{ - break; - } - } + Node.prototype.getValue = function() { + return this.value; + }; - return toPrecision; + /** + * Calculate the distance from the nodes location to the given location (x,y) + * @param {Number} x + * @param {Number} y + * @return {Number} value + */ + Node.prototype.getDistance = function(x, y) { + var dx = this.x - x, + dy = this.y - y; + return Math.sqrt(dx * dx + dy * dy); }; + /** + * Adjust the value range of the node. The node will adjust it's radius + * based on its value. + * @param {Number} min + * @param {Number} max + */ + Node.prototype.setValueRange = function(min, max) { + if (!this.radiusFixed && this.value !== undefined) { + if (max == min) { + this.options.radius= (this.options.radiusMin + this.options.radiusMax) / 2; + } + else { + var scale = (this.options.radiusMax - this.options.radiusMin) / (max - min); + this.options.radius= (this.value - min) * scale + this.options.radiusMin; + } + } + this.baseRadiusValue = this.options.radius; + }; /** - * Snap a date to a rounded value. - * The snap intervals are dependent on the current scale and step. - * @param {Date} date the date to be snapped. - * @return {Date} snappedDate + * Draw this node in the given canvas + * The 2d context of a HTML canvas can be retrieved by canvas.getContext("2d"); + * @param {CanvasRenderingContext2D} ctx */ - DataStep.prototype.snap = function(date) { + Node.prototype.draw = function(ctx) { + throw "Draw method not initialized for node"; + }; + /** + * Recalculate the size of this node in the given canvas + * The 2d context of a HTML canvas can be retrieved by canvas.getContext("2d"); + * @param {CanvasRenderingContext2D} ctx + */ + Node.prototype.resize = function(ctx) { + throw "Resize method not initialized for node"; }; /** - * Check if the current value is a major value (for example when the step - * is DAY, a major value is each first day of the MONTH) - * @return {boolean} true if current date is major, else false. + * Check if this object is overlapping with the provided object + * @param {Object} obj an object with parameters left, top, right, bottom + * @return {boolean} True if location is located on node */ - DataStep.prototype.isMajor = function() { - return (this.current % (this.scale * this.majorSteps[this.stepIndex]) == 0); + Node.prototype.isOverlappingWith = function(obj) { + return (this.left < obj.right && + this.left + this.width > obj.left && + this.top < obj.bottom && + this.top + this.height > obj.top); }; - module.exports = DataStep; + Node.prototype._resizeImage = function (ctx) { + // TODO: pre calculate the image size + if (!this.width || !this.height) { // undefined or 0 + var width, height; + if (this.value) { + this.options.radius= this.baseRadiusValue; + var scale = this.imageObj.height / this.imageObj.width; + if (scale !== undefined) { + width = this.options.radius|| this.imageObj.width; + height = this.options.radius* scale || this.imageObj.height; + } + else { + width = 0; + height = 0; + } + } + else { + width = this.imageObj.width; + height = this.imageObj.height; + } + this.width = width; + this.height = height; -/***/ }, -/* 38 */ -/***/ function(module, exports, __webpack_require__) { + this.growthIndicator = 0; + if (this.width > 0 && this.height > 0) { + this.width += Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * this.clusterSizeWidthFactor; + this.height += Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * this.clusterSizeHeightFactor; + this.options.radius+= Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * this.clusterSizeRadiusFactor; + this.growthIndicator = this.width - width; + } + } - var util = __webpack_require__(1); - var DOMutil = __webpack_require__(6); - var Component = __webpack_require__(22); - var DataStep = __webpack_require__(37); + }; - /** - * A horizontal time axis - * @param {Object} [options] See DataAxis.setOptions for the available - * options. - * @constructor DataAxis - * @extends Component - * @param body - */ - function DataAxis (body, options, svg) { - this.id = util.randomUUID(); - this.body = body; + Node.prototype._drawImage = function (ctx) { + this._resizeImage(ctx); - this.defaultOptions = { - orientation: 'left', // supported: 'left', 'right' - showMinorLabels: true, - showMajorLabels: true, - icons: true, - majorLinesOffset: 7, - minorLinesOffset: 4, - labelOffsetX: 10, - labelOffsetY: 2, - iconWidth: 20, - width: '40px', - visible: true - }; + this.left = this.x - this.width / 2; + this.top = this.y - this.height / 2; - this.linegraphSVG = svg; - this.props = {}; - this.DOMelements = { // dynamic elements - lines: {}, - labels: {} - }; + var yLabel; + if (this.imageObj.width != 0 ) { + // draw the shade + if (this.clusterSize > 1) { + var lineWidth = ((this.clusterSize > 1) ? 10 : 0.0); + lineWidth *= this.networkScaleInv; + lineWidth = Math.min(0.2 * this.width,lineWidth); - this.dom = {}; + ctx.globalAlpha = 0.5; + ctx.drawImage(this.imageObj, this.left - lineWidth, this.top - lineWidth, this.width + 2*lineWidth, this.height + 2*lineWidth); + } - this.range = {start:0, end:0}; + // draw the image + ctx.globalAlpha = 1.0; + ctx.drawImage(this.imageObj, this.left, this.top, this.width, this.height); + yLabel = this.y + this.height / 2; + } + else { + // image still loading... just draw the label for now + yLabel = this.y; + } - this.options = util.extend({}, this.defaultOptions); - this.conversionFactor = 1; + this._label(ctx, this.label, this.x, yLabel, undefined, "top"); + }; - this.setOptions(options); - this.width = Number(('' + this.options.width).replace("px","")); - this.minWidth = this.width; - this.height = this.linegraphSVG.offsetHeight; - this.stepPixels = 25; - this.stepPixelsForced = 25; - this.lineOffset = 0; - this.master = true; - this.svgElements = {}; + Node.prototype._resizeBox = function (ctx) { + if (!this.width) { + var margin = 5; + var textSize = this.getTextSize(ctx); + this.width = textSize.width + 2 * margin; + this.height = textSize.height + 2 * margin; + + this.width += Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * 0.5 * this.clusterSizeWidthFactor; + this.height += Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * 0.5 * this.clusterSizeHeightFactor; + this.growthIndicator = this.width - (textSize.width + 2 * margin); + // this.options.radius+= Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * 0.5 * this.clusterSizeRadiusFactor; + } + }; - this.groups = {}; - this.amountOfGroups = 0; + Node.prototype._drawBox = function (ctx) { + this._resizeBox(ctx); - // create the HTML DOM - this._create(); - } + this.left = this.x - this.width / 2; + this.top = this.y - this.height / 2; - DataAxis.prototype = new Component(); + var clusterLineWidth = 2.5; + var borderWidth = this.options.borderWidth; + var selectionLineWidth = this.options.borderWidthSelected || 2 * this.options.borderWidth; + ctx.strokeStyle = this.selected ? this.options.color.highlight.border : this.hover ? this.options.color.hover.border : this.options.color.border; + // draw the outer border + if (this.clusterSize > 1) { + ctx.lineWidth = (this.selected ? selectionLineWidth : borderWidth) + ((this.clusterSize > 1) ? clusterLineWidth : 0.0); + ctx.lineWidth *= this.networkScaleInv; + ctx.lineWidth = Math.min(this.width,ctx.lineWidth); - DataAxis.prototype.addGroup = function(label, graphOptions) { - if (!this.groups.hasOwnProperty(label)) { - this.groups[label] = graphOptions; + ctx.roundRect(this.left-2*ctx.lineWidth, this.top-2*ctx.lineWidth, this.width+4*ctx.lineWidth, this.height+4*ctx.lineWidth, this.options.radius); + ctx.stroke(); } - this.amountOfGroups += 1; - }; + ctx.lineWidth = (this.selected ? selectionLineWidth : borderWidth) + ((this.clusterSize > 1) ? clusterLineWidth : 0.0); + ctx.lineWidth *= this.networkScaleInv; + ctx.lineWidth = Math.min(this.width,ctx.lineWidth); - DataAxis.prototype.updateGroup = function(label, graphOptions) { - this.groups[label] = graphOptions; + ctx.fillStyle = this.selected ? this.options.color.highlight.background : this.options.color.background; + + ctx.roundRect(this.left, this.top, this.width, this.height, this.options.radius); + ctx.fill(); + ctx.stroke(); + + this._label(ctx, this.label, this.x, this.y); }; - DataAxis.prototype.removeGroup = function(label) { - if (this.groups.hasOwnProperty(label)) { - delete this.groups[label]; - this.amountOfGroups -= 1; + + Node.prototype._resizeDatabase = function (ctx) { + if (!this.width) { + var margin = 5; + var textSize = this.getTextSize(ctx); + var size = textSize.width + 2 * margin; + this.width = size; + this.height = size; + + // scaling used for clustering + this.width += Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * this.clusterSizeWidthFactor; + this.height += Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * this.clusterSizeHeightFactor; + this.options.radius+= Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * this.clusterSizeRadiusFactor; + this.growthIndicator = this.width - size; } }; + Node.prototype._drawDatabase = function (ctx) { + this._resizeDatabase(ctx); + this.left = this.x - this.width / 2; + this.top = this.y - this.height / 2; - DataAxis.prototype.setOptions = function (options) { - if (options) { - var redraw = false; - if (this.options.orientation != options.orientation && options.orientation !== undefined) { - redraw = true; - } - var fields = [ - 'orientation', - 'showMinorLabels', - 'showMajorLabels', - 'icons', - 'majorLinesOffset', - 'minorLinesOffset', - 'labelOffsetX', - 'labelOffsetY', - 'iconWidth', - 'width', - 'visible']; - util.selectiveExtend(fields, this.options, options); + var clusterLineWidth = 2.5; + var borderWidth = this.options.borderWidth; + var selectionLineWidth = this.options.borderWidthSelected || 2 * this.options.borderWidth; - this.minWidth = Number(('' + this.options.width).replace("px","")); + ctx.strokeStyle = this.selected ? this.options.color.highlight.border : this.hover ? this.options.color.hover.border : this.options.color.border; - if (redraw == true && this.dom.frame) { - this.hide(); - this.show(); - } + // draw the outer border + if (this.clusterSize > 1) { + ctx.lineWidth = (this.selected ? selectionLineWidth : borderWidth) + ((this.clusterSize > 1) ? clusterLineWidth : 0.0); + ctx.lineWidth *= this.networkScaleInv; + ctx.lineWidth = Math.min(this.width,ctx.lineWidth); + + ctx.database(this.x - this.width/2 - 2*ctx.lineWidth, this.y - this.height*0.5 - 2*ctx.lineWidth, this.width + 4*ctx.lineWidth, this.height + 4*ctx.lineWidth); + ctx.stroke(); } + ctx.lineWidth = (this.selected ? selectionLineWidth : borderWidth) + ((this.clusterSize > 1) ? clusterLineWidth : 0.0); + ctx.lineWidth *= this.networkScaleInv; + ctx.lineWidth = Math.min(this.width,ctx.lineWidth); + + ctx.fillStyle = this.selected ? this.options.color.highlight.background : this.hover ? this.options.color.hover.background : this.options.color.background; + ctx.database(this.x - this.width/2, this.y - this.height*0.5, this.width, this.height); + ctx.fill(); + ctx.stroke(); + + this._label(ctx, this.label, this.x, this.y); }; - /** - * Create the HTML DOM for the DataAxis - */ - DataAxis.prototype._create = function() { - this.dom.frame = document.createElement('div'); - this.dom.frame.style.width = this.options.width; - this.dom.frame.style.height = this.height; + Node.prototype._resizeCircle = function (ctx) { + if (!this.width) { + var margin = 5; + var textSize = this.getTextSize(ctx); + var diameter = Math.max(textSize.width, textSize.height) + 2 * margin; + this.options.radius = diameter / 2; - this.dom.lineContainer = document.createElement('div'); - this.dom.lineContainer.style.width = '100%'; - this.dom.lineContainer.style.height = this.height; + this.width = diameter; + this.height = diameter; - // create svg element for graph drawing. - this.svg = document.createElementNS('http://www.w3.org/2000/svg',"svg"); - this.svg.style.position = "absolute"; - this.svg.style.top = '0px'; - this.svg.style.height = '100%'; - this.svg.style.width = '100%'; - this.svg.style.display = "block"; - this.dom.frame.appendChild(this.svg); + // scaling used for clustering + // this.width += Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * 0.5 * this.clusterSizeWidthFactor; + // this.height += Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * 0.5 * this.clusterSizeHeightFactor; + this.options.radius += Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * 0.5 * this.clusterSizeRadiusFactor; + this.growthIndicator = this.options.radius- 0.5*diameter; + } }; - DataAxis.prototype._redrawGroupIcons = function () { - DOMutil.prepareElements(this.svgElements); + Node.prototype._drawCircle = function (ctx) { + this._resizeCircle(ctx); + this.left = this.x - this.width / 2; + this.top = this.y - this.height / 2; - var x; - var iconWidth = this.options.iconWidth; - var iconHeight = 15; - var iconOffset = 4; - var y = iconOffset + 0.5 * iconHeight; + var clusterLineWidth = 2.5; + var borderWidth = this.options.borderWidth; + var selectionLineWidth = this.options.borderWidthSelected || 2 * this.options.borderWidth; - if (this.options.orientation == 'left') { - x = iconOffset; - } - else { - x = this.width - iconWidth - iconOffset; - } + ctx.strokeStyle = this.selected ? this.options.color.highlight.border : this.hover ? this.options.color.hover.border : this.options.color.border; - for (var groupId in this.groups) { - if (this.groups.hasOwnProperty(groupId)) { - if (this.groups[groupId].visible == true) { - this.groups[groupId].drawIcon(x, y, this.svgElements, this.svg, iconWidth, iconHeight); - y += iconHeight + iconOffset; - } - } + // draw the outer border + if (this.clusterSize > 1) { + ctx.lineWidth = (this.selected ? selectionLineWidth : borderWidth) + ((this.clusterSize > 1) ? clusterLineWidth : 0.0); + ctx.lineWidth *= this.networkScaleInv; + ctx.lineWidth = Math.min(this.width,ctx.lineWidth); + + ctx.circle(this.x, this.y, this.options.radius+2*ctx.lineWidth); + ctx.stroke(); } + ctx.lineWidth = (this.selected ? selectionLineWidth : borderWidth) + ((this.clusterSize > 1) ? clusterLineWidth : 0.0); + ctx.lineWidth *= this.networkScaleInv; + ctx.lineWidth = Math.min(this.width,ctx.lineWidth); - DOMutil.cleanupElements(this.svgElements); + ctx.fillStyle = this.selected ? this.options.color.highlight.background : this.hover ? this.options.color.hover.background : this.options.color.background; + ctx.circle(this.x, this.y, this.options.radius); + ctx.fill(); + ctx.stroke(); + + this._label(ctx, this.label, this.x, this.y); }; - /** - * Create the HTML DOM for the DataAxis - */ - DataAxis.prototype.show = function() { - if (!this.dom.frame.parentNode) { - if (this.options.orientation == 'left') { - this.body.dom.left.appendChild(this.dom.frame); - } - else { - this.body.dom.right.appendChild(this.dom.frame); + Node.prototype._resizeEllipse = function (ctx) { + if (!this.width) { + var textSize = this.getTextSize(ctx); + + this.width = textSize.width * 1.5; + this.height = textSize.height * 2; + if (this.width < this.height) { + this.width = this.height; } - } + var defaultSize = this.width; - if (!this.dom.lineContainer.parentNode) { - this.body.dom.backgroundHorizontal.appendChild(this.dom.lineContainer); + // scaling used for clustering + this.width += Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * this.clusterSizeWidthFactor; + this.height += Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * this.clusterSizeHeightFactor; + this.options.radius += Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * this.clusterSizeRadiusFactor; + this.growthIndicator = this.width - defaultSize; } }; - /** - * Create the HTML DOM for the DataAxis - */ - DataAxis.prototype.hide = function() { - if (this.dom.frame.parentNode) { - this.dom.frame.parentNode.removeChild(this.dom.frame); - } + Node.prototype._drawEllipse = function (ctx) { + this._resizeEllipse(ctx); + this.left = this.x - this.width / 2; + this.top = this.y - this.height / 2; - if (this.dom.lineContainer.parentNode) { - this.dom.lineContainer.parentNode.removeChild(this.dom.lineContainer); - } - }; + var clusterLineWidth = 2.5; + var borderWidth = this.options.borderWidth; + var selectionLineWidth = this.options.borderWidthSelected || 2 * this.options.borderWidth; - /** - * Set a range (start and end) - * @param end - * @param start - * @param end - */ - DataAxis.prototype.setRange = function (start, end) { - this.range.start = start; - this.range.end = end; - }; + ctx.strokeStyle = this.selected ? this.options.color.highlight.border : this.hover ? this.options.color.hover.border : this.options.color.border; - /** - * Repaint the component - * @return {boolean} Returns true if the component is resized - */ - DataAxis.prototype.redraw = function () { - var changeCalled = false; - var activeGroups = 0; - for (var groupId in this.groups) { - if (this.groups.hasOwnProperty(groupId)) { - if (this.groups[groupId].visible == true) { - activeGroups++; - } - } - } - if (this.amountOfGroups == 0 || activeGroups == 0) { - this.hide(); + // draw the outer border + if (this.clusterSize > 1) { + ctx.lineWidth = (this.selected ? selectionLineWidth : borderWidth) + ((this.clusterSize > 1) ? clusterLineWidth : 0.0); + ctx.lineWidth *= this.networkScaleInv; + ctx.lineWidth = Math.min(this.width,ctx.lineWidth); + + ctx.ellipse(this.left-2*ctx.lineWidth, this.top-2*ctx.lineWidth, this.width+4*ctx.lineWidth, this.height+4*ctx.lineWidth); + ctx.stroke(); } - else { - this.show(); - this.height = Number(this.linegraphSVG.style.height.replace("px","")); - // svg offsetheight did not work in firefox and explorer... + ctx.lineWidth = (this.selected ? selectionLineWidth : borderWidth) + ((this.clusterSize > 1) ? clusterLineWidth : 0.0); + ctx.lineWidth *= this.networkScaleInv; + ctx.lineWidth = Math.min(this.width,ctx.lineWidth); - this.dom.lineContainer.style.height = this.height + 'px'; - this.width = this.options.visible == true ? Number(('' + this.options.width).replace("px","")) : 0; + ctx.fillStyle = this.selected ? this.options.color.highlight.background : this.hover ? this.options.color.hover.background : this.options.color.background; - var props = this.props; - var frame = this.dom.frame; + ctx.ellipse(this.left, this.top, this.width, this.height); + ctx.fill(); + ctx.stroke(); + this._label(ctx, this.label, this.x, this.y); + }; - // update classname - frame.className = 'dataaxis'; + Node.prototype._drawDot = function (ctx) { + this._drawShape(ctx, 'circle'); + }; - // calculate character width and height - this._calculateCharSize(); + Node.prototype._drawTriangle = function (ctx) { + this._drawShape(ctx, 'triangle'); + }; - var orientation = this.options.orientation; - var showMinorLabels = this.options.showMinorLabels; - var showMajorLabels = this.options.showMajorLabels; + Node.prototype._drawTriangleDown = function (ctx) { + this._drawShape(ctx, 'triangleDown'); + }; - // determine the width and height of the elemens for the axis - props.minorLabelHeight = showMinorLabels ? props.minorCharHeight : 0; - props.majorLabelHeight = showMajorLabels ? props.majorCharHeight : 0; + Node.prototype._drawSquare = function (ctx) { + this._drawShape(ctx, 'square'); + }; - props.minorLineWidth = this.body.dom.backgroundHorizontal.offsetWidth - this.lineOffset - this.width + 2 * this.options.minorLinesOffset; - props.minorLineHeight = 1; - props.majorLineWidth = this.body.dom.backgroundHorizontal.offsetWidth - this.lineOffset - this.width + 2 * this.options.majorLinesOffset; - props.majorLineHeight = 1; + Node.prototype._drawStar = function (ctx) { + this._drawShape(ctx, 'star'); + }; - // take frame offline while updating (is almost twice as fast) - if (orientation == 'left') { - frame.style.top = '0'; - frame.style.left = '0'; - frame.style.bottom = ''; - frame.style.width = this.width + 'px'; - frame.style.height = this.height + "px"; - } - else { // right - frame.style.top = ''; - frame.style.bottom = '0'; - frame.style.left = '0'; - frame.style.width = this.width + 'px'; - frame.style.height = this.height + "px"; - } - changeCalled = this._redrawLabels(); - if (this.options.icons == true) { - this._redrawGroupIcons(); - } + Node.prototype._resizeShape = function (ctx) { + if (!this.width) { + this.options.radius= this.baseRadiusValue; + var size = 2 * this.options.radius; + this.width = size; + this.height = size; + + // scaling used for clustering + this.width += Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * this.clusterSizeWidthFactor; + this.height += Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * this.clusterSizeHeightFactor; + this.options.radius+= Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * 0.5 * this.clusterSizeRadiusFactor; + this.growthIndicator = this.width - size; } - return changeCalled; }; - /** - * Repaint major and minor text labels and vertical grid lines - * @private - */ - DataAxis.prototype._redrawLabels = function () { - DOMutil.prepareElements(this.DOMelements.lines); - DOMutil.prepareElements(this.DOMelements.labels); + Node.prototype._drawShape = function (ctx, shape) { + this._resizeShape(ctx); - var orientation = this.options['orientation']; + this.left = this.x - this.width / 2; + this.top = this.y - this.height / 2; - // calculate range and step (step such that we have space for 7 characters per label) - var minimumStep = this.master ? this.props.majorCharHeight || 10 : this.stepPixelsForced; - var step = new DataStep(this.range.start, this.range.end, minimumStep, this.dom.frame.offsetHeight); - this.step = step; - step.first(); - // get the distance in pixels for a step - var stepPixels = this.dom.frame.offsetHeight / ((step.marginRange / step.step) + 1); - this.stepPixels = stepPixels; + var clusterLineWidth = 2.5; + var borderWidth = this.options.borderWidth; + var selectionLineWidth = this.options.borderWidthSelected || 2 * this.options.borderWidth; + var radiusMultiplier = 2; - var amountOfSteps = this.height / stepPixels; - var stepDifference = 0; + // choose draw method depending on the shape + switch (shape) { + case 'dot': radiusMultiplier = 2; break; + case 'square': radiusMultiplier = 2; break; + case 'triangle': radiusMultiplier = 3; break; + case 'triangleDown': radiusMultiplier = 3; break; + case 'star': radiusMultiplier = 4; break; + } - if (this.master == false) { - stepPixels = this.stepPixelsForced; - stepDifference = Math.round((this.height / stepPixels) - amountOfSteps); - for (var i = 0; i < 0.5 * stepDifference; i++) { - step.previous(); - } - amountOfSteps = this.height / stepPixels; + ctx.strokeStyle = this.selected ? this.options.color.highlight.border : this.hover ? this.options.color.hover.border : this.options.color.border; + // draw the outer border + if (this.clusterSize > 1) { + ctx.lineWidth = (this.selected ? selectionLineWidth : borderWidth) + ((this.clusterSize > 1) ? clusterLineWidth : 0.0); + ctx.lineWidth *= this.networkScaleInv; + ctx.lineWidth = Math.min(this.width,ctx.lineWidth); + + ctx[shape](this.x, this.y, this.options.radius+ radiusMultiplier * ctx.lineWidth); + ctx.stroke(); } + ctx.lineWidth = (this.selected ? selectionLineWidth : borderWidth) + ((this.clusterSize > 1) ? clusterLineWidth : 0.0); + ctx.lineWidth *= this.networkScaleInv; + ctx.lineWidth = Math.min(this.width,ctx.lineWidth); + ctx.fillStyle = this.selected ? this.options.color.highlight.background : this.hover ? this.options.color.hover.background : this.options.color.background; + ctx[shape](this.x, this.y, this.options.radius); + ctx.fill(); + ctx.stroke(); - this.valueAtZero = step.marginEnd; - var marginStartPos = 0; + if (this.label) { + this._label(ctx, this.label, this.x, this.y + this.height / 2, undefined, 'top',true); + } + }; - // do not draw the first label - var max = 1; - step.next(); + Node.prototype._resizeText = function (ctx) { + if (!this.width) { + var margin = 5; + var textSize = this.getTextSize(ctx); + this.width = textSize.width + 2 * margin; + this.height = textSize.height + 2 * margin; - this.maxLabelSize = 0; - var y = 0; - while (max < Math.round(amountOfSteps)) { + // scaling used for clustering + this.width += Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * this.clusterSizeWidthFactor; + this.height += Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * this.clusterSizeHeightFactor; + this.options.radius+= Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * this.clusterSizeRadiusFactor; + this.growthIndicator = this.width - (textSize.width + 2 * margin); + } + }; - y = Math.round(max * stepPixels); - marginStartPos = max * stepPixels; - var isMajor = step.isMajor(); + Node.prototype._drawText = function (ctx) { + this._resizeText(ctx); + this.left = this.x - this.width / 2; + this.top = this.y - this.height / 2; - if (this.options['showMinorLabels'] && isMajor == false || this.master == false && this.options['showMinorLabels'] == true) { - this._redrawLabel(y - 2, step.getCurrent(), orientation, 'yAxis minor', this.props.minorCharHeight); - } + this._label(ctx, this.label, this.x, this.y); + }; - if (isMajor && this.options['showMajorLabels'] && this.master == true || - this.options['showMinorLabels'] == false && this.master == false && isMajor == true) { - if (y >= 0) { - this._redrawLabel(y - 2, step.getCurrent(), orientation, 'yAxis major', this.props.majorCharHeight); - } - this._redrawLine(y, orientation, 'grid horizontal major', this.options.majorLinesOffset, this.props.majorLineWidth); - } - else { - this._redrawLine(y, orientation, 'grid horizontal minor', this.options.minorLinesOffset, this.props.minorLineWidth); + + Node.prototype._label = function (ctx, text, x, y, align, baseline, labelUnderNode) { + if (text && Number(this.options.fontSize) * this.networkScale > this.fontDrawThreshold) { + ctx.font = (this.selected ? "bold " : "") + this.options.fontSize + "px " + this.options.fontFace; + ctx.fillStyle = this.options.fontColor || "black"; + ctx.textAlign = align || "center"; + ctx.textBaseline = baseline || "middle"; + + var lines = text.split('\n'); + var lineCount = lines.length; + var fontSize = (Number(this.options.fontSize) + 4); + var yLine = y + (1 - lineCount) / 2 * fontSize; + if (labelUnderNode == true) { + yLine = y + (1 - lineCount) / (2 * fontSize); } - step.next(); - max++; + for (var i = 0; i < lineCount; i++) { + ctx.fillText(lines[i], x, yLine); + yLine += fontSize; + } } + }; - this.conversionFactor = marginStartPos/((amountOfSteps-1) * step.step); - var offset = this.options.icons == true ? this.options.iconWidth + this.options.labelOffsetX + 15 : this.options.labelOffsetX + 15; - // this will resize the yAxis to accomodate the labels. - if (this.maxLabelSize > (this.width - offset) && this.options.visible == true) { - this.width = this.maxLabelSize + offset; - this.options.width = this.width + "px"; - DOMutil.cleanupElements(this.DOMelements.lines); - DOMutil.cleanupElements(this.DOMelements.labels); - this.redraw(); - return true; - } - // this will resize the yAxis if it is too big for the labels. - else if (this.maxLabelSize < (this.width - offset) && this.options.visible == true && this.width > this.minWidth) { - this.width = Math.max(this.minWidth,this.maxLabelSize + offset); - this.options.width = this.width + "px"; - DOMutil.cleanupElements(this.DOMelements.lines); - DOMutil.cleanupElements(this.DOMelements.labels); - this.redraw(); - return true; + Node.prototype.getTextSize = function(ctx) { + if (this.label !== undefined) { + ctx.font = (this.selected ? "bold " : "") + this.options.fontSize + "px " + this.options.fontFace; + + var lines = this.label.split('\n'), + height = (Number(this.options.fontSize) + 4) * lines.length, + width = 0; + + for (var i = 0, iMax = lines.length; i < iMax; i++) { + width = Math.max(width, ctx.measureText(lines[i]).width); + } + + return {"width": width, "height": height}; } else { - DOMutil.cleanupElements(this.DOMelements.lines); - DOMutil.cleanupElements(this.DOMelements.labels); - return false; + return {"width": 0, "height": 0}; } }; /** - * Create a label for the axis at position x - * @private - * @param y - * @param text - * @param orientation - * @param className - * @param characterHeight + * this is used to determine if a node is visible at all. this is used to determine when it needs to be drawn. + * there is a safety margin of 0.3 * width; + * + * @returns {boolean} */ - DataAxis.prototype._redrawLabel = function (y, text, orientation, className, characterHeight) { - // reuse redundant label - var label = DOMutil.getDOMElement('div',this.DOMelements.labels, this.dom.frame); //this.dom.redundant.labels.shift(); - label.className = className; - label.innerHTML = text; - if (orientation == 'left') { - label.style.left = '-' + this.options.labelOffsetX + 'px'; - label.style.textAlign = "right"; + Node.prototype.inArea = function() { + if (this.width !== undefined) { + return (this.x + this.width *this.networkScaleInv >= this.canvasTopLeft.x && + this.x - this.width *this.networkScaleInv < this.canvasBottomRight.x && + this.y + this.height*this.networkScaleInv >= this.canvasTopLeft.y && + this.y - this.height*this.networkScaleInv < this.canvasBottomRight.y); } else { - label.style.right = '-' + this.options.labelOffsetX + 'px'; - label.style.textAlign = "left"; - } - - label.style.top = y - 0.5 * characterHeight + this.options.labelOffsetY + 'px'; - - text += ''; - - var largestWidth = Math.max(this.props.majorCharWidth,this.props.minorCharWidth); - if (this.maxLabelSize < text.length * largestWidth) { - this.maxLabelSize = text.length * largestWidth; + return true; } }; /** - * Create a minor line for the axis at position y - * @param y - * @param orientation - * @param className - * @param offset - * @param width + * checks if the core of the node is in the display area, this is used for opening clusters around zoom + * @returns {boolean} */ - DataAxis.prototype._redrawLine = function (y, orientation, className, offset, width) { - if (this.master == true) { - var line = DOMutil.getDOMElement('div',this.DOMelements.lines, this.dom.lineContainer);//this.dom.redundant.lines.shift(); - line.className = className; - line.innerHTML = ''; - - if (orientation == 'left') { - line.style.left = (this.width - offset) + 'px'; - } - else { - line.style.right = (this.width - offset) + 'px'; - } - - line.style.width = width + 'px'; - line.style.top = y + 'px'; - } + Node.prototype.inView = function() { + return (this.x >= this.canvasTopLeft.x && + this.x < this.canvasBottomRight.x && + this.y >= this.canvasTopLeft.y && + this.y < this.canvasBottomRight.y); }; - - DataAxis.prototype.convertValue = function (value) { - var invertedValue = this.valueAtZero - value; - var convertedValue = invertedValue * this.conversionFactor; - return convertedValue; // the -2 is to compensate for the borders + /** + * This allows the zoom level of the network to influence the rendering + * We store the inverted scale and the coordinates of the top left, and bottom right points of the canvas + * + * @param scale + * @param canvasTopLeft + * @param canvasBottomRight + */ + Node.prototype.setScaleAndPos = function(scale,canvasTopLeft,canvasBottomRight) { + this.networkScaleInv = 1.0/scale; + this.networkScale = scale; + this.canvasTopLeft = canvasTopLeft; + this.canvasBottomRight = canvasBottomRight; }; /** - * Determine the size of text on the axis (both major and minor axis). - * The size is calculated only once and then cached in this.props. - * @private + * This allows the zoom level of the network to influence the rendering + * + * @param scale */ - DataAxis.prototype._calculateCharSize = function () { - // determine the char width and height on the minor axis - if (!('minorCharHeight' in this.props)) { - var textMinor = document.createTextNode('0'); - var measureCharMinor = document.createElement('DIV'); - measureCharMinor.className = 'yAxis minor measure'; - measureCharMinor.appendChild(textMinor); - this.dom.frame.appendChild(measureCharMinor); - - this.props.minorCharHeight = measureCharMinor.clientHeight; - this.props.minorCharWidth = measureCharMinor.clientWidth; - - this.dom.frame.removeChild(measureCharMinor); - } + Node.prototype.setScale = function(scale) { + this.networkScaleInv = 1.0/scale; + this.networkScale = scale; + }; - if (!('majorCharHeight' in this.props)) { - var textMajor = document.createTextNode('0'); - var measureCharMajor = document.createElement('DIV'); - measureCharMajor.className = 'yAxis major measure'; - measureCharMajor.appendChild(textMajor); - this.dom.frame.appendChild(measureCharMajor); - this.props.majorCharHeight = measureCharMajor.clientHeight; - this.props.majorCharWidth = measureCharMajor.clientWidth; - this.dom.frame.removeChild(measureCharMajor); - } + /** + * set the velocity at 0. Is called when this node is contained in another during clustering + */ + Node.prototype.clearVelocity = function() { + this.vx = 0; + this.vy = 0; }; + /** - * Snap a date to a rounded value. - * The snap intervals are dependent on the current scale and step. - * @param {Date} date the date to be snapped. - * @return {Date} snappedDate + * Basic preservation of (kinectic) energy + * + * @param massBeforeClustering */ - DataAxis.prototype.snap = function(date) { - return this.step.snap(date); + Node.prototype.updateVelocity = function(massBeforeClustering) { + var energyBefore = this.vx * this.vx * massBeforeClustering; + //this.vx = (this.vx < 0) ? -Math.sqrt(energyBefore/this.options.mass) : Math.sqrt(energyBefore/this.options.mass); + this.vx = Math.sqrt(energyBefore/this.options.mass); + energyBefore = this.vy * this.vy * massBeforeClustering; + //this.vy = (this.vy < 0) ? -Math.sqrt(energyBefore/this.options.mass) : Math.sqrt(energyBefore/this.options.mass); + this.vy = Math.sqrt(energyBefore/this.options.mass); }; - module.exports = DataAxis; + module.exports = Node; /***/ }, -/* 39 */ +/* 37 */ /***/ function(module, exports, __webpack_require__) { - var util = __webpack_require__(1); - var DOMutil = __webpack_require__(6); - /** - * @constructor Group - * @param {Number | String} groupId - * @param {Object} data - * @param {ItemSet} itemSet + * Popup is a class to create a popup window with some text + * @param {Element} container The container object. + * @param {Number} [x] + * @param {Number} [y] + * @param {String} [text] + * @param {Object} [style] An object containing borderColor, + * backgroundColor, etc. */ - function GraphGroup (group, groupId, options, groupsUsingDefaultStyles) { - this.id = groupId; - var fields = ['sampling','style','sort','yAxisOrientation','barChart','drawPoints','shaded','catmullRom','slots'] - this.options = util.selectiveBridgeObject(fields,options); - this.usingDefaultStyle = group.className === undefined; - this.groupsUsingDefaultStyles = groupsUsingDefaultStyles; - this.zeroPosition = 0; - this.update(group); - if (this.usingDefaultStyle == true) { - this.groupsUsingDefaultStyles[0] += 1; + function Popup(container, x, y, text, style) { + if (container) { + this.container = container; + } + else { + this.container = document.body; } - this.itemsData = []; - this.visible = group.visible === undefined ? true : group.visible; - } - GraphGroup.prototype.setItems = function(items) { - if (items != null) { - this.itemsData = items; - if (this.options.sort == true) { - this.itemsData.sort(function (a,b) {return a.x - b.x;}) + // x, y and text are optional, see if a style object was passed in their place + if (style === undefined) { + if (typeof x === "object") { + style = x; + x = undefined; + } else if (typeof text === "object") { + style = text; + text = undefined; + } else { + // for backwards compatibility, in case clients other than Network are creating Popup directly + style = { + fontColor: 'black', + fontSize: 14, // px + fontFace: 'verdana', + color: { + border: '#666', + background: '#FFFFC6' + } + } } } - else { - this.itemsData = []; + + this.x = 0; + this.y = 0; + this.padding = 5; + + if (x !== undefined && y !== undefined ) { + this.setPosition(x, y); } + if (text !== undefined) { + this.setText(text); + } + + // create the frame + this.frame = document.createElement("div"); + var styleAttr = this.frame.style; + styleAttr.position = "absolute"; + styleAttr.visibility = "hidden"; + styleAttr.border = "1px solid " + style.color.border; + styleAttr.color = style.fontColor; + styleAttr.fontSize = style.fontSize + "px"; + styleAttr.fontFamily = style.fontFace; + styleAttr.padding = this.padding + "px"; + styleAttr.backgroundColor = style.color.background; + styleAttr.borderRadius = "3px"; + styleAttr.MozBorderRadius = "3px"; + styleAttr.WebkitBorderRadius = "3px"; + styleAttr.boxShadow = "3px 3px 10px rgba(128, 128, 128, 0.5)"; + styleAttr.whiteSpace = "nowrap"; + this.container.appendChild(this.frame); + } + + /** + * @param {number} x Horizontal position of the popup window + * @param {number} y Vertical position of the popup window + */ + Popup.prototype.setPosition = function(x, y) { + this.x = parseInt(x); + this.y = parseInt(y); }; - GraphGroup.prototype.setZeroPosition = function(pos) { - this.zeroPosition = pos; + /** + * Set the text for the popup window. This can be HTML code + * @param {string} text + */ + Popup.prototype.setText = function(text) { + this.frame.innerHTML = text; }; - GraphGroup.prototype.setOptions = function(options) { - if (options !== undefined) { - var fields = ['sampling','style','sort','yAxisOrientation','barChart','slots']; - util.selectiveDeepExtend(fields, this.options, options); + /** + * Show the popup window + * @param {boolean} show Optional. Show or hide the window + */ + Popup.prototype.show = function (show) { + if (show === undefined) { + show = true; + } - util.mergeOptions(this.options, options,'catmullRom'); - util.mergeOptions(this.options, options,'drawPoints'); - util.mergeOptions(this.options, options,'shaded'); + if (show) { + var height = this.frame.clientHeight; + var width = this.frame.clientWidth; + var maxHeight = this.frame.parentNode.clientHeight; + var maxWidth = this.frame.parentNode.clientWidth; - if (options.catmullRom) { - if (typeof options.catmullRom == 'object') { - if (options.catmullRom.parametrization) { - if (options.catmullRom.parametrization == 'uniform') { - this.options.catmullRom.alpha = 0; - } - else if (options.catmullRom.parametrization == 'chordal') { - this.options.catmullRom.alpha = 1.0; - } - else { - this.options.catmullRom.parametrization = 'centripetal'; - this.options.catmullRom.alpha = 0.5; - } - } - } + var top = (this.y - height); + if (top + height + this.padding > maxHeight) { + top = maxHeight - height - this.padding; + } + if (top < this.padding) { + top = this.padding; + } + + var left = this.x; + if (left + width + this.padding > maxWidth) { + left = maxWidth - width - this.padding; } + if (left < this.padding) { + left = this.padding; + } + + this.frame.style.left = left + "px"; + this.frame.style.top = top + "px"; + this.frame.style.visibility = "visible"; + } + else { + this.hide(); } }; - GraphGroup.prototype.update = function(group) { - this.group = group; - this.content = group.content || 'graph'; - this.className = group.className || this.className || "graphGroup" + this.groupsUsingDefaultStyles[0] % 10; - this.visible = group.visible === undefined ? true : group.visible; - this.setOptions(group.options); + /** + * Hide the popup window + */ + Popup.prototype.hide = function () { + this.frame.style.visibility = "hidden"; }; - GraphGroup.prototype.drawIcon = function(x, y, JSONcontainer, SVGcontainer, iconWidth, iconHeight) { - var fillHeight = iconHeight * 0.5; - var path, fillPath; - - var outline = DOMutil.getSVGElement("rect", JSONcontainer, SVGcontainer); - outline.setAttributeNS(null, "x", x); - outline.setAttributeNS(null, "y", y - fillHeight); - outline.setAttributeNS(null, "width", iconWidth); - outline.setAttributeNS(null, "height", 2*fillHeight); - outline.setAttributeNS(null, "class", "outline"); - - if (this.options.style == 'line') { - path = DOMutil.getSVGElement("path", JSONcontainer, SVGcontainer); - path.setAttributeNS(null, "class", this.className); - path.setAttributeNS(null, "d", "M" + x + ","+y+" L" + (x + iconWidth) + ","+y+""); - if (this.options.shaded.enabled == true) { - fillPath = DOMutil.getSVGElement("path", JSONcontainer, SVGcontainer); - if (this.options.shaded.orientation == 'top') { - fillPath.setAttributeNS(null, "d", "M"+x+", " + (y - fillHeight) + - "L"+x+","+y+" L"+ (x + iconWidth) + ","+y+" L"+ (x + iconWidth) + "," + (y - fillHeight)); - } - else { - fillPath.setAttributeNS(null, "d", "M"+x+","+y+" " + - "L"+x+"," + (y + fillHeight) + " " + - "L"+ (x + iconWidth) + "," + (y + fillHeight) + - "L"+ (x + iconWidth) + ","+y); - } - fillPath.setAttributeNS(null, "class", this.className + " iconFill"); - } - - if (this.options.drawPoints.enabled == true) { - DOMutil.drawPoint(x + 0.5 * iconWidth,y, this, JSONcontainer, SVGcontainer); - } - } - else { - var barWidth = Math.round(0.3 * iconWidth); - var bar1Height = Math.round(0.4 * iconHeight); - var bar2Height = Math.round(0.75 * iconHeight); - - var offset = Math.round((iconWidth - (2 * barWidth))/3); - - DOMutil.drawBar(x + 0.5*barWidth + offset , y + fillHeight - bar1Height - 1, barWidth, bar1Height, this.className + ' bar', JSONcontainer, SVGcontainer); - DOMutil.drawBar(x + 1.5*barWidth + offset + 2, y + fillHeight - bar2Height - 1, barWidth, bar2Height, this.className + ' bar', JSONcontainer, SVGcontainer); - } - }; - - /** - * - * @param iconWidth - * @param iconHeight - * @returns {{icon: HTMLElement, label: (group.content|*|string), orientation: (.options.yAxisOrientation|*)}} - */ - GraphGroup.prototype.getLegend = function(iconWidth, iconHeight) { - var svg = document.createElementNS('http://www.w3.org/2000/svg',"svg"); - this.drawIcon(0,0.5*iconHeight,[],svg,iconWidth,iconHeight); - return {icon: svg, label: this.content, orientation:this.options.yAxisOrientation}; - } - - module.exports = GraphGroup; + module.exports = Popup; /***/ }, -/* 40 */ +/* 38 */ /***/ function(module, exports, __webpack_require__) { - var util = __webpack_require__(1); - var DOMutil = __webpack_require__(6); - var Component = __webpack_require__(22); - /** - * Legend for Graph2d + * Parse a text source containing data in DOT language into a JSON object. + * The object contains two lists: one with nodes and one with edges. + * + * DOT language reference: http://www.graphviz.org/doc/info/lang.html + * + * @param {String} data Text containing a graph in DOT-notation + * @return {Object} graph An object containing two parameters: + * {Object[]} nodes + * {Object[]} edges */ - function Legend(body, options, side) { - this.body = body; - this.defaultOptions = { - enabled: true, - icons: true, - iconSize: 20, - iconSpacing: 6, - left: { - visible: true, - position: 'top-left' // top/bottom - left,center,right - }, - right: { - visible: true, - position: 'top-left' // top/bottom - left,center,right - } - } - this.side = side; - this.options = util.extend({},this.defaultOptions); - - this.svgElements = {}; - this.dom = {}; - this.groups = {}; - this.amountOfGroups = 0; - this._create(); - - this.setOptions(options); + function parseDOT (data) { + dot = data; + return parseGraph(); } - Legend.prototype = new Component(); - - - Legend.prototype.addGroup = function(label, graphOptions) { - if (!this.groups.hasOwnProperty(label)) { - this.groups[label] = graphOptions; - } - this.amountOfGroups += 1; + // token types enumeration + var TOKENTYPE = { + NULL : 0, + DELIMITER : 1, + IDENTIFIER: 2, + UNKNOWN : 3 }; - Legend.prototype.updateGroup = function(label, graphOptions) { - this.groups[label] = graphOptions; - }; + // map with all delimiters + var DELIMITERS = { + '{': true, + '}': true, + '[': true, + ']': true, + ';': true, + '=': true, + ',': true, - Legend.prototype.removeGroup = function(label) { - if (this.groups.hasOwnProperty(label)) { - delete this.groups[label]; - this.amountOfGroups -= 1; - } + '->': true, + '--': true }; - Legend.prototype._create = function() { - this.dom.frame = document.createElement('div'); - this.dom.frame.className = 'legend'; - this.dom.frame.style.position = "absolute"; - this.dom.frame.style.top = "10px"; - this.dom.frame.style.display = "block"; + var dot = ''; // current dot file + var index = 0; // current index in dot file + var c = ''; // current token character in expr + var token = ''; // current token + var tokenType = TOKENTYPE.NULL; // type of the token - this.dom.textArea = document.createElement('div'); - this.dom.textArea.className = 'legendText'; - this.dom.textArea.style.position = "relative"; - this.dom.textArea.style.top = "0px"; + /** + * Get the first character from the dot file. + * The character is stored into the char c. If the end of the dot file is + * reached, the function puts an empty string in c. + */ + function first() { + index = 0; + c = dot.charAt(0); + } - this.svg = document.createElementNS('http://www.w3.org/2000/svg',"svg"); - this.svg.style.position = 'absolute'; - this.svg.style.top = 0 +'px'; - this.svg.style.width = this.options.iconSize + 5 + 'px'; + /** + * Get the next character from the dot file. + * The character is stored into the char c. If the end of the dot file is + * reached, the function puts an empty string in c. + */ + function next() { + index++; + c = dot.charAt(index); + } - this.dom.frame.appendChild(this.svg); - this.dom.frame.appendChild(this.dom.textArea); - }; + /** + * Preview the next character from the dot file. + * @return {String} cNext + */ + function nextPreview() { + return dot.charAt(index + 1); + } /** - * Hide the component from the DOM + * Test whether given character is alphabetic or numeric + * @param {String} c + * @return {Boolean} isAlphaNumeric */ - Legend.prototype.hide = function() { - // remove the frame containing the items - if (this.dom.frame.parentNode) { - this.dom.frame.parentNode.removeChild(this.dom.frame); - } - }; + var regexAlphaNumeric = /[a-zA-Z_0-9.:#]/; + function isAlphaNumeric(c) { + return regexAlphaNumeric.test(c); + } /** - * Show the component in the DOM (when not already visible). - * @return {Boolean} changed + * Merge all properties of object b into object b + * @param {Object} a + * @param {Object} b + * @return {Object} a */ - Legend.prototype.show = function() { - // show frame containing the items - if (!this.dom.frame.parentNode) { - this.body.dom.center.appendChild(this.dom.frame); + function merge (a, b) { + if (!a) { + a = {}; } - }; - Legend.prototype.setOptions = function(options) { - var fields = ['enabled','orientation','icons','left','right']; - util.selectiveDeepExtend(fields, this.options, options); - }; - - Legend.prototype.redraw = function() { - var activeGroups = 0; - for (var groupId in this.groups) { - if (this.groups.hasOwnProperty(groupId)) { - if (this.groups[groupId].visible == true) { - activeGroups++; + if (b) { + for (var name in b) { + if (b.hasOwnProperty(name)) { + a[name] = b[name]; } } } + return a; + } - if (this.options[this.side].visible == false || this.amountOfGroups == 0 || this.options.enabled == false || activeGroups == 0) { - this.hide(); - } - else { - this.show(); - if (this.options[this.side].position == 'top-left' || this.options[this.side].position == 'bottom-left') { - this.dom.frame.style.left = '4px'; - this.dom.frame.style.textAlign = "left"; - this.dom.textArea.style.textAlign = "left"; - this.dom.textArea.style.left = (this.options.iconSize + 15) + 'px'; - this.dom.textArea.style.right = ''; - this.svg.style.left = 0 +'px'; - this.svg.style.right = ''; + /** + * Set a value in an object, where the provided parameter name can be a + * path with nested parameters. For example: + * + * var obj = {a: 2}; + * setValue(obj, 'b.c', 3); // obj = {a: 2, b: {c: 3}} + * + * @param {Object} obj + * @param {String} path A parameter name or dot-separated parameter path, + * like "color.highlight.border". + * @param {*} value + */ + function setValue(obj, path, value) { + var keys = path.split('.'); + var o = obj; + while (keys.length) { + var key = keys.shift(); + if (keys.length) { + // this isn't the end point + if (!o[key]) { + o[key] = {}; + } + o = o[key]; } else { - this.dom.frame.style.right = '4px'; - this.dom.frame.style.textAlign = "right"; - this.dom.textArea.style.textAlign = "right"; - this.dom.textArea.style.right = (this.options.iconSize + 15) + 'px'; - this.dom.textArea.style.left = ''; - this.svg.style.right = 0 +'px'; - this.svg.style.left = ''; + // this is the end point + o[key] = value; } + } + } - if (this.options[this.side].position == 'top-left' || this.options[this.side].position == 'top-right') { - this.dom.frame.style.top = 4 - Number(this.body.dom.center.style.top.replace("px","")) + 'px'; - this.dom.frame.style.bottom = ''; - } - else { - this.dom.frame.style.bottom = 4 - Number(this.body.dom.center.style.top.replace("px","")) + 'px'; - this.dom.frame.style.top = ''; - } + /** + * Add a node to a graph object. If there is already a node with + * the same id, their attributes will be merged. + * @param {Object} graph + * @param {Object} node + */ + function addNode(graph, node) { + var i, len; + var current = null; - if (this.options.icons == false) { - this.dom.frame.style.width = this.dom.textArea.offsetWidth + 10 + 'px'; - this.dom.textArea.style.right = ''; - this.dom.textArea.style.left = ''; - this.svg.style.width = '0px'; - } - else { - this.dom.frame.style.width = this.options.iconSize + 15 + this.dom.textArea.offsetWidth + 10 + 'px' - this.drawLegendIcons(); - } + // find root graph (in case of subgraph) + var graphs = [graph]; // list with all graphs from current graph to root graph + var root = graph; + while (root.parent) { + graphs.push(root.parent); + root = root.parent; + } - var content = ''; - for (var groupId in this.groups) { - if (this.groups.hasOwnProperty(groupId)) { - if (this.groups[groupId].visible == true) { - content += this.groups[groupId].content + '
'; - } + // find existing node (at root level) by its id + if (root.nodes) { + for (i = 0, len = root.nodes.length; i < len; i++) { + if (node.id === root.nodes[i].id) { + current = root.nodes[i]; + break; } } - this.dom.textArea.innerHTML = content; - this.dom.textArea.style.lineHeight = ((0.75 * this.options.iconSize) + this.options.iconSpacing) + 'px'; } - }; - Legend.prototype.drawLegendIcons = function() { - if (this.dom.frame.parentNode) { - DOMutil.prepareElements(this.svgElements); - var padding = window.getComputedStyle(this.dom.frame).paddingTop; - var iconOffset = Number(padding.replace('px','')); - var x = iconOffset; - var iconWidth = this.options.iconSize; - var iconHeight = 0.75 * this.options.iconSize; - var y = iconOffset + 0.5 * iconHeight + 3; + if (!current) { + // this is a new node + current = { + id: node.id + }; + if (graph.node) { + // clone default attributes + current.attr = merge(current.attr, graph.node); + } + } - this.svg.style.width = iconWidth + 5 + iconOffset + 'px'; + // add node to this (sub)graph and all its parent graphs + for (i = graphs.length - 1; i >= 0; i--) { + var g = graphs[i]; - for (var groupId in this.groups) { - if (this.groups.hasOwnProperty(groupId)) { - if (this.groups[groupId].visible == true) { - this.groups[groupId].drawIcon(x, y, this.svgElements, this.svg, iconWidth, iconHeight); - y += iconHeight + this.options.iconSpacing; - } - } + if (!g.nodes) { + g.nodes = []; + } + if (g.nodes.indexOf(current) == -1) { + g.nodes.push(current); } - - DOMutil.cleanupElements(this.svgElements); } - }; - module.exports = Legend; + // merge attributes + if (node.attr) { + current.attr = merge(current.attr, node.attr); + } + } + /** + * Add an edge to a graph object + * @param {Object} graph + * @param {Object} edge + */ + function addEdge(graph, edge) { + if (!graph.edges) { + graph.edges = []; + } + graph.edges.push(edge); + if (graph.edge) { + var attr = merge({}, graph.edge); // clone default attributes + edge.attr = merge(attr, edge.attr); // merge attributes + } + } -/***/ }, -/* 41 */ -/***/ function(module, exports, __webpack_require__) { + /** + * Create an edge to a graph object + * @param {Object} graph + * @param {String | Number | Object} from + * @param {String | Number | Object} to + * @param {String} type + * @param {Object | null} attr + * @return {Object} edge + */ + function createEdge(graph, from, to, type, attr) { + var edge = { + from: from, + to: to, + type: type + }; - var Emitter = __webpack_require__(10); - var Hammer = __webpack_require__(18); - var mousetrap = __webpack_require__(42); - var util = __webpack_require__(1); - var hammerUtil = __webpack_require__(21); - var DataSet = __webpack_require__(7); - var DataView = __webpack_require__(8); - var dotparser = __webpack_require__(43); - var gephiParser = __webpack_require__(44); - var Groups = __webpack_require__(45); - var Images = __webpack_require__(46); - var Node = __webpack_require__(47); - var Edge = __webpack_require__(48); - var Popup = __webpack_require__(49); - var MixinLoader = __webpack_require__(50); + if (graph.edge) { + edge.attr = merge({}, graph.edge); // clone default attributes + } + edge.attr = merge(edge.attr || {}, attr); // merge attributes - // Load custom shapes into CanvasRenderingContext2D - __webpack_require__(61); + return edge; + } /** - * @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 + * Get next token in the current dot file. + * The token and token type are available as token and tokenType */ - function Network (container, data, options) { - if (!(this instanceof Network)) { - throw new SyntaxError('Constructor must be called with the new operator'); + function getToken() { + tokenType = TOKENTYPE.NULL; + token = ''; + + // skip over whitespaces + while (c == ' ' || c == '\t' || c == '\n' || c == '\r') { // space, tab, enter + next(); } - this._initializeMixinLoaders(); + do { + var isComment = false; - // create variables and set default values - this.containerElement = container; + // skip comment + if (c == '#') { + // find the previous non-space character + var i = index - 1; + while (dot.charAt(i) == ' ' || dot.charAt(i) == '\t') { + i--; + } + if (dot.charAt(i) == '\n' || dot.charAt(i) == '') { + // the # is at the start of a line, this is indeed a line comment + while (c != '' && c != '\n') { + next(); + } + isComment = true; + } + } + if (c == '/' && nextPreview() == '/') { + // skip line comment + while (c != '' && c != '\n') { + next(); + } + isComment = true; + } + if (c == '/' && nextPreview() == '*') { + // skip block comment + while (c != '') { + if (c == '*' && nextPreview() == '/') { + // end of block comment found. skip these last two characters + next(); + next(); + break; + } + else { + next(); + } + } + isComment = true; + } - // render and calculation settings - this.renderRefreshRate = 60; // hz (fps) - this.renderTimestep = 1000 / this.renderRefreshRate; // ms -- saves calculation later on - this.renderTime = 0.5 * this.renderTimestep; // measured time it takes to render a frame - this.maxPhysicsTicksPerRender = 3; // max amount of physics ticks per render step. - this.physicsDiscreteStepsize = 0.50; // discrete stepsize of the simulation + // skip over whitespaces + while (c == ' ' || c == '\t' || c == '\n' || c == '\r') { // space, tab, enter + next(); + } + } + while (isComment); - this.initializing = true; + // check for end of dot file + if (c == '') { + // token is still empty + tokenType = TOKENTYPE.DELIMITER; + return; + } - this.triggerFunctions = {add:null,edit:null,editEdge:null,connect:null,del:null}; + // check for delimiters consisting of 2 characters + var c2 = c + nextPreview(); + if (DELIMITERS[c2]) { + tokenType = TOKENTYPE.DELIMITER; + token = c2; + next(); + next(); + return; + } - // set constant values - this.defaultOptions = { - nodes: { - mass: 1, - radiusMin: 10, - radiusMax: 30, - radius: 10, - shape: 'ellipse', - image: undefined, - widthMin: 16, // px - widthMax: 64, // px - fixed: false, - fontColor: 'black', - fontSize: 14, // px - fontFace: 'verdana', - level: -1, - color: { - border: '#2B7CE9', - background: '#97C2FC', - highlight: { - border: '#2B7CE9', - background: '#D2E5FF' - }, - hover: { - border: '#2B7CE9', - background: '#D2E5FF' - } - }, - borderColor: '#2B7CE9', - backgroundColor: '#97C2FC', - highlightColor: '#D2E5FF', - group: undefined, - borderWidth: 1 - }, - edges: { - widthMin: 1, - widthMax: 15, - width: 1, - widthSelectionMultiplier: 2, - hoverWidth: 1.5, - style: 'line', - color: { - color:'#848484', - highlight:'#848484', - hover: '#848484' - }, - fontColor: '#343434', - fontSize: 14, // px - fontFace: 'arial', - fontFill: 'white', - arrowScaleFactor: 1, - dash: { - length: 10, - gap: 5, - altLength: undefined - }, - inheritColor: "from" // to, from, false, true (== from) - }, - configurePhysics:false, - physics: { - barnesHut: { - enabled: true, - theta: 1 / 0.6, // inverted to save time during calculation - gravitationalConstant: -2000, - centralGravity: 0.3, - springLength: 95, - springConstant: 0.04, - damping: 0.09 - }, - repulsion: { - centralGravity: 0.0, - springLength: 200, - springConstant: 0.05, - nodeDistance: 100, - damping: 0.09 - }, - hierarchicalRepulsion: { - enabled: false, - centralGravity: 0.0, - springLength: 100, - springConstant: 0.01, - nodeDistance: 150, - damping: 0.09 - }, - damping: null, - centralGravity: null, - springLength: null, - springConstant: null - }, - clustering: { // Per Node in Cluster = PNiC - enabled: false, // (Boolean) | global on/off switch for clustering. - initialMaxNodes: 100, // (# nodes) | if the initial amount of nodes is larger than this, we cluster until the total number is less than this threshold. - clusterThreshold:500, // (# nodes) | during calculate forces, we check if the total number of nodes is larger than this. If it is, cluster until reduced to reduceToNodes - reduceToNodes:300, // (# nodes) | during calculate forces, we check if the total number of nodes is larger than clusterThreshold. If it is, cluster until reduced to this - chainThreshold: 0.4, // (% of all drawn nodes)| maximum percentage of allowed chainnodes (long strings of connected nodes) within all nodes. (lower means less chains). - clusterEdgeThreshold: 20, // (px) | edge length threshold. if smaller, this node is clustered. - sectorThreshold: 100, // (# nodes in cluster) | cluster size threshold. If larger, expanding in own sector. - screenSizeThreshold: 0.2, // (% of canvas) | relative size threshold. If the width or height of a clusternode takes up this much of the screen, decluster node. - fontSizeMultiplier: 4.0, // (px PNiC) | how much the cluster font size grows per node in cluster (in px). - maxFontSize: 1000, - forceAmplification: 0.1, // (multiplier PNiC) | factor of increase fo the repulsion force of a cluster (per node in cluster). - distanceAmplification: 0.1, // (multiplier PNiC) | factor how much the repulsion distance of a cluster increases (per node in cluster). - edgeGrowth: 20, // (px PNiC) | amount of clusterSize connected to the edge is multiplied with this and added to edgeLength. - nodeScaling: {width: 1, // (px PNiC) | growth of the width per node in cluster. - height: 1, // (px PNiC) | growth of the height per node in cluster. - radius: 1}, // (px PNiC) | growth of the radius per node in cluster. - maxNodeSizeIncrements: 600, // (# increments) | max growth of the width per node in cluster. - activeAreaBoxSize: 80, // (px) | box area around the curser where clusters are popped open. - clusterLevelDifference: 2 - }, - navigation: { - enabled: false - }, - keyboard: { - enabled: false, - speed: {x: 10, y: 10, zoom: 0.02} - }, - dataManipulation: { - enabled: false, - initiallyVisible: false - }, - hierarchicalLayout: { - enabled:false, - levelSeparation: 150, - nodeSpacing: 100, - direction: "UD" // UD, DU, LR, RL - }, - freezeForStabilization: false, - smoothCurves: { - enabled: true, - dynamic: true, - type: "continuous", - roundness: 0.5 - }, - dynamicSmoothCurves: true, - maxVelocity: 30, - minVelocity: 0.1, // px/s - stabilize: true, // stabilize before displaying the network - stabilizationIterations: 1000, // maximum number of iteration to stabilize - labels:{ - add:"Add Node", - edit:"Edit", - link:"Add Link", - del:"Delete selected", - editNode:"Edit Node", - editEdge:"Edit Edge", - back:"Back", - addDescription:"Click in an empty space to place a new node.", - linkDescription:"Click on a node and drag the edge to another node to connect them.", - editEdgeDescription:"Click on the control points and drag them to a node to connect to it.", - addError:"The function for add does not support two arguments (data,callback).", - linkError:"The function for connect does not support two arguments (data,callback).", - editError:"The function for edit does not support two arguments (data, callback).", - editBoundError:"No edit function has been bound to this button.", - deleteError:"The function for delete does not support two arguments (data, callback).", - deleteClusterError:"Clusters cannot be deleted." - }, - tooltip: { - delay: 300, - fontColor: 'black', - fontSize: 14, // px - fontFace: 'verdana', - color: { - border: '#666', - background: '#FFFFC6' + // check for delimiters consisting of 1 character + if (DELIMITERS[c]) { + tokenType = TOKENTYPE.DELIMITER; + token = c; + next(); + return; + } + + // check for an identifier (number or string) + // TODO: more precise parsing of numbers/strings (and the port separator ':') + if (isAlphaNumeric(c) || c == '-') { + token += c; + next(); + + while (isAlphaNumeric(c)) { + token += c; + next(); + } + if (token == 'false') { + token = false; // convert to boolean + } + else if (token == 'true') { + token = true; // convert to boolean + } + else if (!isNaN(Number(token))) { + token = Number(token); // convert to number + } + tokenType = TOKENTYPE.IDENTIFIER; + return; + } + + // check for a string enclosed by double quotes + if (c == '"') { + next(); + while (c != '' && (c != '"' || (c == '"' && nextPreview() == '"'))) { + token += c; + if (c == '"') { // skip the escape character + next(); } - }, - dragNetwork: true, - dragNodes: true, - zoomable: true, - hover: false, - hideEdgesOnDrag: false, - hideNodesOnDrag: false, - width : '100%', - height : '100%', - selectable: true + next(); + } + if (c != '"') { + throw newSyntaxError('End of string " expected'); + } + next(); + tokenType = TOKENTYPE.IDENTIFIER; + return; + } + + // something unknown is found, wrong characters, a syntax error + tokenType = TOKENTYPE.UNKNOWN; + while (c != '') { + token += c; + next(); + } + throw new SyntaxError('Syntax error in part "' + chop(token, 30) + '"'); + } + + /** + * Parse a graph. + * @returns {Object} graph + */ + function parseGraph() { + var graph = {}; + + first(); + getToken(); + + // optional strict keyword + if (token == 'strict') { + graph.strict = true; + getToken(); + } + + // graph or digraph keyword + if (token == 'graph' || token == 'digraph') { + graph.type = token; + getToken(); + } + + // optional graph id + if (tokenType == TOKENTYPE.IDENTIFIER) { + graph.id = token; + getToken(); + } + + // open angle bracket + if (token != '{') { + throw newSyntaxError('Angle bracket { expected'); + } + getToken(); + + // statements + parseStatements(graph); + + // close angle bracket + if (token != '}') { + throw newSyntaxError('Angle bracket } expected'); + } + getToken(); + + // end of file + if (token !== '') { + throw newSyntaxError('End of file expected'); + } + getToken(); + + // remove temporary default properties + delete graph.node; + delete graph.edge; + delete graph.graph; + + return graph; + } + + /** + * Parse a list with statements. + * @param {Object} graph + */ + function parseStatements (graph) { + while (token !== '' && token != '}') { + parseStatement(graph); + if (token == ';') { + getToken(); + } + } + } + + /** + * Parse a single statement. Can be a an attribute statement, node + * statement, a series of node statements and edge statements, or a + * parameter. + * @param {Object} graph + */ + function parseStatement(graph) { + // parse subgraph + var subgraph = parseSubgraph(graph); + if (subgraph) { + // edge statements + parseEdge(graph, subgraph); + + return; + } + + // parse an attribute statement + var attr = parseAttributeStatement(graph); + if (attr) { + return; + } + + // parse node + if (tokenType != TOKENTYPE.IDENTIFIER) { + throw newSyntaxError('Identifier expected'); + } + var id = token; // id can be a string or a number + getToken(); + + if (token == '=') { + // id statement + getToken(); + if (tokenType != TOKENTYPE.IDENTIFIER) { + throw newSyntaxError('Identifier expected'); + } + graph[id] = token; + getToken(); + // TODO: implement comma separated list with "a_list: ID=ID [','] [a_list] " + } + else { + parseNodeStatement(graph, id); + } + } + + /** + * Parse a subgraph + * @param {Object} graph parent graph object + * @return {Object | null} subgraph + */ + function parseSubgraph (graph) { + var subgraph = null; + + // optional subgraph keyword + if (token == 'subgraph') { + subgraph = {}; + subgraph.type = 'subgraph'; + getToken(); + + // optional graph id + if (tokenType == TOKENTYPE.IDENTIFIER) { + subgraph.id = token; + getToken(); + } + } + + // open angle bracket + if (token == '{') { + getToken(); + + if (!subgraph) { + subgraph = {}; + } + subgraph.parent = graph; + subgraph.node = graph.node; + subgraph.edge = graph.edge; + subgraph.graph = graph.graph; + + // statements + parseStatements(subgraph); + + // close angle bracket + if (token != '}') { + throw newSyntaxError('Angle bracket } expected'); + } + getToken(); + + // remove temporary default properties + delete subgraph.node; + delete subgraph.edge; + delete subgraph.graph; + delete subgraph.parent; + + // register at the parent graph + if (!graph.subgraphs) { + graph.subgraphs = []; + } + graph.subgraphs.push(subgraph); + } + + return subgraph; + } + + /** + * parse an attribute statement like "node [shape=circle fontSize=16]". + * Available keywords are 'node', 'edge', 'graph'. + * The previous list with default attributes will be replaced + * @param {Object} graph + * @returns {String | null} keyword Returns the name of the parsed attribute + * (node, edge, graph), or null if nothing + * is parsed. + */ + function parseAttributeStatement (graph) { + // attribute statements + if (token == 'node') { + getToken(); + + // node attributes + graph.node = parseAttributeList(); + return 'node'; + } + else if (token == 'edge') { + getToken(); + + // edge attributes + graph.edge = parseAttributeList(); + return 'edge'; + } + else if (token == 'graph') { + getToken(); + + // graph attributes + graph.graph = parseAttributeList(); + return 'graph'; + } + + return null; + } + + /** + * parse a node statement + * @param {Object} graph + * @param {String | Number} id + */ + function parseNodeStatement(graph, id) { + // node statement + var node = { + id: id + }; + var attr = parseAttributeList(); + if (attr) { + node.attr = attr; + } + addNode(graph, node); + + // edge statements + parseEdge(graph, id); + } + + /** + * Parse an edge or a series of edges + * @param {Object} graph + * @param {String | Number} from Id of the from node + */ + function parseEdge(graph, from) { + while (token == '->' || token == '--') { + var to; + var type = token; + getToken(); + + var subgraph = parseSubgraph(graph); + if (subgraph) { + to = subgraph; + } + else { + if (tokenType != TOKENTYPE.IDENTIFIER) { + throw newSyntaxError('Identifier or subgraph expected'); + } + to = token; + addNode(graph, { + id: to + }); + getToken(); + } + + // parse edge attributes + var attr = parseAttributeList(); + + // create edge + var edge = createEdge(graph, from, to, type, attr); + addEdge(graph, edge); + + from = to; + } + } + + /** + * Parse a set with attributes, + * for example [label="1.000", shape=solid] + * @return {Object | null} attr + */ + function parseAttributeList() { + var attr = null; + + while (token == '[') { + getToken(); + attr = {}; + while (token !== '' && token != ']') { + if (tokenType != TOKENTYPE.IDENTIFIER) { + throw newSyntaxError('Attribute name expected'); + } + var name = token; + + getToken(); + if (token != '=') { + throw newSyntaxError('Equal sign = expected'); + } + getToken(); + + if (tokenType != TOKENTYPE.IDENTIFIER) { + throw newSyntaxError('Attribute value expected'); + } + var value = token; + setValue(attr, name, value); // name can be a path + + getToken(); + if (token ==',') { + getToken(); + } + } + + if (token != ']') { + throw newSyntaxError('Bracket ] expected'); + } + getToken(); + } + + return attr; + } + + /** + * Create a syntax error with extra information on current token and index. + * @param {String} message + * @returns {SyntaxError} err + */ + function newSyntaxError(message) { + return new SyntaxError(message + ', got "' + chop(token, 30) + '" (char ' + index + ')'); + } + + /** + * Chop off text after a maximum length + * @param {String} text + * @param {Number} maxLength + * @returns {String} + */ + function chop (text, maxLength) { + return (text.length <= maxLength) ? text : (text.substr(0, 27) + '...'); + } + + /** + * Execute a function fn for each pair of elements in two arrays + * @param {Array | *} array1 + * @param {Array | *} array2 + * @param {function} fn + */ + function forEach2(array1, array2, fn) { + if (array1 instanceof Array) { + array1.forEach(function (elem1) { + if (array2 instanceof Array) { + array2.forEach(function (elem2) { + fn(elem1, elem2); + }); + } + else { + fn(elem1, array2); + } + }); + } + else { + if (array2 instanceof Array) { + array2.forEach(function (elem2) { + fn(array1, elem2); + }); + } + else { + fn(array1, array2); + } + } + } + + /** + * Convert a string containing a graph in DOT language into a map containing + * with nodes and edges in the format of graph. + * @param {String} data Text containing a graph in DOT-notation + * @return {Object} graphData + */ + function DOTToGraph (data) { + // parse the DOT file + var dotData = parseDOT(data); + var graphData = { + nodes: [], + edges: [], + options: {} + }; + + // copy the nodes + if (dotData.nodes) { + dotData.nodes.forEach(function (dotNode) { + var graphNode = { + id: dotNode.id, + label: String(dotNode.label || dotNode.id) + }; + merge(graphNode, dotNode.attr); + if (graphNode.image) { + graphNode.shape = 'image'; + } + graphData.nodes.push(graphNode); + }); + } + + // copy the edges + if (dotData.edges) { + /** + * Convert an edge in DOT format to an edge with VisGraph format + * @param {Object} dotEdge + * @returns {Object} graphEdge + */ + function convertEdge(dotEdge) { + var graphEdge = { + from: dotEdge.from, + to: dotEdge.to + }; + merge(graphEdge, dotEdge.attr); + graphEdge.style = (dotEdge.type == '->') ? 'arrow' : 'line'; + return graphEdge; + } + + dotData.edges.forEach(function (dotEdge) { + var from, to; + if (dotEdge.from instanceof Object) { + from = dotEdge.from.nodes; + } + else { + from = { + id: dotEdge.from + } + } + + if (dotEdge.to instanceof Object) { + to = dotEdge.to.nodes; + } + else { + to = { + id: dotEdge.to + } + } + + if (dotEdge.from instanceof Object && dotEdge.from.edges) { + dotEdge.from.edges.forEach(function (subEdge) { + var graphEdge = convertEdge(subEdge); + graphData.edges.push(graphEdge); + }); + } + + forEach2(from, to, function (from, to) { + var subEdge = createEdge(graphData, from.id, to.id, dotEdge.type, dotEdge.attr); + var graphEdge = convertEdge(subEdge); + graphData.edges.push(graphEdge); + }); + + if (dotEdge.to instanceof Object && dotEdge.to.edges) { + dotEdge.to.edges.forEach(function (subEdge) { + var graphEdge = convertEdge(subEdge); + graphData.edges.push(graphEdge); + }); + } + }); + } + + // copy the options + if (dotData.attr) { + graphData.options = dotData.attr; + } + + return graphData; + } + + // exports + exports.parseDOT = parseDOT; + exports.DOTToGraph = DOTToGraph; + + +/***/ }, +/* 39 */ +/***/ function(module, exports, __webpack_require__) { + + + function parseGephi(gephiJSON, options) { + var edges = []; + var nodes = []; + this.options = { + edges: { + inheritColor: true + }, + nodes: { + allowedToMove: false, + parseColor: false + } + }; + + if (options !== undefined) { + this.options.nodes['allowedToMove'] = options.allowedToMove | false; + this.options.nodes['parseColor'] = options.parseColor | false; + this.options.edges['inheritColor'] = options.inheritColor | true; + } + + var gEdges = gephiJSON.edges; + var gNodes = gephiJSON.nodes; + for (var i = 0; i < gEdges.length; i++) { + var edge = {}; + var gEdge = gEdges[i]; + edge['id'] = gEdge.id; + edge['from'] = gEdge.source; + edge['to'] = gEdge.target; + edge['attributes'] = gEdge.attributes; + // edge['value'] = gEdge.attributes !== undefined ? gEdge.attributes.Weight : undefined; + // edge['width'] = edge['value'] !== undefined ? undefined : edgegEdge.size; + edge['color'] = gEdge.color; + edge['inheritColor'] = edge['color'] !== undefined ? false : this.options.inheritColor; + edges.push(edge); + } + + for (var i = 0; i < gNodes.length; i++) { + var node = {}; + var gNode = gNodes[i]; + node['id'] = gNode.id; + node['attributes'] = gNode.attributes; + node['x'] = gNode.x; + node['y'] = gNode.y; + node['label'] = gNode.label; + if (this.options.nodes.parseColor == true) { + node['color'] = gNode.color; + } + else { + node['color'] = gNode.color !== undefined ? {background:gNode.color, border:gNode.color} : undefined; + } + node['radius'] = gNode.size; + node['allowedToMoveX'] = this.options.nodes.allowedToMove; + node['allowedToMoveY'] = this.options.nodes.allowedToMove; + nodes.push(node); + } + + return {nodes:nodes, edges:edges}; + } + + exports.parseGephi = parseGephi; + +/***/ }, +/* 40 */ +/***/ 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. + module.exports = (typeof window !== 'undefined') && window['moment'] || __webpack_require__(47); + + +/***/ }, +/* 41 */ +/***/ function(module, exports, __webpack_require__) { + + // Only load hammer.js when in a browser environment + // (loading hammer.js in a node.js environment gives errors) + if (typeof window !== 'undefined') { + module.exports = window['Hammer'] || __webpack_require__(48); + } + else { + module.exports = function () { + throw Error('hammer.js is only available in a browser, not in node.js.'); + } + } + + +/***/ }, +/* 42 */ +/***/ function(module, exports, __webpack_require__) { + + var Emitter = __webpack_require__(46); + var Hammer = __webpack_require__(41); + var util = __webpack_require__(1); + var DataSet = __webpack_require__(3); + var DataView = __webpack_require__(4); + var Range = __webpack_require__(15); + var TimeAxis = __webpack_require__(27); + var CurrentTime = __webpack_require__(19); + var CustomTime = __webpack_require__(20); + var ItemSet = __webpack_require__(24); + + /** + * Create a timeline visualization + * @param {HTMLElement} container + * @param {vis.DataSet | Array | google.visualization.DataTable} [items] + * @param {Object} [options] See Core.setOptions for the available options. + * @constructor + */ + function Core () {} + + // turn Core into an event emitter + Emitter(Core.prototype); + + /** + * Create the main DOM for the Core: a root panel containing left, right, + * top, bottom, content, and background panel. + * @param {Element} container The container element where the Core will + * be attached. + * @private + */ + Core.prototype._create = function (container) { + this.dom = {}; + + this.dom.root = document.createElement('div'); + this.dom.background = document.createElement('div'); + this.dom.backgroundVertical = document.createElement('div'); + this.dom.backgroundHorizontal = document.createElement('div'); + this.dom.centerContainer = document.createElement('div'); + this.dom.leftContainer = document.createElement('div'); + this.dom.rightContainer = document.createElement('div'); + this.dom.center = document.createElement('div'); + this.dom.left = document.createElement('div'); + this.dom.right = document.createElement('div'); + this.dom.top = document.createElement('div'); + this.dom.bottom = document.createElement('div'); + this.dom.shadowTop = document.createElement('div'); + this.dom.shadowBottom = document.createElement('div'); + this.dom.shadowTopLeft = document.createElement('div'); + this.dom.shadowBottomLeft = document.createElement('div'); + this.dom.shadowTopRight = document.createElement('div'); + this.dom.shadowBottomRight = document.createElement('div'); + + this.dom.background.className = 'vispanel background'; + this.dom.backgroundVertical.className = 'vispanel background vertical'; + this.dom.backgroundHorizontal.className = 'vispanel background horizontal'; + this.dom.centerContainer.className = 'vispanel center'; + this.dom.leftContainer.className = 'vispanel left'; + this.dom.rightContainer.className = 'vispanel right'; + this.dom.top.className = 'vispanel top'; + this.dom.bottom.className = 'vispanel bottom'; + this.dom.left.className = 'content'; + this.dom.center.className = 'content'; + this.dom.right.className = 'content'; + this.dom.shadowTop.className = 'shadow top'; + this.dom.shadowBottom.className = 'shadow bottom'; + this.dom.shadowTopLeft.className = 'shadow top'; + this.dom.shadowBottomLeft.className = 'shadow bottom'; + this.dom.shadowTopRight.className = 'shadow top'; + this.dom.shadowBottomRight.className = 'shadow bottom'; + + this.dom.root.appendChild(this.dom.background); + this.dom.root.appendChild(this.dom.backgroundVertical); + this.dom.root.appendChild(this.dom.backgroundHorizontal); + this.dom.root.appendChild(this.dom.centerContainer); + this.dom.root.appendChild(this.dom.leftContainer); + this.dom.root.appendChild(this.dom.rightContainer); + this.dom.root.appendChild(this.dom.top); + this.dom.root.appendChild(this.dom.bottom); + + this.dom.centerContainer.appendChild(this.dom.center); + this.dom.leftContainer.appendChild(this.dom.left); + this.dom.rightContainer.appendChild(this.dom.right); + + this.dom.centerContainer.appendChild(this.dom.shadowTop); + this.dom.centerContainer.appendChild(this.dom.shadowBottom); + this.dom.leftContainer.appendChild(this.dom.shadowTopLeft); + this.dom.leftContainer.appendChild(this.dom.shadowBottomLeft); + this.dom.rightContainer.appendChild(this.dom.shadowTopRight); + this.dom.rightContainer.appendChild(this.dom.shadowBottomRight); + + this.on('rangechange', this.redraw.bind(this)); + this.on('change', this.redraw.bind(this)); + this.on('touch', this._onTouch.bind(this)); + this.on('pinch', this._onPinch.bind(this)); + this.on('dragstart', this._onDragStart.bind(this)); + this.on('drag', this._onDrag.bind(this)); + + // create event listeners for all interesting events, these events will be + // emitted via emitter + this.hammer = Hammer(this.dom.root, { + prevent_default: true + }); + this.listeners = {}; + + var me = this; + var events = [ + 'touch', 'pinch', + 'tap', 'doubletap', 'hold', + 'dragstart', 'drag', 'dragend', + 'mousewheel', 'DOMMouseScroll' // DOMMouseScroll is needed for Firefox + ]; + events.forEach(function (event) { + var listener = function () { + var args = [event].concat(Array.prototype.slice.call(arguments, 0)); + me.emit.apply(me, args); + }; + me.hammer.on(event, listener); + me.listeners[event] = listener; + }); + + // size properties of each of the panels + this.props = { + root: {}, + background: {}, + centerContainer: {}, + leftContainer: {}, + rightContainer: {}, + center: {}, + left: {}, + right: {}, + top: {}, + bottom: {}, + border: {}, + scrollTop: 0, + scrollTopMin: 0 + }; + this.touch = {}; // store state information needed for touch events + + // attach the root panel to the provided container + if (!container) throw new Error('No container provided'); + container.appendChild(this.dom.root); + }; + + /** + * Destroy the Core, clean up all DOM elements and event listeners. + */ + Core.prototype.destroy = function () { + // unbind datasets + this.clear(); + + // remove all event listeners + this.off(); + + // stop checking for changed size + this._stopAutoResize(); + + // remove from DOM + if (this.dom.root.parentNode) { + this.dom.root.parentNode.removeChild(this.dom.root); + } + this.dom = null; + + // cleanup hammer touch events + for (var event in this.listeners) { + if (this.listeners.hasOwnProperty(event)) { + delete this.listeners[event]; + } + } + this.listeners = null; + this.hammer = null; + + // give all components the opportunity to cleanup + this.components.forEach(function (component) { + component.destroy(); + }); + + this.body = null; + }; + + + /** + * Set a custom time bar + * @param {Date} time + */ + Core.prototype.setCustomTime = function (time) { + if (!this.customTime) { + throw new Error('Cannot get custom time: Custom time bar is not enabled'); + } + + this.customTime.setCustomTime(time); + }; + + /** + * Retrieve the current custom time. + * @return {Date} customTime + */ + Core.prototype.getCustomTime = function() { + if (!this.customTime) { + throw new Error('Cannot get custom time: Custom time bar is not enabled'); + } + + return this.customTime.getCustomTime(); + }; + + + /** + * Get the id's of the currently visible items. + * @returns {Array} The ids of the visible items + */ + Core.prototype.getVisibleItems = function() { + return this.itemSet && this.itemSet.getVisibleItems() || []; + }; + + + + /** + * Clear the Core. By Default, items, groups and options are cleared. + * Example usage: + * + * timeline.clear(); // clear items, groups, and options + * timeline.clear({options: true}); // clear options only + * + * @param {Object} [what] Optionally specify what to clear. By default: + * {items: true, groups: true, options: true} + */ + Core.prototype.clear = function(what) { + // clear items + if (!what || what.items) { + this.setItems(null); + } + + // clear groups + if (!what || what.groups) { + this.setGroups(null); + } + + // clear options of timeline and of each of the components + if (!what || what.options) { + this.components.forEach(function (component) { + component.setOptions(component.defaultOptions); + }); + + this.setOptions(this.defaultOptions); // this will also do a redraw + } + }; + + /** + * Set Core window such that it fits all items + */ + Core.prototype.fit = function() { + // apply the data range as range + var dataRange = this.getItemRange(); + + // add 5% space on both sides + var start = dataRange.min; + var end = dataRange.max; + if (start != null && end != null) { + var interval = (end.valueOf() - start.valueOf()); + if (interval <= 0) { + // prevent an empty interval + interval = 24 * 60 * 60 * 1000; // 1 day + } + start = new Date(start.valueOf() - interval * 0.05); + end = new Date(end.valueOf() + interval * 0.05); + } + + // skip range set if there is no start and end date + if (start === null && end === null) { + return; + } + + this.range.setRange(start, end); + }; + + + /** + * Set the visible window. Both parameters are optional, you can change only + * start or only end. Syntax: + * + * TimeLine.setWindow(start, end) + * TimeLine.setWindow(range) + * + * Where start and end can be a Date, number, or string, and range is an + * object with properties start and end. + * + * @param {Date | Number | String | Object} [start] Start date of visible window + * @param {Date | Number | String} [end] End date of visible window + */ + Core.prototype.setWindow = function(start, end) { + if (arguments.length == 1) { + var range = arguments[0]; + this.range.setRange(range.start, range.end); + } + else { + this.range.setRange(start, end); + } + }; + + /** + * Get the visible window + * @return {{start: Date, end: Date}} Visible range + */ + Core.prototype.getWindow = function() { + var range = this.range.getRange(); + return { + start: new Date(range.start), + end: new Date(range.end) }; - this.constants = util.extend({}, this.defaultOptions); + }; + + /** + * Force a redraw of the Core. Can be useful to manually redraw when + * option autoResize=false + */ + Core.prototype.redraw = function() { + var resized = false, + options = this.options, + props = this.props, + dom = this.dom; + + if (!dom) return; // when destroyed + + // update class names + dom.root.className = 'vis timeline root ' + options.orientation; + + // update root width and height options + dom.root.style.maxHeight = util.option.asSize(options.maxHeight, ''); + dom.root.style.minHeight = util.option.asSize(options.minHeight, ''); + dom.root.style.width = util.option.asSize(options.width, ''); + + // calculate border widths + props.border.left = (dom.centerContainer.offsetWidth - dom.centerContainer.clientWidth) / 2; + props.border.right = props.border.left; + props.border.top = (dom.centerContainer.offsetHeight - dom.centerContainer.clientHeight) / 2; + props.border.bottom = props.border.top; + var borderRootHeight= dom.root.offsetHeight - dom.root.clientHeight; + var borderRootWidth = dom.root.offsetWidth - dom.root.clientWidth; + + // calculate the heights. If any of the side panels is empty, we set the height to + // minus the border width, such that the border will be invisible + props.center.height = dom.center.offsetHeight; + props.left.height = dom.left.offsetHeight; + props.right.height = dom.right.offsetHeight; + props.top.height = dom.top.clientHeight || -props.border.top; + props.bottom.height = dom.bottom.clientHeight || -props.border.bottom; + + // TODO: compensate borders when any of the panels is empty. + + // apply auto height + // TODO: only calculate autoHeight when needed (else we cause an extra reflow/repaint of the DOM) + var contentHeight = Math.max(props.left.height, props.center.height, props.right.height); + var autoHeight = props.top.height + contentHeight + props.bottom.height + + borderRootHeight + props.border.top + props.border.bottom; + dom.root.style.height = util.option.asSize(options.height, autoHeight + 'px'); + + // calculate heights of the content panels + props.root.height = dom.root.offsetHeight; + props.background.height = props.root.height - borderRootHeight; + var containerHeight = props.root.height - props.top.height - props.bottom.height - + borderRootHeight; + props.centerContainer.height = containerHeight; + props.leftContainer.height = containerHeight; + props.rightContainer.height = props.leftContainer.height; + + // calculate the widths of the panels + props.root.width = dom.root.offsetWidth; + props.background.width = props.root.width - borderRootWidth; + props.left.width = dom.leftContainer.clientWidth || -props.border.left; + props.leftContainer.width = props.left.width; + props.right.width = dom.rightContainer.clientWidth || -props.border.right; + props.rightContainer.width = props.right.width; + var centerWidth = props.root.width - props.left.width - props.right.width - borderRootWidth; + props.center.width = centerWidth; + props.centerContainer.width = centerWidth; + props.top.width = centerWidth; + props.bottom.width = centerWidth; + + // resize the panels + dom.background.style.height = props.background.height + 'px'; + dom.backgroundVertical.style.height = props.background.height + 'px'; + dom.backgroundHorizontal.style.height = props.centerContainer.height + 'px'; + dom.centerContainer.style.height = props.centerContainer.height + 'px'; + dom.leftContainer.style.height = props.leftContainer.height + 'px'; + dom.rightContainer.style.height = props.rightContainer.height + 'px'; + + dom.background.style.width = props.background.width + 'px'; + dom.backgroundVertical.style.width = props.centerContainer.width + 'px'; + dom.backgroundHorizontal.style.width = props.background.width + 'px'; + dom.centerContainer.style.width = props.center.width + 'px'; + dom.top.style.width = props.top.width + 'px'; + dom.bottom.style.width = props.bottom.width + 'px'; + + // reposition the panels + dom.background.style.left = '0'; + dom.background.style.top = '0'; + dom.backgroundVertical.style.left = props.left.width + 'px'; + dom.backgroundVertical.style.top = '0'; + dom.backgroundHorizontal.style.left = '0'; + dom.backgroundHorizontal.style.top = props.top.height + 'px'; + dom.centerContainer.style.left = props.left.width + 'px'; + dom.centerContainer.style.top = props.top.height + 'px'; + dom.leftContainer.style.left = '0'; + dom.leftContainer.style.top = props.top.height + 'px'; + dom.rightContainer.style.left = (props.left.width + props.center.width) + 'px'; + dom.rightContainer.style.top = props.top.height + 'px'; + dom.top.style.left = props.left.width + 'px'; + dom.top.style.top = '0'; + dom.bottom.style.left = props.left.width + 'px'; + dom.bottom.style.top = (props.top.height + props.centerContainer.height) + 'px'; + + // update the scrollTop, feasible range for the offset can be changed + // when the height of the Core or of the contents of the center changed + this._updateScrollTop(); + + // reposition the scrollable contents + var offset = this.props.scrollTop; + if (options.orientation == 'bottom') { + offset += Math.max(this.props.centerContainer.height - this.props.center.height - + this.props.border.top - this.props.border.bottom, 0); + } + dom.center.style.left = '0'; + dom.center.style.top = offset + 'px'; + dom.left.style.left = '0'; + dom.left.style.top = offset + 'px'; + dom.right.style.left = '0'; + dom.right.style.top = offset + 'px'; + + // show shadows when vertical scrolling is available + var visibilityTop = this.props.scrollTop == 0 ? 'hidden' : ''; + var visibilityBottom = this.props.scrollTop == this.props.scrollTopMin ? 'hidden' : ''; + dom.shadowTop.style.visibility = visibilityTop; + dom.shadowBottom.style.visibility = visibilityBottom; + dom.shadowTopLeft.style.visibility = visibilityTop; + dom.shadowBottomLeft.style.visibility = visibilityBottom; + dom.shadowTopRight.style.visibility = visibilityTop; + dom.shadowBottomRight.style.visibility = visibilityBottom; + + // redraw all components + this.components.forEach(function (component) { + resized = component.redraw() || resized; + }); + if (resized) { + // keep repainting until all sizes are settled + this.redraw(); + } + }; + + // TODO: deprecated since version 1.1.0, remove some day + Core.prototype.repaint = function () { + throw new Error('Function repaint is deprecated. Use redraw instead.'); + }; + + /** + * Convert a position on screen (pixels) to a datetime + * @param {int} x Position on the screen in pixels + * @return {Date} time The datetime the corresponds with given position x + * @private + */ + // TODO: move this function to Range + Core.prototype._toTime = function(x) { + var conversion = this.range.conversion(this.props.center.width); + return new Date(x / conversion.scale + conversion.offset); + }; - this.hoverObj = {nodes:{},edges:{}}; - this.controlNodesActive = false; - // Node variables - var network = this; - this.groups = new Groups(); // object with groups - this.images = new Images(); // object with images - this.images.setOnloadCallback(function () { - network._redraw(); - }); + /** + * Convert a position on the global screen (pixels) to a datetime + * @param {int} x Position on the screen in pixels + * @return {Date} time The datetime the corresponds with given position x + * @private + */ + // TODO: move this function to Range + Core.prototype._toGlobalTime = function(x) { + var conversion = this.range.conversion(this.props.root.width); + return new Date(x / conversion.scale + conversion.offset); + }; - // keyboard navigation variables - this.xIncrement = 0; - this.yIncrement = 0; - this.zoomIncrement = 0; + /** + * Convert a datetime (Date object) into a position on the screen + * @param {Date} time A date + * @return {int} x The position on the screen in pixels which corresponds + * with the given date. + * @private + */ + // TODO: move this function to Range + Core.prototype._toScreen = function(time) { + var conversion = this.range.conversion(this.props.center.width); + return (time.valueOf() - conversion.offset) * conversion.scale; + }; - // loading all the mixins: - // load the force calculation functions, grouped under the physics system. - this._loadPhysicsSystem(); - // create a frame and canvas - this._create(); - // load the sector system. (mandatory, fully integrated with Network) - this._loadSectorSystem(); - // load the cluster system. (mandatory, even when not using the cluster system, there are function calls to it) - this._loadClusterSystem(); - // load the selection system. (mandatory, required by Network) - this._loadSelectionSystem(); - // load the selection system. (mandatory, required by Network) - this._loadHierarchySystem(); - // apply options - this._setTranslation(this.frame.clientWidth / 2, this.frame.clientHeight / 2); - this._setScale(1); - this.setOptions(options); + /** + * Convert a datetime (Date object) into a position on the root + * This is used to get the pixel density estimate for the screen, not the center panel + * @param {Date} time A date + * @return {int} x The position on root in pixels which corresponds + * with the given date. + * @private + */ + // TODO: move this function to Range + Core.prototype._toGlobalScreen = function(time) { + var conversion = this.range.conversion(this.props.root.width); + return (time.valueOf() - conversion.offset) * conversion.scale; + }; - // other vars - this.freezeSimulation = false;// freeze the simulation - this.cachedFunctions = {}; - // containers for nodes and edges - this.calculationNodes = {}; - this.calculationNodeIndices = []; - this.nodeIndices = []; // array with all the indices of the nodes. Used to speed up forces calculation - this.nodes = {}; // object with Node objects - this.edges = {}; // object with Edge objects + /** + * Initialize watching when option autoResize is true + * @private + */ + Core.prototype._initAutoResize = function () { + if (this.options.autoResize == true) { + this._startAutoResize(); + } + else { + this._stopAutoResize(); + } + }; - // position and scale variables and objects - this.canvasTopLeft = {"x": 0,"y": 0}; // coordinates of the top left of the canvas. they will be set during _redraw. - this.canvasBottomRight = {"x": 0,"y": 0}; // coordinates of the bottom right of the canvas. they will be set during _redraw - this.pointerPosition = {"x": 0,"y": 0}; // coordinates of the bottom right of the canvas. they will be set during _redraw - this.areaCenter = {}; // object with x and y elements used for determining the center of the zoom action - this.scale = 1; // defining the global scale variable in the constructor - this.previousScale = this.scale; // this is used to check if the zoom operation is zooming in or out + /** + * Watch for changes in the size of the container. On resize, the Panel will + * automatically redraw itself. + * @private + */ + Core.prototype._startAutoResize = function () { + var me = this; - // datasets or dataviews - this.nodesData = null; // A DataSet or DataView - this.edgesData = null; // A DataSet or DataView + this._stopAutoResize(); - // create event listeners used to subscribe on the DataSets of the nodes and edges - this.nodesListeners = { - 'add': function (event, params) { - network._addNodes(params.items); - network.start(); - }, - 'update': function (event, params) { - network._updateNodes(params.items); - network.start(); - }, - 'remove': function (event, params) { - network._removeNodes(params.items); - network.start(); + this._onResize = function() { + if (me.options.autoResize != true) { + // stop watching when the option autoResize is changed to false + me._stopAutoResize(); + return; } - }; - this.edgesListeners = { - 'add': function (event, params) { - network._addEdges(params.items); - network.start(); - }, - 'update': function (event, params) { - network._updateEdges(params.items); - network.start(); - }, - 'remove': function (event, params) { - network._removeEdges(params.items); - network.start(); + + if (me.dom.root) { + // check whether the frame is resized + if ((me.dom.root.clientWidth != me.props.lastWidth) || + (me.dom.root.clientHeight != me.props.lastHeight)) { + me.props.lastWidth = me.dom.root.clientWidth; + me.props.lastHeight = me.dom.root.clientHeight; + + me.emit('change'); + } } }; - // properties for the animation - this.moving = true; - this.timer = undefined; // Scheduling function. Is definded in this.start(); - - // load data (the disable start variable will be the same as the enabled clustering) - this.setData(data,this.constants.clustering.enabled || this.constants.hierarchicalLayout.enabled); + // add event listener to window resize + util.addEventListener(window, 'resize', this._onResize); - // hierarchical layout - this.initializing = false; - if (this.constants.hierarchicalLayout.enabled == true) { - this._setupHierarchicalLayout(); - } - else { - // zoom so all data will fit on the screen, if clustering is enabled, we do not want start to be called here. - if (this.constants.stabilize == false) { - this.zoomExtent(true,this.constants.clustering.enabled); - } - } + this.watchTimer = setInterval(this._onResize, 1000); + }; - // if clustering is disabled, the simulation will have started in the setData function - if (this.constants.clustering.enabled) { - this.startWithClustering(); + /** + * Stop watching for a resize of the frame. + * @private + */ + Core.prototype._stopAutoResize = function () { + if (this.watchTimer) { + clearInterval(this.watchTimer); + this.watchTimer = undefined; } - } - // Extend Network with an Emitter mixin - Emitter(Network.prototype); + // remove event listener on window.resize + util.removeEventListener(window, 'resize', this._onResize); + this._onResize = null; + }; /** - * Get the script path where the vis.js library is located - * - * @returns {string | null} path Path or null when not found. Path does not - * end with a slash. + * Start moving the timeline vertically + * @param {Event} event * @private */ - Network.prototype._getScriptPath = function() { - var scripts = document.getElementsByTagName( 'script' ); - - // find script named vis.js or vis.min.js - for (var i = 0; i < scripts.length; i++) { - var src = scripts[i].src; - var match = src && /\/?vis(.min)?\.js$/.exec(src); - if (match) { - // return path without the script name - return src.substring(0, src.length - match[0].length); - } - } + Core.prototype._onTouch = function (event) { + this.touch.allowDragging = true; + }; - return null; + /** + * Start moving the timeline vertically + * @param {Event} event + * @private + */ + Core.prototype._onPinch = function (event) { + this.touch.allowDragging = false; }; + /** + * Start moving the timeline vertically + * @param {Event} event + * @private + */ + Core.prototype._onDragStart = function (event) { + this.touch.initialScrollTop = this.props.scrollTop; + }; /** - * Find the center position of the network + * Move the timeline vertically + * @param {Event} event * @private */ - Network.prototype._getRange = function() { - var minY = 1e9, maxY = -1e9, minX = 1e9, maxX = -1e9, node; - for (var nodeId in this.nodes) { - if (this.nodes.hasOwnProperty(nodeId)) { - node = this.nodes[nodeId]; - if (minX > (node.x)) {minX = node.x;} - if (maxX < (node.x)) {maxX = node.x;} - if (minY > (node.y)) {minY = node.y;} - if (maxY < (node.y)) {maxY = node.y;} - } - } - if (minX == 1e9 && maxX == -1e9 && minY == 1e9 && maxY == -1e9) { - minY = 0, maxY = 0, minX = 0, maxX = 0; + Core.prototype._onDrag = function (event) { + // refuse to drag when we where pinching to prevent the timeline make a jump + // when releasing the fingers in opposite order from the touch screen + if (!this.touch.allowDragging) return; + + var delta = event.gesture.deltaY; + + var oldScrollTop = this._getScrollTop(); + var newScrollTop = this._setScrollTop(this.touch.initialScrollTop + delta); + + if (newScrollTop != oldScrollTop) { + this.redraw(); // TODO: this causes two redraws when dragging, the other is triggered by rangechange already } - return {minX: minX, maxX: maxX, minY: minY, maxY: maxY}; }; - /** - * @param {object} range = {minX: minX, maxX: maxX, minY: minY, maxY: maxY}; - * @returns {{x: number, y: number}} + * Apply a scrollTop + * @param {Number} scrollTop + * @returns {Number} scrollTop Returns the applied scrollTop * @private */ - Network.prototype._findCenter = function(range) { - return {x: (0.5 * (range.maxX + range.minX)), - y: (0.5 * (range.maxY + range.minY))}; + Core.prototype._setScrollTop = function (scrollTop) { + this.props.scrollTop = scrollTop; + this._updateScrollTop(); + return this.props.scrollTop; }; - /** - * center the network - * - * @param {object} range = {minX: minX, maxX: maxX, minY: minY, maxY: maxY}; + * Update the current scrollTop when the height of the containers has been changed + * @returns {Number} scrollTop Returns the applied scrollTop + * @private */ - Network.prototype._centerNetwork = function(range) { - var center = this._findCenter(range); + Core.prototype._updateScrollTop = function () { + // recalculate the scrollTopMin + var scrollTopMin = Math.min(this.props.centerContainer.height - this.props.center.height, 0); // is negative or zero + if (scrollTopMin != this.props.scrollTopMin) { + // in case of bottom orientation, change the scrollTop such that the contents + // do not move relative to the time axis at the bottom + if (this.options.orientation == 'bottom') { + this.props.scrollTop += (scrollTopMin - this.props.scrollTopMin); + } + this.props.scrollTopMin = scrollTopMin; + } - center.x *= this.scale; - center.y *= this.scale; - center.x -= 0.5 * this.frame.canvas.clientWidth; - center.y -= 0.5 * this.frame.canvas.clientHeight; + // limit the scrollTop to the feasible scroll range + if (this.props.scrollTop > 0) this.props.scrollTop = 0; + if (this.props.scrollTop < scrollTopMin) this.props.scrollTop = scrollTopMin; - this._setTranslation(-center.x,-center.y); // set at 0,0 + return this.props.scrollTop; }; - /** - * This function zooms out to fit all data on screen based on amount of nodes - * - * @param {Boolean} [initialZoom] | zoom based on fitted formula or range, true = fitted, default = false; - * @param {Boolean} [disableStart] | If true, start is not called. + * Get the current scrollTop + * @returns {number} scrollTop + * @private */ - Network.prototype.zoomExtent = function(initialZoom, disableStart) { - if (initialZoom === undefined) { - initialZoom = false; - } - if (disableStart === undefined) { - disableStart = false; - } + Core.prototype._getScrollTop = function () { + return this.props.scrollTop; + }; - var range = this._getRange(); - var zoomLevel; + module.exports = Core; - if (initialZoom == true) { - var numberOfNodes = this.nodeIndices.length; - if (this.constants.smoothCurves == true) { - if (this.constants.clustering.enabled == true && - numberOfNodes >= this.constants.clustering.initialMaxNodes) { - zoomLevel = 49.07548 / (numberOfNodes + 142.05338) + 9.1444e-04; // this is obtained from fitting a dataset from 5 points with scale levels that looked good. - } - else { - zoomLevel = 12.662 / (numberOfNodes + 7.4147) + 0.0964822; // this is obtained from fitting a dataset from 5 points with scale levels that looked good. - } - } - else { - if (this.constants.clustering.enabled == true && - numberOfNodes >= this.constants.clustering.initialMaxNodes) { - zoomLevel = 77.5271985 / (numberOfNodes + 187.266146) + 4.76710517e-05; // this is obtained from fitting a dataset from 5 points with scale levels that looked good. - } - else { - zoomLevel = 30.5062972 / (numberOfNodes + 19.93597763) + 0.08413486; // this is obtained from fitting a dataset from 5 points with scale levels that looked good. - } - } - // correct for larger canvasses. - var factor = Math.min(this.frame.canvas.clientWidth / 600, this.frame.canvas.clientHeight / 600); - zoomLevel *= factor; - } - else { - var xDistance = (Math.abs(range.minX) + Math.abs(range.maxX)) * 1.1; - var yDistance = (Math.abs(range.minY) + Math.abs(range.maxY)) * 1.1; +/***/ }, +/* 43 */ +/***/ function(module, exports, __webpack_require__) { - var xZoomLevel = this.frame.canvas.clientWidth / xDistance; - var yZoomLevel = this.frame.canvas.clientHeight / yDistance; + var Hammer = __webpack_require__(41); - zoomLevel = (xZoomLevel <= yZoomLevel) ? xZoomLevel : yZoomLevel; - } + /** + * Fake a hammer.js gesture. Event can be a ScrollEvent or MouseMoveEvent + * @param {Element} element + * @param {Event} event + */ + exports.fakeGesture = function(element, event) { + var eventType = null; - if (zoomLevel > 1.0) { - zoomLevel = 1.0; - } + // for hammer.js 1.0.5 + // var gesture = Hammer.event.collectEventData(this, eventType, event); + // for hammer.js 1.0.6+ + var touches = Hammer.event.getTouchList(event, eventType); + var gesture = Hammer.event.collectEventData(this, eventType, touches, event); - this._setScale(zoomLevel); - this._centerNetwork(range); - if (disableStart == false) { - this.moving = true; - this.start(); + // on IE in standards mode, no touches are recognized by hammer.js, + // resulting in NaN values for center.pageX and center.pageY + if (isNaN(gesture.center.pageX)) { + gesture.center.pageX = event.pageX; } + if (isNaN(gesture.center.pageY)) { + gesture.center.pageY = event.pageY; + } + + return gesture; }; +/***/ }, +/* 44 */ +/***/ function(module, exports, __webpack_require__) { + /** - * Update the this.nodeIndices with the most recent node index list - * @private + * Canvas shapes used by Network */ - Network.prototype._updateNodeIndexList = function() { - this._clearNodeIndexList(); - for (var idx in this.nodes) { - if (this.nodes.hasOwnProperty(idx)) { - this.nodeIndices.push(idx); - } - } - }; + if (typeof CanvasRenderingContext2D !== 'undefined') { + /** + * Draw a circle shape + */ + CanvasRenderingContext2D.prototype.circle = function(x, y, r) { + this.beginPath(); + this.arc(x, y, r, 0, 2*Math.PI, false); + }; - /** - * 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 - * @param {Boolean} [disableStart] | optional: disable the calling of the start function. - */ - Network.prototype.setData = function(data, disableStart) { - if (disableStart === undefined) { - disableStart = false; - } + /** + * Draw a square shape + * @param {Number} x horizontal center + * @param {Number} y vertical center + * @param {Number} r size, width and height of the square + */ + CanvasRenderingContext2D.prototype.square = function(x, y, r) { + this.beginPath(); + this.rect(x - r, y - r, r * 2, r * 2); + }; - 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.'); - } + /** + * Draw a triangle shape + * @param {Number} x horizontal center + * @param {Number} y vertical center + * @param {Number} r radius, half the length of the sides of the triangle + */ + CanvasRenderingContext2D.prototype.triangle = function(x, y, r) { + // http://en.wikipedia.org/wiki/Equilateral_triangle + this.beginPath(); - // set options - this.setOptions(data && data.options); + var s = r * 2; + var s2 = s / 2; + var ir = Math.sqrt(3) / 6 * s; // radius of inner circle + var h = Math.sqrt(s * s - s2 * s2); // height - // set all data - if (data && data.dot) { - // parse DOT file - if(data && data.dot) { - var dotData = dotparser.DOTToGraph(data.dot); - this.setData(dotData); - return; - } - } - else if (data && data.gephi) { - // parse DOT file - if(data && data.gephi) { - var gephiData = gephiParser.parseGephi(data.gephi); - this.setData(gephiData); - return; + this.moveTo(x, y - (h - ir)); + this.lineTo(x + s2, y + ir); + this.lineTo(x - s2, y + ir); + this.lineTo(x, y - (h - ir)); + this.closePath(); + }; + + /** + * Draw a triangle shape in downward orientation + * @param {Number} x horizontal center + * @param {Number} y vertical center + * @param {Number} r radius + */ + CanvasRenderingContext2D.prototype.triangleDown = function(x, y, r) { + // http://en.wikipedia.org/wiki/Equilateral_triangle + this.beginPath(); + + var s = r * 2; + var s2 = s / 2; + var ir = Math.sqrt(3) / 6 * s; // radius of inner circle + var h = Math.sqrt(s * s - s2 * s2); // height + + this.moveTo(x, y + (h - ir)); + this.lineTo(x + s2, y - ir); + this.lineTo(x - s2, y - ir); + this.lineTo(x, y + (h - ir)); + this.closePath(); + }; + + /** + * Draw a star shape, a star with 5 points + * @param {Number} x horizontal center + * @param {Number} y vertical center + * @param {Number} r radius, half the length of the sides of the triangle + */ + CanvasRenderingContext2D.prototype.star = function(x, y, r) { + // http://www.html5canvastutorials.com/labs/html5-canvas-star-spinner/ + this.beginPath(); + + for (var n = 0; n < 10; n++) { + var radius = (n % 2 === 0) ? r * 1.3 : r * 0.5; + this.lineTo( + x + radius * Math.sin(n * 2 * Math.PI / 10), + y - radius * Math.cos(n * 2 * Math.PI / 10) + ); } - } - else { - this._setNodes(data && data.nodes); - this._setEdges(data && data.edges); - } - this._putDataInSector(); - if (!disableStart) { - // find a stable position or start animating to a stable position - if (this.constants.stabilize) { - var me = this; - setTimeout(function() {me._stabilize(); me.start();},0) - } - else { - this.start(); - } - } - }; + this.closePath(); + }; - /** - * Set options - * @param {Object} options - * @param {Boolean} [initializeView] | set zoom and translation to default. - */ - Network.prototype.setOptions = function (options) { - if (options) { - var prop; + /** + * http://stackoverflow.com/questions/1255512/how-to-draw-a-rounded-rectangle-on-html-canvas + */ + CanvasRenderingContext2D.prototype.roundRect = function(x, y, w, h, r) { + var r2d = Math.PI/180; + if( w - ( 2 * r ) < 0 ) { r = ( w / 2 ); } //ensure that the radius isn't too large for x + if( h - ( 2 * r ) < 0 ) { r = ( h / 2 ); } //ensure that the radius isn't too large for y + this.beginPath(); + this.moveTo(x+r,y); + this.lineTo(x+w-r,y); + this.arc(x+w-r,y+r,r,r2d*270,r2d*360,false); + this.lineTo(x+w,y+h-r); + this.arc(x+w-r,y+h-r,r,0,r2d*90,false); + this.lineTo(x+r,y+h); + this.arc(x+r,y+h-r,r,r2d*90,r2d*180,false); + this.lineTo(x,y+r); + this.arc(x+r,y+r,r,r2d*180,r2d*270,false); + }; - var fields = ['nodes','edges','smoothCurves','hierarchicalLayout','clustering','navigation','keyboard','dataManipulation', - 'onAdd','onEdit','onEditEdge','onConnect','onDelete' - ]; - util.selectiveNotDeepExtend(fields,this.constants, options); - util.selectiveNotDeepExtend(['color'],this.constants.nodes, options.nodes); - util.selectiveNotDeepExtend(['color','length'],this.constants.edges, options.edges); + /** + * http://stackoverflow.com/questions/2172798/how-to-draw-an-oval-in-html5-canvas + */ + CanvasRenderingContext2D.prototype.ellipse = function(x, y, w, h) { + var kappa = .5522848, + ox = (w / 2) * kappa, // control point offset horizontal + oy = (h / 2) * kappa, // control point offset vertical + xe = x + w, // x-end + ye = y + h, // y-end + xm = x + w / 2, // x-middle + ym = y + h / 2; // y-middle - if (options.physics) { - util.mergeOptions(this.constants.physics, options.physics,'barnesHut'); - util.mergeOptions(this.constants.physics, options.physics,'repulsion'); + this.beginPath(); + this.moveTo(x, ym); + this.bezierCurveTo(x, ym - oy, xm - ox, y, xm, y); + this.bezierCurveTo(xm + ox, y, xe, ym - oy, xe, ym); + this.bezierCurveTo(xe, ym + oy, xm + ox, ye, xm, ye); + this.bezierCurveTo(xm - ox, ye, x, ym + oy, x, ym); + }; - if (options.physics.hierarchicalRepulsion) { - this.constants.hierarchicalLayout.enabled = true; - this.constants.physics.hierarchicalRepulsion.enabled = true; - this.constants.physics.barnesHut.enabled = false; - for (prop in options.physics.hierarchicalRepulsion) { - if (options.physics.hierarchicalRepulsion.hasOwnProperty(prop)) { - this.constants.physics.hierarchicalRepulsion[prop] = options.physics.hierarchicalRepulsion[prop]; - } - } - } - } - if (options.onAdd) {this.triggerFunctions.add = options.onAdd;} - if (options.onEdit) {this.triggerFunctions.edit = options.onEdit;} - if (options.onEditEdge) {this.triggerFunctions.editEdge = options.onEditEdge;} - if (options.onConnect) {this.triggerFunctions.connect = options.onConnect;} - if (options.onDelete) {this.triggerFunctions.del = options.onDelete;} - util.mergeOptions(this.constants, options,'smoothCurves'); - util.mergeOptions(this.constants, options,'hierarchicalLayout'); - util.mergeOptions(this.constants, options,'clustering'); - util.mergeOptions(this.constants, options,'navigation'); - util.mergeOptions(this.constants, options,'keyboard'); - util.mergeOptions(this.constants, options,'dataManipulation'); + /** + * http://stackoverflow.com/questions/2172798/how-to-draw-an-oval-in-html5-canvas + */ + CanvasRenderingContext2D.prototype.database = function(x, y, w, h) { + var f = 1/3; + var wEllipse = w; + var hEllipse = h * f; + var kappa = .5522848, + ox = (wEllipse / 2) * kappa, // control point offset horizontal + oy = (hEllipse / 2) * kappa, // control point offset vertical + xe = x + wEllipse, // x-end + ye = y + hEllipse, // y-end + xm = x + wEllipse / 2, // x-middle + ym = y + hEllipse / 2, // y-middle + ymb = y + (h - hEllipse/2), // y-midlle, bottom ellipse + yeb = y + h; // y-end, bottom ellipse - if (options.dataManipulation) { - this.editMode = this.constants.dataManipulation.initiallyVisible; - } + this.beginPath(); + this.moveTo(xe, ym); + this.bezierCurveTo(xe, ym + oy, xm + ox, ye, xm, ye); + this.bezierCurveTo(xm - ox, ye, x, ym + oy, x, ym); - // TODO: work out these options and document them - if (options.edges) { - if (options.edges.color !== undefined) { - if (util.isString(options.edges.color)) { - this.constants.edges.color = {}; - this.constants.edges.color.color = options.edges.color; - this.constants.edges.color.highlight = options.edges.color; - this.constants.edges.color.hover = options.edges.color; - } - else { - if (options.edges.color.color !== undefined) {this.constants.edges.color.color = options.edges.color.color;} - if (options.edges.color.highlight !== undefined) {this.constants.edges.color.highlight = options.edges.color.highlight;} - if (options.edges.color.hover !== undefined) {this.constants.edges.color.hover = options.edges.color.hover;} - } - } + this.bezierCurveTo(x, ym - oy, xm - ox, y, xm, y); + this.bezierCurveTo(xm + ox, y, xe, ym - oy, xe, ym); - if (!options.edges.fontColor) { - if (options.edges.color !== undefined) { - if (util.isString(options.edges.color)) {this.constants.edges.fontColor = options.edges.color;} - else if (options.edges.color.color !== undefined) {this.constants.edges.fontColor = options.edges.color.color;} - } - } - } + this.lineTo(xe, ymb); - if (options.nodes) { - if (options.nodes.color) { - var newColorObj = util.parseColor(options.nodes.color); - this.constants.nodes.color.background = newColorObj.background; - this.constants.nodes.color.border = newColorObj.border; - this.constants.nodes.color.highlight.background = newColorObj.highlight.background; - this.constants.nodes.color.highlight.border = newColorObj.highlight.border; - this.constants.nodes.color.hover.background = newColorObj.hover.background; - this.constants.nodes.color.hover.border = newColorObj.hover.border; - } - } - if (options.groups) { - for (var groupname in options.groups) { - if (options.groups.hasOwnProperty(groupname)) { - var group = options.groups[groupname]; - this.groups.add(groupname, group); - } - } - } + this.bezierCurveTo(xe, ymb + oy, xm + ox, yeb, xm, yeb); + this.bezierCurveTo(xm - ox, yeb, x, ymb + oy, x, ymb); - if (options.tooltip) { - for (prop in options.tooltip) { - if (options.tooltip.hasOwnProperty(prop)) { - this.constants.tooltip[prop] = options.tooltip[prop]; - } - } - if (options.tooltip.color) { - this.constants.tooltip.color = util.parseColor(options.tooltip.color); - } - } - } + this.lineTo(x, ym); + }; - // (Re)loading the mixins that can be enabled or disabled in the options. - // load the force calculation functions, grouped under the physics system. - this._loadPhysicsSystem(); - // load the navigation system. - this._loadNavigationControls(); - // load the data manipulation system - this._loadManipulationSystem(); - // configure the smooth curves - this._configureSmoothCurves(); + /** + * Draw an arrow point (no line) + */ + CanvasRenderingContext2D.prototype.arrow = function(x, y, angle, length) { + // tail + var xt = x - length * Math.cos(angle); + var yt = y - length * Math.sin(angle); + + // inner tail + // TODO: allow to customize different shapes + var xi = x - length * 0.9 * Math.cos(angle); + var yi = y - length * 0.9 * Math.sin(angle); - // bind keys. If disabled, this will not do anything; - this._createKeyBinds(); - this.setSize(this.constants.width, this.constants.height); - this.moving = true; - this.start(); + // left + var xl = xt + length / 3 * Math.cos(angle + 0.5 * Math.PI); + var yl = yt + length / 3 * Math.sin(angle + 0.5 * Math.PI); - }; + // right + var xr = xt + length / 3 * Math.cos(angle - 0.5 * Math.PI); + var yr = yt + length / 3 * Math.sin(angle - 0.5 * Math.PI); - /** - * Create the main frame for the Network. - * This function is executed once when a Network object is created. The frame - * contains a canvas, and this canvas contains all objects like the axis and - * nodes. - * @private - */ - Network.prototype._create = function () { - // remove all elements from the container element. - while (this.containerElement.hasChildNodes()) { - this.containerElement.removeChild(this.containerElement.firstChild); - } + this.beginPath(); + this.moveTo(x, y); + this.lineTo(xl, yl); + this.lineTo(xi, yi); + this.lineTo(xr, yr); + this.closePath(); + }; + + /** + * Sets up the dashedLine functionality for drawing + * Original code came from http://stackoverflow.com/questions/4576724/dotted-stroke-in-canvas + * @author David Jordan + * @date 2012-08-08 + */ + CanvasRenderingContext2D.prototype.dashedLine = function(x,y,x2,y2,dashArray){ + if (!dashArray) dashArray=[10,5]; + if (dashLength==0) dashLength = 0.001; // Hack for Safari + var dashCount = dashArray.length; + this.moveTo(x, y); + var dx = (x2-x), dy = (y2-y); + var slope = dy/dx; + var distRemaining = Math.sqrt( dx*dx + dy*dy ); + var dashIndex=0, draw=true; + while (distRemaining>=0.1){ + var dashLength = dashArray[dashIndex++%dashCount]; + if (dashLength > distRemaining) dashLength = distRemaining; + var xStep = Math.sqrt( dashLength*dashLength / (1 + slope*slope) ); + if (dx<0) xStep = -xStep; + x += xStep; + y += slope*xStep; + this[draw ? 'lineTo' : 'moveTo'](x,y); + distRemaining -= dashLength; + draw = !draw; + } + }; - this.frame = document.createElement('div'); - this.frame.className = 'network-frame'; - this.frame.style.position = 'relative'; - this.frame.style.overflow = 'hidden'; + // TODO: add diamond shape + } - // create the network canvas (HTML canvas element) - this.frame.canvas = document.createElement( 'canvas' ); - this.frame.canvas.style.position = 'relative'; - this.frame.appendChild(this.frame.canvas); - if (!this.frame.canvas.getContext) { - var noCanvas = document.createElement( 'DIV' ); - noCanvas.style.color = 'red'; - noCanvas.style.fontWeight = 'bold' ; - noCanvas.style.padding = '10px'; - noCanvas.innerHTML = 'Error: your browser does not support HTML canvas'; - this.frame.canvas.appendChild(noCanvas); - } - var me = this; - this.drag = {}; - this.pinch = {}; - this.hammer = Hammer(this.frame.canvas, { - prevent_default: true - }); - this.hammer.on('tap', me._onTap.bind(me) ); - this.hammer.on('doubletap', me._onDoubleTap.bind(me) ); - this.hammer.on('hold', me._onHold.bind(me) ); - this.hammer.on('pinch', me._onPinch.bind(me) ); - this.hammer.on('touch', me._onTouch.bind(me) ); - this.hammer.on('dragstart', me._onDragStart.bind(me) ); - this.hammer.on('drag', me._onDrag.bind(me) ); - this.hammer.on('dragend', me._onDragEnd.bind(me) ); - this.hammer.on('release', me._onRelease.bind(me) ); - this.hammer.on('mousewheel',me._onMouseWheel.bind(me) ); - this.hammer.on('DOMMouseScroll',me._onMouseWheel.bind(me) ); // for FF - this.hammer.on('mousemove', me._onMouseMoveTitle.bind(me) ); +/***/ }, +/* 45 */ +/***/ function(module, exports, __webpack_require__) { - // add the frame to the container element - this.containerElement.appendChild(this.frame); + var PhysicsMixin = __webpack_require__(56); + var ClusterMixin = __webpack_require__(50); + var SectorsMixin = __webpack_require__(51); + var SelectionMixin = __webpack_require__(52); + var ManipulationMixin = __webpack_require__(53); + var NavigationMixin = __webpack_require__(54); + var HierarchicalLayoutMixin = __webpack_require__(55); + /** + * Load a mixin into the network object + * + * @param {Object} sourceVariable | this object has to contain functions. + * @private + */ + exports._loadMixin = function (sourceVariable) { + for (var mixinFunction in sourceVariable) { + if (sourceVariable.hasOwnProperty(mixinFunction)) { + this[mixinFunction] = sourceVariable[mixinFunction]; + } + } }; /** - * Binding the keys for keyboard navigation. These functions are defined in the NavigationMixin + * removes a mixin from the network object. + * + * @param {Object} sourceVariable | this object has to contain functions. * @private */ - Network.prototype._createKeyBinds = function() { - var me = this; - this.mousetrap = mousetrap; - - this.mousetrap.reset(); - - if (this.constants.keyboard.enabled == true) { - this.mousetrap.bind("up", this._moveUp.bind(me) , "keydown"); - this.mousetrap.bind("up", this._yStopMoving.bind(me), "keyup"); - this.mousetrap.bind("down", this._moveDown.bind(me) , "keydown"); - this.mousetrap.bind("down", this._yStopMoving.bind(me), "keyup"); - this.mousetrap.bind("left", this._moveLeft.bind(me) , "keydown"); - this.mousetrap.bind("left", this._xStopMoving.bind(me), "keyup"); - this.mousetrap.bind("right",this._moveRight.bind(me), "keydown"); - this.mousetrap.bind("right",this._xStopMoving.bind(me), "keyup"); - this.mousetrap.bind("=", this._zoomIn.bind(me), "keydown"); - this.mousetrap.bind("=", this._stopZoom.bind(me), "keyup"); - this.mousetrap.bind("-", this._zoomOut.bind(me), "keydown"); - this.mousetrap.bind("-", this._stopZoom.bind(me), "keyup"); - this.mousetrap.bind("[", this._zoomIn.bind(me), "keydown"); - this.mousetrap.bind("[", this._stopZoom.bind(me), "keyup"); - this.mousetrap.bind("]", this._zoomOut.bind(me), "keydown"); - this.mousetrap.bind("]", this._stopZoom.bind(me), "keyup"); - this.mousetrap.bind("pageup",this._zoomIn.bind(me), "keydown"); - this.mousetrap.bind("pageup",this._stopZoom.bind(me), "keyup"); - this.mousetrap.bind("pagedown",this._zoomOut.bind(me),"keydown"); - this.mousetrap.bind("pagedown",this._stopZoom.bind(me), "keyup"); + exports._clearMixin = function (sourceVariable) { + for (var mixinFunction in sourceVariable) { + if (sourceVariable.hasOwnProperty(mixinFunction)) { + this[mixinFunction] = undefined; + } } + }; - if (this.constants.dataManipulation.enabled == true) { - this.mousetrap.bind("escape",this._createManipulatorBar.bind(me)); - this.mousetrap.bind("del",this._deleteSelected.bind(me)); + + /** + * Mixin the physics system and initialize the parameters required. + * + * @private + */ + exports._loadPhysicsSystem = function () { + this._loadMixin(PhysicsMixin); + this._loadSelectedForceSolver(); + if (this.constants.configurePhysics == true) { + this._loadPhysicsConfiguration(); } }; + /** - * Get the pointer location from a touch location - * @param {{pageX: Number, pageY: Number}} touch - * @return {{x: Number, y: Number}} pointer + * Mixin the cluster system and initialize the parameters required. + * * @private */ - Network.prototype._getPointer = function (touch) { - return { - x: touch.pageX - util.getAbsoluteLeft(this.frame.canvas), - y: touch.pageY - util.getAbsoluteTop(this.frame.canvas) - }; + exports._loadClusterSystem = function () { + this.clusterSession = 0; + this.hubThreshold = 5; + this._loadMixin(ClusterMixin); }; + /** - * On start of a touch gesture, store the pointer - * @param event + * Mixin the sector system and initialize the parameters required + * * @private */ - Network.prototype._onTouch = function (event) { - this.drag.pointer = this._getPointer(event.gesture.center); - this.drag.pinched = false; - this.pinch.scale = this._getScale(); + exports._loadSectorSystem = function () { + this.sectors = {}; + this.activeSector = ["default"]; + this.sectors["active"] = {}; + this.sectors["active"]["default"] = {"nodes": {}, + "edges": {}, + "nodeIndices": [], + "formationScale": 1.0, + "drawingNode": undefined }; + this.sectors["frozen"] = {}; + this.sectors["support"] = {"nodes": {}, + "edges": {}, + "nodeIndices": [], + "formationScale": 1.0, + "drawingNode": undefined }; - this._handleTouch(this.drag.pointer); + this.nodeIndices = this.sectors["active"]["default"]["nodeIndices"]; // the node indices list is used to speed up the computation of the repulsion fields + + this._loadMixin(SectorsMixin); }; + /** - * handle drag start event + * Mixin the selection system and initialize the parameters required + * * @private */ - Network.prototype._onDragStart = function () { - this._handleDragStart(); + exports._loadSelectionSystem = function () { + this.selectionObj = {nodes: {}, edges: {}}; + + this._loadMixin(SelectionMixin); }; /** - * This function is called by _onDragStart. - * It is separated out because we can then overload it for the datamanipulation system. + * Mixin the navigationUI (User Interface) system and initialize the parameters required * * @private */ - Network.prototype._handleDragStart = function() { - var drag = this.drag; - var node = this._getNodeAt(drag.pointer); - // note: drag.pointer is set in _onTouch to get the initial touch location + exports._loadManipulationSystem = function () { + // reset global variables -- these are used by the selection of nodes and edges. + this.blockConnectingEdgeSelection = false; + this.forceAppendSelection = false; - drag.dragging = true; - drag.selection = []; - drag.translation = this._getTranslation(); - drag.nodeId = null; + if (this.constants.dataManipulation.enabled == true) { + // load the manipulator HTML elements. All styling done in css. + if (this.manipulationDiv === undefined) { + this.manipulationDiv = document.createElement('div'); + this.manipulationDiv.className = 'network-manipulationDiv'; + this.manipulationDiv.id = 'network-manipulationDiv'; + if (this.editMode == true) { + this.manipulationDiv.style.display = "block"; + } + else { + this.manipulationDiv.style.display = "none"; + } + this.containerElement.insertBefore(this.manipulationDiv, this.frame); + } - if (node != null) { - drag.nodeId = node.id; - // select the clicked node if not yet selected - if (!node.isSelected()) { - this._selectObject(node,false); + if (this.editModeDiv === undefined) { + this.editModeDiv = document.createElement('div'); + this.editModeDiv.className = 'network-manipulation-editMode'; + this.editModeDiv.id = 'network-manipulation-editMode'; + if (this.editMode == true) { + this.editModeDiv.style.display = "none"; + } + else { + this.editModeDiv.style.display = "block"; + } + this.containerElement.insertBefore(this.editModeDiv, this.frame); } - // create an array with the selected nodes and their original location and status - for (var objectId in this.selectionObj.nodes) { - if (this.selectionObj.nodes.hasOwnProperty(objectId)) { - var object = this.selectionObj.nodes[objectId]; - var s = { - id: object.id, - node: object, + if (this.closeDiv === undefined) { + this.closeDiv = document.createElement('div'); + this.closeDiv.className = 'network-manipulation-closeDiv'; + this.closeDiv.id = 'network-manipulation-closeDiv'; + this.closeDiv.style.display = this.manipulationDiv.style.display; + this.containerElement.insertBefore(this.closeDiv, this.frame); + } - // store original x, y, xFixed and yFixed, make the node temporarily Fixed - x: object.x, - y: object.y, - xFixed: object.xFixed, - yFixed: object.yFixed - }; + // load the manipulation functions + this._loadMixin(ManipulationMixin); - object.xFixed = true; - object.yFixed = true; + // create the manipulator toolbar + this._createManipulatorBar(); + } + else { + if (this.manipulationDiv !== undefined) { + // removes all the bindings and overloads + this._createManipulatorBar(); + // remove the manipulation divs + this.containerElement.removeChild(this.manipulationDiv); + this.containerElement.removeChild(this.editModeDiv); + this.containerElement.removeChild(this.closeDiv); - drag.selection.push(s); - } + this.manipulationDiv = undefined; + this.editModeDiv = undefined; + this.closeDiv = undefined; + // remove the mixin functions + this._clearMixin(ManipulationMixin); } } }; /** - * handle drag event + * Mixin the navigation (User Interface) system and initialize the parameters required + * + * @private + */ + exports._loadNavigationControls = function () { + this._loadMixin(NavigationMixin); + + // the clean function removes the button divs, this is done to remove the bindings. + this._cleanNavigation(); + if (this.constants.navigation.enabled == true) { + this._loadNavigationElements(); + } + }; + + + /** + * Mixin the hierarchical layout system. + * * @private */ - Network.prototype._onDrag = function (event) { - this._handleOnDrag(event) + exports._loadHierarchySystem = function () { + this._loadMixin(HierarchicalLayoutMixin); }; +/***/ }, +/* 46 */ +/***/ function(module, exports, __webpack_require__) { + + + /** + * Expose `Emitter`. + */ + + module.exports = Emitter; + /** - * This function is called by _onDrag. - * It is separated out because we can then overload it for the datamanipulation system. + * Initialize a new `Emitter`. * - * @private + * @api public */ - Network.prototype._handleOnDrag = function(event) { - if (this.drag.pinched) { - return; - } - var pointer = this._getPointer(event.gesture.center); + function Emitter(obj) { + if (obj) return mixin(obj); + }; - var me = this; - var drag = this.drag; - var selection = drag.selection; - if (selection && selection.length && this.constants.dragNodes == true) { - // calculate delta's and new location - var deltaX = pointer.x - drag.pointer.x; - var deltaY = pointer.y - drag.pointer.y; + /** + * Mixin the emitter properties. + * + * @param {Object} obj + * @return {Object} + * @api private + */ - // update position of all selected nodes - selection.forEach(function (s) { - var node = s.node; + function mixin(obj) { + for (var key in Emitter.prototype) { + obj[key] = Emitter.prototype[key]; + } + return obj; + } - if (!s.xFixed) { - node.x = me._XconvertDOMtoCanvas(me._XconvertCanvasToDOM(s.x) + deltaX); - } + /** + * Listen on the given `event` with `fn`. + * + * @param {String} event + * @param {Function} fn + * @return {Emitter} + * @api public + */ - if (!s.yFixed) { - node.y = me._YconvertDOMtoCanvas(me._YconvertCanvasToDOM(s.y) + deltaY); - } - }); + Emitter.prototype.on = + Emitter.prototype.addEventListener = function(event, fn){ + this._callbacks = this._callbacks || {}; + (this._callbacks[event] = this._callbacks[event] || []) + .push(fn); + return this; + }; + /** + * Adds an `event` listener that will be invoked a single + * time then automatically removed. + * + * @param {String} event + * @param {Function} fn + * @return {Emitter} + * @api public + */ - // start _animationStep if not yet running - if (!this.moving) { - this.moving = true; - this.start(); - } - } - else { - if (this.constants.dragNetwork == true) { - // move the network - var diffX = pointer.x - this.drag.pointer.x; - var diffY = pointer.y - this.drag.pointer.y; + Emitter.prototype.once = function(event, fn){ + var self = this; + this._callbacks = this._callbacks || {}; - this._setTranslation( - this.drag.translation.x + diffX, - this.drag.translation.y + diffY - ); - this._redraw(); - // this.moving = true; - // this.start(); - } + function on() { + self.off(event, on); + fn.apply(this, arguments); } + + on.fn = fn; + this.on(event, on); + return this; }; /** - * handle drag start event - * @private + * Remove the given callback for `event` or all + * registered callbacks. + * + * @param {String} event + * @param {Function} fn + * @return {Emitter} + * @api public */ - Network.prototype._onDragEnd = function () { - this.drag.dragging = false; - var selection = this.drag.selection; - if (selection && selection.length) { - selection.forEach(function (s) { - // restore original xFixed and yFixed - s.node.xFixed = s.xFixed; - s.node.yFixed = s.yFixed; - }); - this.moving = true; - this.start(); + + Emitter.prototype.off = + Emitter.prototype.removeListener = + Emitter.prototype.removeAllListeners = + Emitter.prototype.removeEventListener = function(event, fn){ + this._callbacks = this._callbacks || {}; + + // all + if (0 == arguments.length) { + this._callbacks = {}; + return this; } - else { - this._redraw(); + + // specific event + var callbacks = this._callbacks[event]; + if (!callbacks) return this; + + // remove all handlers + if (1 == arguments.length) { + delete this._callbacks[event]; + return this; } + // remove specific handler + var cb; + for (var i = 0; i < callbacks.length; i++) { + cb = callbacks[i]; + if (cb === fn || cb.fn === fn) { + callbacks.splice(i, 1); + break; + } + } + return this; }; /** - * handle tap/click event: select/unselect a node - * @private + * Emit `event` with the given args. + * + * @param {String} event + * @param {Mixed} ... + * @return {Emitter} */ - Network.prototype._onTap = function (event) { - var pointer = this._getPointer(event.gesture.center); - this.pointerPosition = pointer; - this._handleTap(pointer); - }; + Emitter.prototype.emit = function(event){ + this._callbacks = this._callbacks || {}; + var args = [].slice.call(arguments, 1) + , callbacks = this._callbacks[event]; + if (callbacks) { + callbacks = callbacks.slice(0); + for (var i = 0, len = callbacks.length; i < len; ++i) { + callbacks[i].apply(this, args); + } + } - /** - * handle doubletap event - * @private - */ - Network.prototype._onDoubleTap = function (event) { - var pointer = this._getPointer(event.gesture.center); - this._handleDoubleTap(pointer); + return this; }; - /** - * handle long tap event: multi select nodes - * @private + * Return array of callbacks for `event`. + * + * @param {String} event + * @return {Array} + * @api public */ - Network.prototype._onHold = function (event) { - var pointer = this._getPointer(event.gesture.center); - this.pointerPosition = pointer; - this._handleOnHold(pointer); + + Emitter.prototype.listeners = function(event){ + this._callbacks = this._callbacks || {}; + return this._callbacks[event] || []; }; /** - * handle the release of the screen + * Check if this emitter has `event` handlers. * - * @private + * @param {String} event + * @return {Boolean} + * @api public */ - Network.prototype._onRelease = function (event) { - var pointer = this._getPointer(event.gesture.center); - this._handleOnRelease(pointer); + + Emitter.prototype.hasListeners = function(event){ + return !! this.listeners(event).length; }; - /** - * Handle pinch event - * @param event - * @private - */ - Network.prototype._onPinch = function (event) { - var pointer = this._getPointer(event.gesture.center); - this.drag.pinched = true; - if (!('scale' in this.pinch)) { - this.pinch.scale = 1; - } +/***/ }, +/* 47 */ +/***/ function(module, exports, __webpack_require__) { + + var __WEBPACK_AMD_DEFINE_RESULT__;/* WEBPACK VAR INJECTION */(function(global, module) {//! moment.js + //! version : 2.7.0 + //! authors : Tim Wood, Iskren Chernev, Moment.js contributors + //! license : MIT + //! momentjs.com + + (function (undefined) { + + /************************************ + Constants + ************************************/ + + var moment, + VERSION = "2.7.0", + // the global-scope this is NOT the global object in Node.js + globalScope = typeof global !== 'undefined' ? global : this, + oldGlobalMoment, + round = Math.round, + i, - // TODO: enabled moving while pinching? - var scale = this.pinch.scale * event.gesture.scale; - this._zoom(scale, pointer) - }; + YEAR = 0, + MONTH = 1, + DATE = 2, + HOUR = 3, + MINUTE = 4, + SECOND = 5, + MILLISECOND = 6, - /** - * Zoom the network in or out - * @param {Number} scale a number around 1, and between 0.01 and 10 - * @param {{x: Number, y: Number}} pointer Position on screen - * @return {Number} appliedScale scale is limited within the boundaries - * @private - */ - Network.prototype._zoom = function(scale, pointer) { - if (this.constants.zoomable == true) { - var scaleOld = this._getScale(); - if (scale < 0.00001) { - scale = 0.00001; - } - if (scale > 10) { - scale = 10; - } + // internal storage for language config files + languages = {}, - var preScaleDragPointer = null; - if (this.drag !== undefined) { - if (this.drag.dragging == true) { - preScaleDragPointer = this.DOMtoCanvas(this.drag.pointer); - } - } - // + this.frame.canvas.clientHeight / 2 - var translation = this._getTranslation(); + // moment internal properties + momentProperties = { + _isAMomentObject: null, + _i : null, + _f : null, + _l : null, + _strict : null, + _tzm : null, + _isUTC : null, + _offset : null, // optional. Combine with _isUTC + _pf : null, + _lang : null // optional + }, - var scaleFrac = scale / scaleOld; - var tx = (1 - scaleFrac) * pointer.x + translation.x * scaleFrac; - var ty = (1 - scaleFrac) * pointer.y + translation.y * scaleFrac; + // check for nodeJS + hasModule = (typeof module !== 'undefined' && module.exports), - this.areaCenter = {"x" : this._XconvertDOMtoCanvas(pointer.x), - "y" : this._YconvertDOMtoCanvas(pointer.y)}; + // ASP.NET json date format regex + aspNetJsonRegex = /^\/?Date\((\-?\d+)/i, + aspNetTimeSpanJsonRegex = /(\-)?(?:(\d*)\.)?(\d+)\:(\d+)(?:\:(\d+)\.?(\d{3})?)?/, - this._setScale(scale); - this._setTranslation(tx, ty); - this.updateClustersDefault(); + // from http://docs.closure-library.googlecode.com/git/closure_goog_date_date.js.source.html + // somewhat more in line with 4.4.3.2 2004 spec, but allows decimal anywhere + isoDurationRegex = /^(-)?P(?:(?:([0-9,.]*)Y)?(?:([0-9,.]*)M)?(?:([0-9,.]*)D)?(?:T(?:([0-9,.]*)H)?(?:([0-9,.]*)M)?(?:([0-9,.]*)S)?)?|([0-9,.]*)W)$/, - if (preScaleDragPointer != null) { - var postScaleDragPointer = this.canvasToDOM(preScaleDragPointer); - this.drag.pointer.x = postScaleDragPointer.x; - this.drag.pointer.y = postScaleDragPointer.y; - } + // format tokens + formattingTokens = /(\[[^\[]*\])|(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Q|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|mm?|ss?|S{1,4}|X|zz?|ZZ?|.)/g, + localFormattingTokens = /(\[[^\[]*\])|(\\)?(LT|LL?L?L?|l{1,4})/g, - this._redraw(); + // parsing token regexes + parseTokenOneOrTwoDigits = /\d\d?/, // 0 - 99 + parseTokenOneToThreeDigits = /\d{1,3}/, // 0 - 999 + parseTokenOneToFourDigits = /\d{1,4}/, // 0 - 9999 + parseTokenOneToSixDigits = /[+\-]?\d{1,6}/, // -999,999 - 999,999 + parseTokenDigits = /\d+/, // nonzero number of digits + parseTokenWord = /[0-9]*['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF\/]+(\s*?[\u0600-\u06FF]+){1,2}/i, // any word (or two) characters or numbers including two/three word month in arabic. + parseTokenTimezone = /Z|[\+\-]\d\d:?\d\d/gi, // +00:00 -00:00 +0000 -0000 or Z + parseTokenT = /T/i, // T (ISO separator) + parseTokenTimestampMs = /[\+\-]?\d+(\.\d{1,3})?/, // 123456789 123456789.123 + parseTokenOrdinal = /\d{1,2}/, - if (scaleOld < scale) { - this.emit("zoom", {direction:"+"}); - } - else { - this.emit("zoom", {direction:"-"}); - } + //strict parsing regexes + parseTokenOneDigit = /\d/, // 0 - 9 + parseTokenTwoDigits = /\d\d/, // 00 - 99 + parseTokenThreeDigits = /\d{3}/, // 000 - 999 + parseTokenFourDigits = /\d{4}/, // 0000 - 9999 + parseTokenSixDigits = /[+-]?\d{6}/, // -999,999 - 999,999 + parseTokenSignedNumber = /[+-]?\d+/, // -inf - inf - return scale; - } - }; + // iso 8601 regex + // 0000-00-00 0000-W00 or 0000-W00-0 + T + 00 or 00:00 or 00:00:00 or 00:00:00.000 + +00:00 or +0000 or +00) + isoRegex = /^\s*(?:[+-]\d{6}|\d{4})-(?:(\d\d-\d\d)|(W\d\d$)|(W\d\d-\d)|(\d\d\d))((T| )(\d\d(:\d\d(:\d\d(\.\d+)?)?)?)?([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/, + isoFormat = 'YYYY-MM-DDTHH:mm:ssZ', - /** - * Event handler for mouse wheel event, used to zoom the timeline - * See http://adomas.org/javascript-mouse-wheel/ - * https://github.com/EightMedia/hammer.js/issues/256 - * @param {MouseEvent} event - * @private - */ - Network.prototype._onMouseWheel = function(event) { - // retrieve delta - var delta = 0; - if (event.wheelDelta) { /* IE/Opera. */ - delta = event.wheelDelta/120; - } else if (event.detail) { /* Mozilla case. */ - // In Mozilla, sign of delta is different than in IE. - // Also, delta is multiple of 3. - delta = -event.detail/3; - } + isoDates = [ + ['YYYYYY-MM-DD', /[+-]\d{6}-\d{2}-\d{2}/], + ['YYYY-MM-DD', /\d{4}-\d{2}-\d{2}/], + ['GGGG-[W]WW-E', /\d{4}-W\d{2}-\d/], + ['GGGG-[W]WW', /\d{4}-W\d{2}/], + ['YYYY-DDD', /\d{4}-\d{3}/] + ], - // If delta is nonzero, handle it. - // Basically, delta is now positive if wheel was scrolled up, - // and negative, if wheel was scrolled down. - if (delta) { + // iso time formats and regexes + isoTimes = [ + ['HH:mm:ss.SSSS', /(T| )\d\d:\d\d:\d\d\.\d+/], + ['HH:mm:ss', /(T| )\d\d:\d\d:\d\d/], + ['HH:mm', /(T| )\d\d:\d\d/], + ['HH', /(T| )\d\d/] + ], - // calculate the new scale - var scale = this._getScale(); - var zoom = delta / 10; - if (delta < 0) { - zoom = zoom / (1 - zoom); - } - scale *= (1 + zoom); + // timezone chunker "+10:00" > ["10", "00"] or "-1530" > ["-15", "30"] + parseTimezoneChunker = /([\+\-]|\d\d)/gi, - // calculate the pointer location - var gesture = hammerUtil.fakeGesture(this, event); - var pointer = this._getPointer(gesture.center); + // getter and setter names + proxyGettersAndSetters = 'Date|Hours|Minutes|Seconds|Milliseconds'.split('|'), + unitMillisecondFactors = { + 'Milliseconds' : 1, + 'Seconds' : 1e3, + 'Minutes' : 6e4, + 'Hours' : 36e5, + 'Days' : 864e5, + 'Months' : 2592e6, + 'Years' : 31536e6 + }, - // apply the new scale - this._zoom(scale, pointer); - } + unitAliases = { + ms : 'millisecond', + s : 'second', + m : 'minute', + h : 'hour', + d : 'day', + D : 'date', + w : 'week', + W : 'isoWeek', + M : 'month', + Q : 'quarter', + y : 'year', + DDD : 'dayOfYear', + e : 'weekday', + E : 'isoWeekday', + gg: 'weekYear', + GG: 'isoWeekYear' + }, - // Prevent default actions caused by mouse wheel. - event.preventDefault(); - }; + camelFunctions = { + dayofyear : 'dayOfYear', + isoweekday : 'isoWeekday', + isoweek : 'isoWeek', + weekyear : 'weekYear', + isoweekyear : 'isoWeekYear' + }, + // format function strings + formatFunctions = {}, - /** - * Mouse move handler for checking whether the title moves over a node with a title. - * @param {Event} event - * @private - */ - Network.prototype._onMouseMoveTitle = function (event) { - var gesture = hammerUtil.fakeGesture(this, event); - var pointer = this._getPointer(gesture.center); + // default relative time thresholds + relativeTimeThresholds = { + s: 45, //seconds to minutes + m: 45, //minutes to hours + h: 22, //hours to days + dd: 25, //days to month (month == 1) + dm: 45, //days to months (months > 1) + dy: 345 //days to year + }, - // check if the previously selected node is still selected - if (this.popupObj) { - this._checkHidePopup(pointer); - } + // tokens to ordinalize and pad + ordinalizeTokens = 'DDD w W M D d'.split(' '), + paddedTokens = 'M D H h m s w W'.split(' '), - // start a timeout that will check if the mouse is positioned above - // an element - var me = this; - var checkShow = function() { - me._checkShowPopup(pointer); - }; - if (this.popupTimer) { - clearInterval(this.popupTimer); // stop any running calculationTimer - } - if (!this.drag.dragging) { - this.popupTimer = setTimeout(checkShow, this.constants.tooltip.delay); - } + formatTokenFunctions = { + M : function () { + return this.month() + 1; + }, + MMM : function (format) { + return this.lang().monthsShort(this, format); + }, + MMMM : function (format) { + return this.lang().months(this, format); + }, + D : function () { + return this.date(); + }, + DDD : function () { + return this.dayOfYear(); + }, + d : function () { + return this.day(); + }, + dd : function (format) { + return this.lang().weekdaysMin(this, format); + }, + ddd : function (format) { + return this.lang().weekdaysShort(this, format); + }, + dddd : function (format) { + return this.lang().weekdays(this, format); + }, + w : function () { + return this.week(); + }, + W : function () { + return this.isoWeek(); + }, + YY : function () { + return leftZeroFill(this.year() % 100, 2); + }, + YYYY : function () { + return leftZeroFill(this.year(), 4); + }, + YYYYY : function () { + return leftZeroFill(this.year(), 5); + }, + YYYYYY : function () { + var y = this.year(), sign = y >= 0 ? '+' : '-'; + return sign + leftZeroFill(Math.abs(y), 6); + }, + gg : function () { + return leftZeroFill(this.weekYear() % 100, 2); + }, + gggg : function () { + return leftZeroFill(this.weekYear(), 4); + }, + ggggg : function () { + return leftZeroFill(this.weekYear(), 5); + }, + GG : function () { + return leftZeroFill(this.isoWeekYear() % 100, 2); + }, + GGGG : function () { + return leftZeroFill(this.isoWeekYear(), 4); + }, + GGGGG : function () { + return leftZeroFill(this.isoWeekYear(), 5); + }, + e : function () { + return this.weekday(); + }, + E : function () { + return this.isoWeekday(); + }, + a : function () { + return this.lang().meridiem(this.hours(), this.minutes(), true); + }, + A : function () { + return this.lang().meridiem(this.hours(), this.minutes(), false); + }, + H : function () { + return this.hours(); + }, + h : function () { + return this.hours() % 12 || 12; + }, + m : function () { + return this.minutes(); + }, + s : function () { + return this.seconds(); + }, + S : function () { + return toInt(this.milliseconds() / 100); + }, + SS : function () { + return leftZeroFill(toInt(this.milliseconds() / 10), 2); + }, + SSS : function () { + return leftZeroFill(this.milliseconds(), 3); + }, + SSSS : function () { + return leftZeroFill(this.milliseconds(), 3); + }, + Z : function () { + var a = -this.zone(), + b = "+"; + if (a < 0) { + a = -a; + b = "-"; + } + return b + leftZeroFill(toInt(a / 60), 2) + ":" + leftZeroFill(toInt(a) % 60, 2); + }, + ZZ : function () { + var a = -this.zone(), + b = "+"; + if (a < 0) { + a = -a; + b = "-"; + } + return b + leftZeroFill(toInt(a / 60), 2) + leftZeroFill(toInt(a) % 60, 2); + }, + z : function () { + return this.zoneAbbr(); + }, + zz : function () { + return this.zoneName(); + }, + X : function () { + return this.unix(); + }, + Q : function () { + return this.quarter(); + } + }, + lists = ['months', 'monthsShort', 'weekdays', 'weekdaysShort', 'weekdaysMin']; - /** - * Adding hover highlights - */ - if (this.constants.hover == true) { - // removing all hover highlights - for (var edgeId in this.hoverObj.edges) { - if (this.hoverObj.edges.hasOwnProperty(edgeId)) { - this.hoverObj.edges[edgeId].hover = false; - delete this.hoverObj.edges[edgeId]; - } + // Pick the first defined of two or three arguments. dfl comes from + // default. + function dfl(a, b, c) { + switch (arguments.length) { + case 2: return a != null ? a : b; + case 3: return a != null ? a : b != null ? b : c; + default: throw new Error("Implement me"); + } } - // adding hover highlights - var obj = this._getNodeAt(pointer); - if (obj == null) { - obj = this._getEdgeAt(pointer); - } - if (obj != null) { - this._hoverObject(obj); + function defaultParsingFlags() { + // We need to deep clone this object, and es5 standard is not very + // helpful. + return { + empty : false, + unusedTokens : [], + unusedInput : [], + overflow : -2, + charsLeftOver : 0, + nullInput : false, + invalidMonth : null, + invalidFormat : false, + userInvalidated : false, + iso: false + }; } - // removing all node hover highlights except for the selected one. - for (var nodeId in this.hoverObj.nodes) { - if (this.hoverObj.nodes.hasOwnProperty(nodeId)) { - if (obj instanceof Node && obj.id != nodeId || obj instanceof Edge || obj == null) { - this._blurObject(this.hoverObj.nodes[nodeId]); - delete this.hoverObj.nodes[nodeId]; + function deprecate(msg, fn) { + var firstTime = true; + function printMsg() { + if (moment.suppressDeprecationWarnings === false && + typeof console !== 'undefined' && console.warn) { + console.warn("Deprecation warning: " + msg); + } } - } + return extend(function () { + if (firstTime) { + printMsg(); + firstTime = false; + } + return fn.apply(this, arguments); + }, fn); } - this.redraw(); - } - }; - - /** - * Check if there is an element on the given position in the network - * (a node or edge). If so, and if this element has a title, - * show a popup window with its title. - * - * @param {{x:Number, y:Number}} pointer - * @private - */ - Network.prototype._checkShowPopup = function (pointer) { - var obj = { - left: this._XconvertDOMtoCanvas(pointer.x), - top: this._YconvertDOMtoCanvas(pointer.y), - right: this._XconvertDOMtoCanvas(pointer.x), - bottom: this._YconvertDOMtoCanvas(pointer.y) - }; - var id; - var lastPopupNode = this.popupObj; - - if (this.popupObj == undefined) { - // search the nodes for overlap, select the top one in case of multiple nodes - var nodes = this.nodes; - for (id in nodes) { - if (nodes.hasOwnProperty(id)) { - var node = nodes[id]; - if (node.getTitle() !== undefined && node.isOverlappingWith(obj)) { - this.popupObj = node; - break; - } - } + function padToken(func, count) { + return function (a) { + return leftZeroFill(func.call(this, a), count); + }; } - } - - if (this.popupObj === undefined) { - // search the edges for overlap - var edges = this.edges; - for (id in edges) { - if (edges.hasOwnProperty(id)) { - var edge = edges[id]; - if (edge.connected && (edge.getTitle() !== undefined) && - edge.isOverlappingWith(obj)) { - this.popupObj = edge; - break; - } - } + function ordinalizeToken(func, period) { + return function (a) { + return this.lang().ordinal(func.call(this, a), period); + }; } - } - - if (this.popupObj) { - // show popup message window - if (this.popupObj != lastPopupNode) { - var me = this; - if (!me.popup) { - me.popup = new Popup(me.frame, me.constants.tooltip); - } - // adjust a small offset such that the mouse cursor is located in the - // bottom left location of the popup, and you can easily move over the - // popup area - me.popup.setPosition(pointer.x - 3, pointer.y - 3); - me.popup.setText(me.popupObj.getTitle()); - me.popup.show(); + while (ordinalizeTokens.length) { + i = ordinalizeTokens.pop(); + formatTokenFunctions[i + 'o'] = ordinalizeToken(formatTokenFunctions[i], i); } - } - else { - if (this.popup) { - this.popup.hide(); + while (paddedTokens.length) { + i = paddedTokens.pop(); + formatTokenFunctions[i + i] = padToken(formatTokenFunctions[i], 2); } - } - }; + formatTokenFunctions.DDDD = padToken(formatTokenFunctions.DDD, 3); - /** - * Check if the popup must be hided, which is the case when the mouse is no - * longer hovering on the object - * @param {{x:Number, y:Number}} pointer - * @private - */ - Network.prototype._checkHidePopup = function (pointer) { - if (!this.popupObj || !this._getNodeAt(pointer) ) { - this.popupObj = undefined; - if (this.popup) { - this.popup.hide(); + /************************************ + Constructors + ************************************/ + + function Language() { + } - } - }; + // Moment prototype object + function Moment(config) { + checkOverflow(config); + extend(this, config); + } - /** - * Set a new size for the network - * @param {string} width Width in pixels or percentage (for example '800px' - * or '50%') - * @param {string} height Height in pixels or percentage (for example '400px' - * or '30%') - */ - Network.prototype.setSize = function(width, height) { - this.frame.style.width = width; - this.frame.style.height = height; + // Duration Constructor + function Duration(duration) { + var normalizedInput = normalizeObjectUnits(duration), + years = normalizedInput.year || 0, + quarters = normalizedInput.quarter || 0, + months = normalizedInput.month || 0, + weeks = normalizedInput.week || 0, + days = normalizedInput.day || 0, + hours = normalizedInput.hour || 0, + minutes = normalizedInput.minute || 0, + seconds = normalizedInput.second || 0, + milliseconds = normalizedInput.millisecond || 0; - this.frame.canvas.style.width = '100%'; - this.frame.canvas.style.height = '100%'; + // representation for dateAddRemove + this._milliseconds = +milliseconds + + seconds * 1e3 + // 1000 + minutes * 6e4 + // 1000 * 60 + hours * 36e5; // 1000 * 60 * 60 + // Because of dateAddRemove treats 24 hours as different from a + // day when working around DST, we need to store them separately + this._days = +days + + weeks * 7; + // It is impossible translate months into days without knowing + // which months you are are talking about, so we have to store + // it separately. + this._months = +months + + quarters * 3 + + years * 12; - this.frame.canvas.width = this.frame.canvas.clientWidth; - this.frame.canvas.height = this.frame.canvas.clientHeight; + this._data = {}; - if (this.manipulationDiv !== undefined) { - this.manipulationDiv.style.width = this.frame.canvas.clientWidth + "px"; - } - if (this.navigationDivs !== undefined) { - if (this.navigationDivs['wrapper'] !== undefined) { - this.navigationDivs['wrapper'].style.width = this.frame.canvas.clientWidth + "px"; - this.navigationDivs['wrapper'].style.height = this.frame.canvas.clientHeight + "px"; + this._bubble(); } - } - - this.emit('resize', {width:this.frame.canvas.width,height:this.frame.canvas.height}); - }; - /** - * Set a data set with nodes for the network - * @param {Array | DataSet | DataView} nodes The data containing the nodes. - * @private - */ - Network.prototype._setNodes = function(nodes) { - var oldNodesData = this.nodesData; + /************************************ + Helpers + ************************************/ - if (nodes instanceof DataSet || nodes instanceof DataView) { - this.nodesData = nodes; - } - else if (nodes instanceof Array) { - this.nodesData = new DataSet(); - this.nodesData.add(nodes); - } - else if (!nodes) { - this.nodesData = new DataSet(); - } - else { - throw new TypeError('Array or DataSet expected'); - } - if (oldNodesData) { - // unsubscribe from old dataset - util.forEach(this.nodesListeners, function (callback, event) { - oldNodesData.off(event, callback); - }); - } + function extend(a, b) { + for (var i in b) { + if (b.hasOwnProperty(i)) { + a[i] = b[i]; + } + } - // remove drawn nodes - this.nodes = {}; + if (b.hasOwnProperty("toString")) { + a.toString = b.toString; + } - if (this.nodesData) { - // subscribe to new dataset - var me = this; - util.forEach(this.nodesListeners, function (callback, event) { - me.nodesData.on(event, callback); - }); + if (b.hasOwnProperty("valueOf")) { + a.valueOf = b.valueOf; + } - // draw all new nodes - var ids = this.nodesData.getIds(); - this._addNodes(ids); - } - this._updateSelection(); - }; + return a; + } - /** - * Add nodes - * @param {Number[] | String[]} ids - * @private - */ - Network.prototype._addNodes = function(ids) { - var id; - for (var i = 0, len = ids.length; i < len; i++) { - id = ids[i]; - var data = this.nodesData.get(id); - var node = new Node(data, this.images, this.groups, this.constants); - this.nodes[id] = node; // note: this may replace an existing node + function cloneMoment(m) { + var result = {}, i; + for (i in m) { + if (m.hasOwnProperty(i) && momentProperties.hasOwnProperty(i)) { + result[i] = m[i]; + } + } - if ((node.xFixed == false || node.yFixed == false) && (node.x === null || node.y === null)) { - var radius = 10 * 0.1*ids.length; - var angle = 2 * Math.PI * Math.random(); - if (node.xFixed == false) {node.x = radius * Math.cos(angle);} - if (node.yFixed == false) {node.y = radius * Math.sin(angle);} + return result; } - this.moving = true; - } - this._updateNodeIndexList(); - if (this.constants.hierarchicalLayout.enabled == true && this.initializing == false) { - this._resetLevels(); - this._setupHierarchicalLayout(); - } - this._updateCalculationNodes(); - this._reconnectEdges(); - this._updateValueRange(this.nodes); - this.updateLabels(); - }; - /** - * Update existing nodes, or create them when not yet existing - * @param {Number[] | String[]} ids - * @private - */ - Network.prototype._updateNodes = function(ids) { - var nodes = this.nodes, - nodesData = this.nodesData; - for (var i = 0, len = ids.length; i < len; i++) { - var id = ids[i]; - var node = nodes[id]; - var data = nodesData.get(id); - if (node) { - // update node - node.setProperties(data, this.constants); + function absRound(number) { + if (number < 0) { + return Math.ceil(number); + } else { + return Math.floor(number); + } } - else { - // create node - node = new Node(properties, this.images, this.groups, this.constants); - nodes[id] = node; + + // left zero fill a number + // see http://jsperf.com/left-zero-filling for performance comparison + function leftZeroFill(number, targetLength, forceSign) { + var output = '' + Math.abs(number), + sign = number >= 0; + + while (output.length < targetLength) { + output = '0' + output; + } + return (sign ? (forceSign ? '+' : '') : '-') + output; } - } - this.moving = true; - if (this.constants.hierarchicalLayout.enabled == true && this.initializing == false) { - this._resetLevels(); - this._setupHierarchicalLayout(); - } - this._updateNodeIndexList(); - this._reconnectEdges(); - this._updateValueRange(nodes); - }; - /** - * Remove existing nodes. If nodes do not exist, the method will just ignore it. - * @param {Number[] | String[]} ids - * @private - */ - Network.prototype._removeNodes = function(ids) { - var nodes = this.nodes; - for (var i = 0, len = ids.length; i < len; i++) { - var id = ids[i]; - delete nodes[id]; - } - this._updateNodeIndexList(); - if (this.constants.hierarchicalLayout.enabled == true && this.initializing == false) { - this._resetLevels(); - this._setupHierarchicalLayout(); - } - this._updateCalculationNodes(); - this._reconnectEdges(); - this._updateSelection(); - this._updateValueRange(nodes); - }; + // helper function for _.addTime and _.subtractTime + function addOrSubtractDurationFromMoment(mom, duration, isAdding, updateOffset) { + var milliseconds = duration._milliseconds, + days = duration._days, + months = duration._months; + updateOffset = updateOffset == null ? true : updateOffset; + + if (milliseconds) { + mom._d.setTime(+mom._d + milliseconds * isAdding); + } + if (days) { + rawSetter(mom, 'Date', rawGetter(mom, 'Date') + days * isAdding); + } + if (months) { + rawMonthSetter(mom, rawGetter(mom, 'Month') + months * isAdding); + } + if (updateOffset) { + moment.updateOffset(mom, days || months); + } + } - /** - * Load edges by reading the data table - * @param {Array | DataSet | DataView} edges The data containing the edges. - * @private - * @private - */ - Network.prototype._setEdges = function(edges) { - var oldEdgesData = this.edgesData; + // check if is an array + function isArray(input) { + return Object.prototype.toString.call(input) === '[object Array]'; + } - if (edges instanceof DataSet || edges instanceof DataView) { - this.edgesData = edges; - } - else if (edges instanceof Array) { - this.edgesData = new DataSet(); - this.edgesData.add(edges); - } - else if (!edges) { - this.edgesData = new DataSet(); - } - else { - throw new TypeError('Array or DataSet expected'); - } + function isDate(input) { + return Object.prototype.toString.call(input) === '[object Date]' || + input instanceof Date; + } - if (oldEdgesData) { - // unsubscribe from old dataset - util.forEach(this.edgesListeners, function (callback, event) { - oldEdgesData.off(event, callback); - }); - } + // compare two arrays, return the number of differences + function compareArrays(array1, array2, dontConvert) { + var len = Math.min(array1.length, array2.length), + lengthDiff = Math.abs(array1.length - array2.length), + diffs = 0, + i; + for (i = 0; i < len; i++) { + if ((dontConvert && array1[i] !== array2[i]) || + (!dontConvert && toInt(array1[i]) !== toInt(array2[i]))) { + diffs++; + } + } + return diffs + lengthDiff; + } - // remove drawn edges - this.edges = {}; + function normalizeUnits(units) { + if (units) { + var lowered = units.toLowerCase().replace(/(.)s$/, '$1'); + units = unitAliases[units] || camelFunctions[lowered] || lowered; + } + return units; + } - if (this.edgesData) { - // subscribe to new dataset - var me = this; - util.forEach(this.edgesListeners, function (callback, event) { - me.edgesData.on(event, callback); - }); + function normalizeObjectUnits(inputObject) { + var normalizedInput = {}, + normalizedProp, + prop; - // draw all new nodes - var ids = this.edgesData.getIds(); - this._addEdges(ids); - } + for (prop in inputObject) { + if (inputObject.hasOwnProperty(prop)) { + normalizedProp = normalizeUnits(prop); + if (normalizedProp) { + normalizedInput[normalizedProp] = inputObject[prop]; + } + } + } - this._reconnectEdges(); - }; + return normalizedInput; + } - /** - * Add edges - * @param {Number[] | String[]} ids - * @private - */ - Network.prototype._addEdges = function (ids) { - var edges = this.edges, - edgesData = this.edgesData; + function makeList(field) { + var count, setter; - for (var i = 0, len = ids.length; i < len; i++) { - var id = ids[i]; + if (field.indexOf('week') === 0) { + count = 7; + setter = 'day'; + } + else if (field.indexOf('month') === 0) { + count = 12; + setter = 'month'; + } + else { + return; + } - var oldEdge = edges[id]; - if (oldEdge) { - oldEdge.disconnect(); + moment[field] = function (format, index) { + var i, getter, + method = moment.fn._lang[field], + results = []; + + if (typeof format === 'number') { + index = format; + format = undefined; + } + + getter = function (i) { + var m = moment().utc().set(setter, i); + return method.call(moment.fn._lang, m, format || ''); + }; + + if (index != null) { + return getter(index); + } + else { + for (i = 0; i < count; i++) { + results.push(getter(i)); + } + return results; + } + }; } - var data = edgesData.get(id, {"showInternalIds" : true}); - edges[id] = new Edge(data, this, this.constants); - } + function toInt(argumentForCoercion) { + var coercedNumber = +argumentForCoercion, + value = 0; - this.moving = true; - this._updateValueRange(edges); - this._createBezierNodes(); - if (this.constants.hierarchicalLayout.enabled == true && this.initializing == false) { - this._resetLevels(); - this._setupHierarchicalLayout(); - } - this._updateCalculationNodes(); - }; + if (coercedNumber !== 0 && isFinite(coercedNumber)) { + if (coercedNumber >= 0) { + value = Math.floor(coercedNumber); + } else { + value = Math.ceil(coercedNumber); + } + } - /** - * Update existing edges, or create them when not yet existing - * @param {Number[] | String[]} ids - * @private - */ - Network.prototype._updateEdges = function (ids) { - var edges = this.edges, - edgesData = this.edgesData; - for (var i = 0, len = ids.length; i < len; i++) { - var id = ids[i]; + return value; + } - var data = edgesData.get(id); - var edge = edges[id]; - if (edge) { - // update edge - edge.disconnect(); - edge.setProperties(data, this.constants); - edge.connect(); + function daysInMonth(year, month) { + return new Date(Date.UTC(year, month + 1, 0)).getUTCDate(); } - else { - // create edge - edge = new Edge(data, this, this.constants); - this.edges[id] = edge; + + function weeksInYear(year, dow, doy) { + return weekOfYear(moment([year, 11, 31 + dow - doy]), dow, doy).week; } - } - this._createBezierNodes(); - if (this.constants.hierarchicalLayout.enabled == true && this.initializing == false) { - this._resetLevels(); - this._setupHierarchicalLayout(); - } - this.moving = true; - this._updateValueRange(edges); - }; + function daysInYear(year) { + return isLeapYear(year) ? 366 : 365; + } - /** - * Remove existing edges. Non existing ids will be ignored - * @param {Number[] | String[]} ids - * @private - */ - Network.prototype._removeEdges = function (ids) { - var edges = this.edges; - for (var i = 0, len = ids.length; i < len; i++) { - var id = ids[i]; - var edge = edges[id]; - if (edge) { - if (edge.via != null) { - delete this.sectors['support']['nodes'][edge.via.id]; - } - edge.disconnect(); - delete edges[id]; + function isLeapYear(year) { + return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0; } - } - this.moving = true; - this._updateValueRange(edges); - if (this.constants.hierarchicalLayout.enabled == true && this.initializing == false) { - this._resetLevels(); - this._setupHierarchicalLayout(); - } - this._updateCalculationNodes(); - }; + function checkOverflow(m) { + var overflow; + if (m._a && m._pf.overflow === -2) { + overflow = + m._a[MONTH] < 0 || m._a[MONTH] > 11 ? MONTH : + m._a[DATE] < 1 || m._a[DATE] > daysInMonth(m._a[YEAR], m._a[MONTH]) ? DATE : + m._a[HOUR] < 0 || m._a[HOUR] > 23 ? HOUR : + m._a[MINUTE] < 0 || m._a[MINUTE] > 59 ? MINUTE : + m._a[SECOND] < 0 || m._a[SECOND] > 59 ? SECOND : + m._a[MILLISECOND] < 0 || m._a[MILLISECOND] > 999 ? MILLISECOND : + -1; - /** - * Reconnect all edges - * @private - */ - Network.prototype._reconnectEdges = function() { - var id, - nodes = this.nodes, - edges = this.edges; - for (id in nodes) { - if (nodes.hasOwnProperty(id)) { - nodes[id].edges = []; - } - } + if (m._pf._overflowDayOfYear && (overflow < YEAR || overflow > DATE)) { + overflow = DATE; + } - for (id in edges) { - if (edges.hasOwnProperty(id)) { - var edge = edges[id]; - edge.from = null; - edge.to = null; - edge.connect(); + m._pf.overflow = overflow; + } } - } - }; - /** - * 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; + function isValid(m) { + if (m._isValid == null) { + m._isValid = !isNaN(m._d.getTime()) && + m._pf.overflow < 0 && + !m._pf.empty && + !m._pf.invalidMonth && + !m._pf.nullInput && + !m._pf.invalidFormat && + !m._pf.userInvalidated; - // determine the range of the objects - var valueMin = undefined; - var valueMax = undefined; - 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); - } + if (m._strict) { + m._isValid = m._isValid && + m._pf.charsLeftOver === 0 && + m._pf.unusedTokens.length === 0; + } + } + return m._isValid; } - } - // adjust the range of all objects - if (valueMin !== undefined && valueMax !== undefined) { - for (id in obj) { - if (obj.hasOwnProperty(id)) { - obj[id].setValueRange(valueMin, valueMax); - } + function normalizeLanguage(key) { + return key ? key.toLowerCase().replace('_', '-') : key; } - } - }; - /** - * Redraw the network with the current data - * chart will be resized too. - */ - Network.prototype.redraw = function() { - this.setSize(this.constants.width, this.constants.height); - this._redraw(); - }; + // Return a moment from input, that is local/utc/zone equivalent to model. + function makeAs(input, model) { + return model._isUTC ? moment(input).zone(model._offset || 0) : + moment(input).local(); + } - /** - * Redraw the network with the current data - * @private - */ - Network.prototype._redraw = function() { - var ctx = this.frame.canvas.getContext('2d'); - // clear the canvas - var w = this.frame.canvas.width; - var h = this.frame.canvas.height; - ctx.clearRect(0, 0, w, h); + /************************************ + Languages + ************************************/ - // set scaling and translation - ctx.save(); - ctx.translate(this.translation.x, this.translation.y); - ctx.scale(this.scale, this.scale); - this.canvasTopLeft = { - "x": this._XconvertDOMtoCanvas(0), - "y": this._YconvertDOMtoCanvas(0) - }; - this.canvasBottomRight = { - "x": this._XconvertDOMtoCanvas(this.frame.canvas.clientWidth), - "y": this._YconvertDOMtoCanvas(this.frame.canvas.clientHeight) - }; + extend(Language.prototype, { + set : function (config) { + var prop, i; + for (i in config) { + prop = config[i]; + if (typeof prop === 'function') { + this[i] = prop; + } else { + this['_' + i] = prop; + } + } + }, - this._doInAllSectors("_drawAllSectorNodes",ctx); - if (this.drag.dragging == false || this.drag.dragging === undefined || this.constants.hideEdgesOnDrag == false) { - this._doInAllSectors("_drawEdges",ctx); - } + _months : "January_February_March_April_May_June_July_August_September_October_November_December".split("_"), + months : function (m) { + return this._months[m.month()]; + }, - if (this.drag.dragging == false || this.drag.dragging === undefined || this.constants.hideNodesOnDrag == false) { - this._doInAllSectors("_drawNodes",ctx,false); - } + _monthsShort : "Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"), + monthsShort : function (m) { + return this._monthsShort[m.month()]; + }, - if (this.controlNodesActive == true) { - this._doInAllSectors("_drawControlNodes",ctx); - } + monthsParse : function (monthName) { + var i, mom, regex; - // this._doInSupportSector("_drawNodes",ctx,true); - // this._drawTree(ctx,"#F00F0F"); + if (!this._monthsParse) { + this._monthsParse = []; + } - // restore original scaling and translation - ctx.restore(); - }; + for (i = 0; i < 12; i++) { + // make the regex if we don't have it already + if (!this._monthsParse[i]) { + mom = moment.utc([2000, i]); + regex = '^' + this.months(mom, '') + '|^' + this.monthsShort(mom, ''); + this._monthsParse[i] = new RegExp(regex.replace('.', ''), 'i'); + } + // test the regex + if (this._monthsParse[i].test(monthName)) { + return i; + } + } + }, - /** - * Set the translation of the network - * @param {Number} offsetX Horizontal offset - * @param {Number} offsetY Vertical offset - * @private - */ - Network.prototype._setTranslation = function(offsetX, offsetY) { - if (this.translation === undefined) { - this.translation = { - x: 0, - y: 0 - }; - } + _weekdays : "Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"), + weekdays : function (m) { + return this._weekdays[m.day()]; + }, - if (offsetX !== undefined) { - this.translation.x = offsetX; - } - if (offsetY !== undefined) { - this.translation.y = offsetY; - } + _weekdaysShort : "Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"), + weekdaysShort : function (m) { + return this._weekdaysShort[m.day()]; + }, - this.emit('viewChanged'); - }; + _weekdaysMin : "Su_Mo_Tu_We_Th_Fr_Sa".split("_"), + weekdaysMin : function (m) { + return this._weekdaysMin[m.day()]; + }, - /** - * Get the translation of the network - * @return {Object} translation An object with parameters x and y, both a number - * @private - */ - Network.prototype._getTranslation = function() { - return { - x: this.translation.x, - y: this.translation.y - }; - }; + weekdaysParse : function (weekdayName) { + var i, mom, regex; - /** - * Scale the network - * @param {Number} scale Scaling factor 1.0 is unscaled - * @private - */ - Network.prototype._setScale = function(scale) { - this.scale = scale; - }; + if (!this._weekdaysParse) { + this._weekdaysParse = []; + } - /** - * Get the current scale of the network - * @return {Number} scale Scaling factor 1.0 is unscaled - * @private - */ - Network.prototype._getScale = function() { - return this.scale; - }; + for (i = 0; i < 7; i++) { + // make the regex if we don't have it already + if (!this._weekdaysParse[i]) { + mom = moment([2000, 1]).day(i); + regex = '^' + this.weekdays(mom, '') + '|^' + this.weekdaysShort(mom, '') + '|^' + this.weekdaysMin(mom, ''); + this._weekdaysParse[i] = new RegExp(regex.replace('.', ''), 'i'); + } + // test the regex + if (this._weekdaysParse[i].test(weekdayName)) { + return i; + } + } + }, - /** - * Convert the X coordinate in DOM-space (coordinate point in browser relative to the container div) to - * the X coordinate in canvas-space (the simulation sandbox, which the camera looks upon) - * @param {number} x - * @returns {number} - * @private - */ - Network.prototype._XconvertDOMtoCanvas = function(x) { - return (x - this.translation.x) / this.scale; - }; + _longDateFormat : { + LT : "h:mm A", + L : "MM/DD/YYYY", + LL : "MMMM D YYYY", + LLL : "MMMM D YYYY LT", + LLLL : "dddd, MMMM D YYYY LT" + }, + longDateFormat : function (key) { + var output = this._longDateFormat[key]; + if (!output && this._longDateFormat[key.toUpperCase()]) { + output = this._longDateFormat[key.toUpperCase()].replace(/MMMM|MM|DD|dddd/g, function (val) { + return val.slice(1); + }); + this._longDateFormat[key] = output; + } + return output; + }, + + isPM : function (input) { + // IE8 Quirks Mode & IE7 Standards Mode do not allow accessing strings like arrays + // Using charAt should be more compatible. + return ((input + '').toLowerCase().charAt(0) === 'p'); + }, - /** - * Convert the X coordinate in canvas-space (the simulation sandbox, which the camera looks upon) to - * the X coordinate in DOM-space (coordinate point in browser relative to the container div) - * @param {number} x - * @returns {number} - * @private - */ - Network.prototype._XconvertCanvasToDOM = function(x) { - return x * this.scale + this.translation.x; - }; + _meridiemParse : /[ap]\.?m?\.?/i, + meridiem : function (hours, minutes, isLower) { + if (hours > 11) { + return isLower ? 'pm' : 'PM'; + } else { + return isLower ? 'am' : 'AM'; + } + }, - /** - * Convert the Y coordinate in DOM-space (coordinate point in browser relative to the container div) to - * the Y coordinate in canvas-space (the simulation sandbox, which the camera looks upon) - * @param {number} y - * @returns {number} - * @private - */ - Network.prototype._YconvertDOMtoCanvas = function(y) { - return (y - this.translation.y) / this.scale; - }; + _calendar : { + sameDay : '[Today at] LT', + nextDay : '[Tomorrow at] LT', + nextWeek : 'dddd [at] LT', + lastDay : '[Yesterday at] LT', + lastWeek : '[Last] dddd [at] LT', + sameElse : 'L' + }, + calendar : function (key, mom) { + var output = this._calendar[key]; + return typeof output === 'function' ? output.apply(mom) : output; + }, - /** - * Convert the Y coordinate in canvas-space (the simulation sandbox, which the camera looks upon) to - * the Y coordinate in DOM-space (coordinate point in browser relative to the container div) - * @param {number} y - * @returns {number} - * @private - */ - Network.prototype._YconvertCanvasToDOM = function(y) { - return y * this.scale + this.translation.y ; - }; + _relativeTime : { + future : "in %s", + past : "%s ago", + s : "a few seconds", + m : "a minute", + mm : "%d minutes", + h : "an hour", + hh : "%d hours", + d : "a day", + dd : "%d days", + M : "a month", + MM : "%d months", + y : "a year", + yy : "%d years" + }, + relativeTime : function (number, withoutSuffix, string, isFuture) { + var output = this._relativeTime[string]; + return (typeof output === 'function') ? + output(number, withoutSuffix, string, isFuture) : + output.replace(/%d/i, number); + }, + pastFuture : function (diff, output) { + var format = this._relativeTime[diff > 0 ? 'future' : 'past']; + return typeof format === 'function' ? format(output) : format.replace(/%s/i, output); + }, + ordinal : function (number) { + return this._ordinal.replace("%d", number); + }, + _ordinal : "%d", - /** - * - * @param {object} pos = {x: number, y: number} - * @returns {{x: number, y: number}} - * @constructor - */ - Network.prototype.canvasToDOM = function(pos) { - return {x:this._XconvertCanvasToDOM(pos.x),y:this._YconvertCanvasToDOM(pos.y)}; - } + preparse : function (string) { + return string; + }, - /** - * - * @param {object} pos = {x: number, y: number} - * @returns {{x: number, y: number}} - * @constructor - */ - Network.prototype.DOMtoCanvas = function(pos) { - return {x:this._XconvertDOMtoCanvas(pos.x),y:this._YconvertDOMtoCanvas(pos.y)}; - } + postformat : function (string) { + return string; + }, - /** - * Redraw all nodes - * The 2d context of a HTML canvas can be retrieved by canvas.getContext('2d'); - * @param {CanvasRenderingContext2D} ctx - * @param {Boolean} [alwaysShow] - * @private - */ - Network.prototype._drawNodes = function(ctx,alwaysShow) { - if (alwaysShow === undefined) { - alwaysShow = false; - } + week : function (mom) { + return weekOfYear(mom, this._week.dow, this._week.doy).week; + }, - // first draw the unselected nodes - var nodes = this.nodes; - var selected = []; + _week : { + dow : 0, // Sunday is the first day of the week. + doy : 6 // The week that contains Jan 1st is the first week of the year. + }, - for (var id in nodes) { - if (nodes.hasOwnProperty(id)) { - nodes[id].setScaleAndPos(this.scale,this.canvasTopLeft,this.canvasBottomRight); - if (nodes[id].isSelected()) { - selected.push(id); - } - else { - if (nodes[id].inArea() || alwaysShow) { - nodes[id].draw(ctx); + _invalidDate: 'Invalid date', + invalidDate: function () { + return this._invalidDate; } - } - } - } - - // draw the selected nodes on top - for (var s = 0, sMax = selected.length; s < sMax; s++) { - if (nodes[selected[s]].inArea() || alwaysShow) { - nodes[selected[s]].draw(ctx); - } - } - }; + }); - /** - * Redraw all edges - * The 2d context of a HTML canvas can be retrieved by canvas.getContext('2d'); - * @param {CanvasRenderingContext2D} ctx - * @private - */ - Network.prototype._drawEdges = function(ctx) { - var edges = this.edges; - for (var id in edges) { - if (edges.hasOwnProperty(id)) { - var edge = edges[id]; - edge.setScale(this.scale); - if (edge.connected) { - edges[id].draw(ctx); - } + // Loads a language definition into the `languages` cache. The function + // takes a key and optionally values. If not in the browser and no values + // are provided, it will load the language file module. As a convenience, + // this function also returns the language values. + function loadLang(key, values) { + values.abbr = key; + if (!languages[key]) { + languages[key] = new Language(); + } + languages[key].set(values); + return languages[key]; } - } - }; - /** - * Redraw all edges - * The 2d context of a HTML canvas can be retrieved by canvas.getContext('2d'); - * @param {CanvasRenderingContext2D} ctx - * @private - */ - Network.prototype._drawControlNodes = function(ctx) { - var edges = this.edges; - for (var id in edges) { - if (edges.hasOwnProperty(id)) { - edges[id]._drawControlNodes(ctx); + // Remove a language from the `languages` cache. Mostly useful in tests. + function unloadLang(key) { + delete languages[key]; } - } - }; - /** - * Find a stable position for all nodes - * @private - */ - Network.prototype._stabilize = function() { - if (this.constants.freezeForStabilization == true) { - this._freezeDefinedNodes(); - } + // Determines which language definition to use and returns it. + // + // With no parameters, it will return the global language. If you + // pass in a language key, such as 'en', it will return the + // definition for 'en', so long as 'en' has already been loaded using + // moment.lang. + function getLangDefinition(key) { + var i = 0, j, lang, next, split, + get = function (k) { + if (!languages[k] && hasModule) { + try { + __webpack_require__(57)("./" + k); + } catch (e) { } + } + return languages[k]; + }; - // find stable position - var count = 0; - while (this.moving && count < this.constants.stabilizationIterations) { - this._physicsTick(); - count++; - } - this.zoomExtent(false,true); - if (this.constants.freezeForStabilization == true) { - this._restoreFrozenNodes(); - } - this.emit("stabilized",{iterations:count}); - }; + if (!key) { + return moment.fn._lang; + } - /** - * 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 - */ - Network.prototype._freezeDefinedNodes = function() { - var nodes = this.nodes; - for (var id in nodes) { - if (nodes.hasOwnProperty(id)) { - if (nodes[id].x != null && nodes[id].y != null) { - nodes[id].fixedData.x = nodes[id].xFixed; - nodes[id].fixedData.y = nodes[id].yFixed; - nodes[id].xFixed = true; - nodes[id].yFixed = true; - } - } - } - }; + if (!isArray(key)) { + //short-circuit everything else + lang = get(key); + if (lang) { + return lang; + } + key = [key]; + } - /** - * Unfreezes the nodes that have been frozen by _freezeDefinedNodes. - * - * @private - */ - Network.prototype._restoreFrozenNodes = function() { - var nodes = this.nodes; - for (var id in nodes) { - if (nodes.hasOwnProperty(id)) { - if (nodes[id].fixedData.x != null) { - nodes[id].xFixed = nodes[id].fixedData.x; - nodes[id].yFixed = nodes[id].fixedData.y; - } + //pick the language from the array + //try ['en-au', 'en-gb'] as 'en-au', 'en-gb', 'en', as in move through the list trying each + //substring from most specific to least, but move to the next array item if it's a more specific variant than the current root + while (i < key.length) { + split = normalizeLanguage(key[i]).split('-'); + j = split.length; + next = normalizeLanguage(key[i + 1]); + next = next ? next.split('-') : null; + while (j > 0) { + lang = get(split.slice(0, j).join('-')); + if (lang) { + return lang; + } + if (next && next.length >= j && compareArrays(split, next, true) >= j - 1) { + //the next array item is better than a shallower substring of this one + break; + } + j--; + } + i++; + } + return moment.fn._lang; } - } - }; + /************************************ + Formatting + ************************************/ - /** - * Check if any of the nodes is still moving - * @param {number} vmin the minimum velocity considered as 'moving' - * @return {boolean} true if moving, false if non of the nodes is moving - * @private - */ - Network.prototype._isMoving = function(vmin) { - var nodes = this.nodes; - for (var id in nodes) { - if (nodes.hasOwnProperty(id) && nodes[id].isMoving(vmin)) { - return true; + + function removeFormattingTokens(input) { + if (input.match(/\[[\s\S]/)) { + return input.replace(/^\[|\]$/g, ""); + } + return input.replace(/\\/g, ""); } - } - return false; - }; + function makeFormatFunction(format) { + var array = format.match(formattingTokens), i, length; - /** - * /** - * Perform one discrete step for all nodes - * - * @private - */ - Network.prototype._discreteStepNodes = function() { - var interval = this.physicsDiscreteStepsize; - var nodes = this.nodes; - var nodeId; - var nodesPresent = false; + for (i = 0, length = array.length; i < length; i++) { + if (formatTokenFunctions[array[i]]) { + array[i] = formatTokenFunctions[array[i]]; + } else { + array[i] = removeFormattingTokens(array[i]); + } + } - if (this.constants.maxVelocity > 0) { - for (nodeId in nodes) { - if (nodes.hasOwnProperty(nodeId)) { - nodes[nodeId].discreteStepLimited(interval, this.constants.maxVelocity); - nodesPresent = true; - } - } - } - else { - for (nodeId in nodes) { - if (nodes.hasOwnProperty(nodeId)) { - nodes[nodeId].discreteStep(interval); - nodesPresent = true; - } + return function (mom) { + var output = ""; + for (i = 0; i < length; i++) { + output += array[i] instanceof Function ? array[i].call(mom, format) : array[i]; + } + return output; + }; } - } - if (nodesPresent == true) { - var vminCorrected = this.constants.minVelocity / Math.max(this.scale,0.05); - if (vminCorrected > 0.5*this.constants.maxVelocity) { - this.moving = true; - } - else { - this.moving = this._isMoving(vminCorrected); - if (this.moving == false) { - this.emit("stabilized",{iterations:null}); - } - this.moving = this.moving || this.configurePhysics; + // format date using native date object + function formatMoment(m, format) { - } - } - }; + if (!m.isValid()) { + return m.lang().invalidDate(); + } - /** - * A single simulation step (or "tick") in the physics simulation - * - * @private - */ - Network.prototype._physicsTick = function() { - if (!this.freezeSimulation) { - if (this.moving == true) { - this._doInAllActiveSectors("_initializeForceCalculation"); - this._doInAllActiveSectors("_discreteStepNodes"); - if (this.constants.smoothCurves.enabled == true && this.constants.smoothCurves.dynamic == true) { - this._doInSupportSector("_discreteStepNodes"); - } - this._findCenter(this._getRange()) + format = expandFormat(format, m.lang()); + + if (!formatFunctions[format]) { + formatFunctions[format] = makeFormatFunction(format); + } + + return formatFunctions[format](m); } - } - }; + function expandFormat(format, lang) { + var i = 5; - /** - * This function runs one step of the animation. It calls an x amount of physics ticks and one render tick. - * It reschedules itself at the beginning of the function - * - * @private - */ - Network.prototype._animationStep = function() { - // reset the timer so a new scheduled animation step can be set - this.timer = undefined; - // handle the keyboad movement - this._handleNavigation(); + function replaceLongDateFormatTokens(input) { + return lang.longDateFormat(input) || input; + } - // this schedules a new animation step - this.start(); + localFormattingTokens.lastIndex = 0; + while (i >= 0 && localFormattingTokens.test(format)) { + format = format.replace(localFormattingTokens, replaceLongDateFormatTokens); + localFormattingTokens.lastIndex = 0; + i -= 1; + } - // start the physics simulation - var calculationTime = Date.now(); - var maxSteps = 1; - this._physicsTick(); - var timeRequired = Date.now() - calculationTime; - while (timeRequired < 0.9*(this.renderTimestep - this.renderTime) && maxSteps < this.maxPhysicsTicksPerRender) { - this._physicsTick(); - timeRequired = Date.now() - calculationTime; - maxSteps++; - } - // start the rendering process - var renderTime = Date.now(); - this._redraw(); - this.renderTime = Date.now() - renderTime; + return format; + } - }; - if (typeof window !== 'undefined') { - window.requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || - window.webkitRequestAnimationFrame || window.msRequestAnimationFrame; - } + /************************************ + Parsing + ************************************/ - /** - * Schedule a animation step with the refreshrate interval. - */ - Network.prototype.start = function() { - if (this.moving == true || this.xIncrement != 0 || this.yIncrement != 0 || this.zoomIncrement != 0) { - if (!this.timer) { - var ua = navigator.userAgent.toLowerCase(); - var requiresTimeout = false; - if (ua.indexOf('msie 9.0') != -1) { // IE 9 - requiresTimeout = true; - } - else if (ua.indexOf('safari') != -1) { // safari - if (ua.indexOf('chrome') <= -1) { - requiresTimeout = true; + // get the regex to find the next token + function getParseRegexForToken(token, config) { + var a, strict = config._strict; + switch (token) { + case 'Q': + return parseTokenOneDigit; + case 'DDDD': + return parseTokenThreeDigits; + case 'YYYY': + case 'GGGG': + case 'gggg': + return strict ? parseTokenFourDigits : parseTokenOneToFourDigits; + case 'Y': + case 'G': + case 'g': + return parseTokenSignedNumber; + case 'YYYYYY': + case 'YYYYY': + case 'GGGGG': + case 'ggggg': + return strict ? parseTokenSixDigits : parseTokenOneToSixDigits; + case 'S': + if (strict) { return parseTokenOneDigit; } + /* falls through */ + case 'SS': + if (strict) { return parseTokenTwoDigits; } + /* falls through */ + case 'SSS': + if (strict) { return parseTokenThreeDigits; } + /* falls through */ + case 'DDD': + return parseTokenOneToThreeDigits; + case 'MMM': + case 'MMMM': + case 'dd': + case 'ddd': + case 'dddd': + return parseTokenWord; + case 'a': + case 'A': + return getLangDefinition(config._l)._meridiemParse; + case 'X': + return parseTokenTimestampMs; + case 'Z': + case 'ZZ': + return parseTokenTimezone; + case 'T': + return parseTokenT; + case 'SSSS': + return parseTokenDigits; + case 'MM': + case 'DD': + case 'YY': + case 'GG': + case 'gg': + case 'HH': + case 'hh': + case 'mm': + case 'ss': + case 'ww': + case 'WW': + return strict ? parseTokenTwoDigits : parseTokenOneOrTwoDigits; + case 'M': + case 'D': + case 'd': + case 'H': + case 'h': + case 'm': + case 's': + case 'w': + case 'W': + case 'e': + case 'E': + return parseTokenOneOrTwoDigits; + case 'Do': + return parseTokenOrdinal; + default : + a = new RegExp(regexpEscape(unescapeFormat(token.replace('\\', '')), "i")); + return a; } - } - - if (requiresTimeout == true) { - this.timer = window.setTimeout(this._animationStep.bind(this), this.renderTimestep); // wait this.renderTimeStep milliseconds and perform the animation step function - } - else{ - this.timer = window.requestAnimationFrame(this._animationStep.bind(this), this.renderTimestep); // wait this.renderTimeStep milliseconds and perform the animation step function - } } - } - else { - this._redraw(); - } - }; - - - /** - * Move the network according to the keyboard presses. - * - * @private - */ - Network.prototype._handleNavigation = function() { - if (this.xIncrement != 0 || this.yIncrement != 0) { - var translation = this._getTranslation(); - this._setTranslation(translation.x+this.xIncrement, translation.y+this.yIncrement); - } - if (this.zoomIncrement != 0) { - var center = { - x: this.frame.canvas.clientWidth / 2, - y: this.frame.canvas.clientHeight / 2 - }; - this._zoom(this.scale*(1 + this.zoomIncrement), center); - } - }; - - - /** - * Freeze the _animationStep - */ - Network.prototype.toggleFreeze = function() { - if (this.freezeSimulation == false) { - this.freezeSimulation = true; - } - else { - this.freezeSimulation = false; - this.start(); - } - }; + function timezoneMinutesFromString(string) { + string = string || ""; + var possibleTzMatches = (string.match(parseTokenTimezone) || []), + tzChunk = possibleTzMatches[possibleTzMatches.length - 1] || [], + parts = (tzChunk + '').match(parseTimezoneChunker) || ['-', 0, 0], + minutes = +(parts[1] * 60) + toInt(parts[2]); - /** - * This function cleans the support nodes if they are not needed and adds them when they are. - * - * @param {boolean} [disableStart] - * @private - */ - Network.prototype._configureSmoothCurves = function(disableStart) { - if (disableStart === undefined) { - disableStart = true; - } - if (this.constants.smoothCurves.enabled == true && this.constants.smoothCurves.dynamic == true) { - this._createBezierNodes(); - // cleanup unused support nodes - for (var nodeId in this.sectors['support']['nodes']) { - if (this.sectors['support']['nodes'].hasOwnProperty(nodeId)) { - if (this.edges[this.sectors['support']['nodes'][nodeId].parentEdgeId] === undefined) { - delete this.sectors['support']['nodes'][nodeId]; - } - } - } - } - else { - // delete the support nodes - this.sectors['support']['nodes'] = {}; - for (var edgeId in this.edges) { - if (this.edges.hasOwnProperty(edgeId)) { - this.edges[edgeId].via = null; - } + return parts[0] === '+' ? -minutes : minutes; } - } + // function to convert string input to date + function addTimeToArrayFromToken(token, input, config) { + var a, datePartArray = config._a; - this._updateCalculationNodes(); - if (!disableStart) { - this.moving = true; - this.start(); - } - }; - + switch (token) { + // QUARTER + case 'Q': + if (input != null) { + datePartArray[MONTH] = (toInt(input) - 1) * 3; + } + break; + // MONTH + case 'M' : // fall through to MM + case 'MM' : + if (input != null) { + datePartArray[MONTH] = toInt(input) - 1; + } + break; + case 'MMM' : // fall through to MMMM + case 'MMMM' : + a = getLangDefinition(config._l).monthsParse(input); + // if we didn't find a month name, mark the date as invalid. + if (a != null) { + datePartArray[MONTH] = a; + } else { + config._pf.invalidMonth = input; + } + break; + // DAY OF MONTH + case 'D' : // fall through to DD + case 'DD' : + if (input != null) { + datePartArray[DATE] = toInt(input); + } + break; + case 'Do' : + if (input != null) { + datePartArray[DATE] = toInt(parseInt(input, 10)); + } + break; + // DAY OF YEAR + case 'DDD' : // fall through to DDDD + case 'DDDD' : + if (input != null) { + config._dayOfYear = toInt(input); + } - /** - * Bezier curves require an anchor point to calculate the smooth flow. These points are nodes. These nodes are invisible but - * are used for the force calculation. - * - * @private - */ - Network.prototype._createBezierNodes = function() { - if (this.constants.smoothCurves.enabled == true && this.constants.smoothCurves.dynamic == true) { - for (var edgeId in this.edges) { - if (this.edges.hasOwnProperty(edgeId)) { - var edge = this.edges[edgeId]; - if (edge.via == null) { - var nodeId = "edgeId:".concat(edge.id); - this.sectors['support']['nodes'][nodeId] = new Node( - {id:nodeId, - mass:1, - shape:'circle', - image:"", - internalMultiplier:1 - },{},{},this.constants); - edge.via = this.sectors['support']['nodes'][nodeId]; - edge.via.parentEdgeId = edge.id; - edge.positionBezierNode(); + break; + // YEAR + case 'YY' : + datePartArray[YEAR] = moment.parseTwoDigitYear(input); + break; + case 'YYYY' : + case 'YYYYY' : + case 'YYYYYY' : + datePartArray[YEAR] = toInt(input); + break; + // AM / PM + case 'a' : // fall through to A + case 'A' : + config._isPm = getLangDefinition(config._l).isPM(input); + break; + // 24 HOUR + case 'H' : // fall through to hh + case 'HH' : // fall through to hh + case 'h' : // fall through to hh + case 'hh' : + datePartArray[HOUR] = toInt(input); + break; + // MINUTE + case 'm' : // fall through to mm + case 'mm' : + datePartArray[MINUTE] = toInt(input); + break; + // SECOND + case 's' : // fall through to ss + case 'ss' : + datePartArray[SECOND] = toInt(input); + break; + // MILLISECOND + case 'S' : + case 'SS' : + case 'SSS' : + case 'SSSS' : + datePartArray[MILLISECOND] = toInt(('0.' + input) * 1000); + break; + // UNIX TIMESTAMP WITH MS + case 'X': + config._d = new Date(parseFloat(input) * 1000); + break; + // TIMEZONE + case 'Z' : // fall through to ZZ + case 'ZZ' : + config._useUTC = true; + config._tzm = timezoneMinutesFromString(input); + break; + // WEEKDAY - human + case 'dd': + case 'ddd': + case 'dddd': + a = getLangDefinition(config._l).weekdaysParse(input); + // if we didn't get a weekday name, mark the date as invalid + if (a != null) { + config._w = config._w || {}; + config._w['d'] = a; + } else { + config._pf.invalidWeekday = input; + } + break; + // WEEK, WEEK DAY - numeric + case 'w': + case 'ww': + case 'W': + case 'WW': + case 'd': + case 'e': + case 'E': + token = token.substr(0, 1); + /* falls through */ + case 'gggg': + case 'GGGG': + case 'GGGGG': + token = token.substr(0, 2); + if (input) { + config._w = config._w || {}; + config._w[token] = toInt(input); + } + break; + case 'gg': + case 'GG': + config._w = config._w || {}; + config._w[token] = moment.parseTwoDigitYear(input); } - } - } - } - }; - - /** - * load the functions that load the mixins into the prototype. - * - * @private - */ - Network.prototype._initializeMixinLoaders = function () { - for (var mixin in MixinLoader) { - if (MixinLoader.hasOwnProperty(mixin)) { - Network.prototype[mixin] = MixinLoader[mixin]; } - } - }; - /** - * Load the XY positions of the nodes into the dataset. - */ - Network.prototype.storePosition = function() { - var dataArray = []; - for (var nodeId in this.nodes) { - if (this.nodes.hasOwnProperty(nodeId)) { - var node = this.nodes[nodeId]; - var allowedToMoveX = !this.nodes.xFixed; - var allowedToMoveY = !this.nodes.yFixed; - if (this.nodesData._data[nodeId].x != Math.round(node.x) || this.nodesData._data[nodeId].y != Math.round(node.y)) { - dataArray.push({id:nodeId,x:Math.round(node.x),y:Math.round(node.y),allowedToMoveX:allowedToMoveX,allowedToMoveY:allowedToMoveY}); - } - } - } - this.nodesData.update(dataArray); - }; + function dayOfYearFromWeekInfo(config) { + var w, weekYear, week, weekday, dow, doy, temp, lang; + w = config._w; + if (w.GG != null || w.W != null || w.E != null) { + dow = 1; + doy = 4; - /** - * Center a node in view. - * - * @param {Number} nodeId - * @param {Number} [zoomLevel] - */ - Network.prototype.focusOnNode = function (nodeId, zoomLevel) { - if (this.nodes.hasOwnProperty(nodeId)) { - if (zoomLevel === undefined) { - zoomLevel = this._getScale(); - } - var nodePosition= {x: this.nodes[nodeId].x, y: this.nodes[nodeId].y}; + // TODO: We need to take the current isoWeekYear, but that depends on + // how we interpret now (local, utc, fixed offset). So create + // a now version of current config (take local/utc/offset flags, and + // create now). + weekYear = dfl(w.GG, config._a[YEAR], weekOfYear(moment(), 1, 4).year); + week = dfl(w.W, 1); + weekday = dfl(w.E, 1); + } else { + lang = getLangDefinition(config._l); + dow = lang._week.dow; + doy = lang._week.doy; - var requiredScale = zoomLevel; - this._setScale(requiredScale); + weekYear = dfl(w.gg, config._a[YEAR], weekOfYear(moment(), dow, doy).year); + week = dfl(w.w, 1); - var canvasCenter = this.DOMtoCanvas({x:0.5 * this.frame.canvas.width,y:0.5 * this.frame.canvas.height}); - var translation = this._getTranslation(); + if (w.d != null) { + // weekday -- low day numbers are considered next week + weekday = w.d; + if (weekday < dow) { + ++week; + } + } else if (w.e != null) { + // local weekday -- counting starts from begining of week + weekday = w.e + dow; + } else { + // default to begining of week + weekday = dow; + } + } + temp = dayOfYearFromWeeks(weekYear, week, weekday, doy, dow); - var distanceFromCenter = {x:canvasCenter.x - nodePosition.x, - y:canvasCenter.y - nodePosition.y}; + config._a[YEAR] = temp.year; + config._dayOfYear = temp.dayOfYear; + } - this._setTranslation(translation.x + requiredScale * distanceFromCenter.x, - translation.y + requiredScale * distanceFromCenter.y); - this.redraw(); - } - else { - console.log("This nodeId cannot be found.") - } - }; + // convert an array to a date. + // the array should mirror the parameters below + // note: all values past the year are optional and will default to the lowest possible value. + // [year, month, day , hour, minute, second, millisecond] + function dateFromConfig(config) { + var i, date, input = [], currentDate, yearToUse; - module.exports = Network; + if (config._d) { + return; + } + currentDate = currentDateArray(config); -/***/ }, -/* 42 */ -/***/ function(module, exports, __webpack_require__) { + //compute day of the year from weeks and weekdays + if (config._w && config._a[DATE] == null && config._a[MONTH] == null) { + dayOfYearFromWeekInfo(config); + } - /** - * Copyright 2012 Craig Campbell - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Mousetrap is a simple keyboard shortcut library for Javascript with - * no external dependencies - * - * @version 1.1.2 - * @url craig.is/killing/mice - */ + //if the day of the year is set, figure out what it is + if (config._dayOfYear) { + yearToUse = dfl(config._a[YEAR], currentDate[YEAR]); - /** - * mapping of special keycodes to their corresponding keys - * - * everything in this dictionary cannot use keypress events - * so it has to be here to map to the correct keycodes for - * keyup/keydown events - * - * @type {Object} - */ - var _MAP = { - 8: 'backspace', - 9: 'tab', - 13: 'enter', - 16: 'shift', - 17: 'ctrl', - 18: 'alt', - 20: 'capslock', - 27: 'esc', - 32: 'space', - 33: 'pageup', - 34: 'pagedown', - 35: 'end', - 36: 'home', - 37: 'left', - 38: 'up', - 39: 'right', - 40: 'down', - 45: 'ins', - 46: 'del', - 91: 'meta', - 93: 'meta', - 224: 'meta' - }, + if (config._dayOfYear > daysInYear(yearToUse)) { + config._pf._overflowDayOfYear = true; + } - /** - * mapping for special characters so they can support - * - * this dictionary is only used incase you want to bind a - * keyup or keydown event to one of these keys - * - * @type {Object} - */ - _KEYCODE_MAP = { - 106: '*', - 107: '+', - 109: '-', - 110: '.', - 111 : '/', - 186: ';', - 187: '=', - 188: ',', - 189: '-', - 190: '.', - 191: '/', - 192: '`', - 219: '[', - 220: '\\', - 221: ']', - 222: '\'' - }, + date = makeUTCDate(yearToUse, 0, config._dayOfYear); + config._a[MONTH] = date.getUTCMonth(); + config._a[DATE] = date.getUTCDate(); + } - /** - * this is a mapping of keys that require shift on a US keypad - * back to the non shift equivelents - * - * this is so you can use keyup events with these keys - * - * note that this will only work reliably on US keyboards - * - * @type {Object} - */ - _SHIFT_MAP = { - '~': '`', - '!': '1', - '@': '2', - '#': '3', - '$': '4', - '%': '5', - '^': '6', - '&': '7', - '*': '8', - '(': '9', - ')': '0', - '_': '-', - '+': '=', - ':': ';', - '\"': '\'', - '<': ',', - '>': '.', - '?': '/', - '|': '\\' - }, + // Default to current date. + // * if no year, month, day of month are given, default to today + // * if day of month is given, default month and year + // * if month is given, default only year + // * if year is given, don't default anything + for (i = 0; i < 3 && config._a[i] == null; ++i) { + config._a[i] = input[i] = currentDate[i]; + } - /** - * this is a list of special strings you can use to map - * to modifier keys when you specify your keyboard shortcuts - * - * @type {Object} - */ - _SPECIAL_ALIASES = { - 'option': 'alt', - 'command': 'meta', - 'return': 'enter', - 'escape': 'esc' - }, + // Zero out whatever was not defaulted, including time + for (; i < 7; i++) { + config._a[i] = input[i] = (config._a[i] == null) ? (i === 2 ? 1 : 0) : config._a[i]; + } - /** - * variable to store the flipped version of _MAP from above - * needed to check if we should use keypress or not when no action - * is specified - * - * @type {Object|undefined} - */ - _REVERSE_MAP, + config._d = (config._useUTC ? makeUTCDate : makeDate).apply(null, input); + // Apply timezone offset from input. The actual zone can be changed + // with parseZone. + if (config._tzm != null) { + config._d.setUTCMinutes(config._d.getUTCMinutes() + config._tzm); + } + } - /** - * a list of all the callbacks setup via Mousetrap.bind() - * - * @type {Object} - */ - _callbacks = {}, + function dateFromObject(config) { + var normalizedInput; - /** - * direct map of string combinations to callbacks used for trigger() - * - * @type {Object} - */ - _direct_map = {}, + if (config._d) { + return; + } - /** - * keeps track of what level each sequence is at since multiple - * sequences can start out with the same sequence - * - * @type {Object} - */ - _sequence_levels = {}, + normalizedInput = normalizeObjectUnits(config._i); + config._a = [ + normalizedInput.year, + normalizedInput.month, + normalizedInput.day, + normalizedInput.hour, + normalizedInput.minute, + normalizedInput.second, + normalizedInput.millisecond + ]; - /** - * variable to store the setTimeout call - * - * @type {null|number} - */ - _reset_timer, + dateFromConfig(config); + } - /** - * temporary state where we will ignore the next keyup - * - * @type {boolean|string} - */ - _ignore_next_keyup = false, + function currentDateArray(config) { + var now = new Date(); + if (config._useUTC) { + return [ + now.getUTCFullYear(), + now.getUTCMonth(), + now.getUTCDate() + ]; + } else { + return [now.getFullYear(), now.getMonth(), now.getDate()]; + } + } - /** - * are we currently inside of a sequence? - * type of action ("keyup" or "keydown" or "keypress") or false - * - * @type {boolean|string} - */ - _inside_sequence = false; + // date from string and format string + function makeDateFromStringAndFormat(config) { - /** - * loop through the f keys, f1 to f19 and add them to the map - * programatically - */ - for (var i = 1; i < 20; ++i) { - _MAP[111 + i] = 'f' + i; - } + if (config._f === moment.ISO_8601) { + parseISO(config); + return; + } - /** - * loop through to map numbers on the numeric keypad - */ - for (i = 0; i <= 9; ++i) { - _MAP[i + 96] = i; - } + config._a = []; + config._pf.empty = true; - /** - * cross browser add event method - * - * @param {Element|HTMLDocument} object - * @param {string} type - * @param {Function} callback - * @returns void - */ - function _addEvent(object, type, callback) { - if (object.addEventListener) { - return object.addEventListener(type, callback, false); - } + // This array is used to make a Date, either with `new Date` or `Date.UTC` + var lang = getLangDefinition(config._l), + string = '' + config._i, + i, parsedInput, tokens, token, skipped, + stringLength = string.length, + totalParsedInputLength = 0; - object.attachEvent('on' + type, callback); - } + tokens = expandFormat(config._f, lang).match(formattingTokens) || []; - /** - * takes the event and returns the key character - * - * @param {Event} e - * @return {string} - */ - function _characterFromEvent(e) { + for (i = 0; i < tokens.length; i++) { + token = tokens[i]; + parsedInput = (string.match(getParseRegexForToken(token, config)) || [])[0]; + if (parsedInput) { + skipped = string.substr(0, string.indexOf(parsedInput)); + if (skipped.length > 0) { + config._pf.unusedInput.push(skipped); + } + string = string.slice(string.indexOf(parsedInput) + parsedInput.length); + totalParsedInputLength += parsedInput.length; + } + // don't parse if it's not a known token + if (formatTokenFunctions[token]) { + if (parsedInput) { + config._pf.empty = false; + } + else { + config._pf.unusedTokens.push(token); + } + addTimeToArrayFromToken(token, parsedInput, config); + } + else if (config._strict && !parsedInput) { + config._pf.unusedTokens.push(token); + } + } - // for keypress events we should return the character as is - if (e.type == 'keypress') { - return String.fromCharCode(e.which); - } + // add remaining unparsed input length to the string + config._pf.charsLeftOver = stringLength - totalParsedInputLength; + if (string.length > 0) { + config._pf.unusedInput.push(string); + } - // for non keypress events the special maps are needed - if (_MAP[e.which]) { - return _MAP[e.which]; - } + // handle am pm + if (config._isPm && config._a[HOUR] < 12) { + config._a[HOUR] += 12; + } + // if is 12 am, change hours to 0 + if (config._isPm === false && config._a[HOUR] === 12) { + config._a[HOUR] = 0; + } - if (_KEYCODE_MAP[e.which]) { - return _KEYCODE_MAP[e.which]; - } + dateFromConfig(config); + checkOverflow(config); + } - // if it is not in the special map - return String.fromCharCode(e.which).toLowerCase(); - } + function unescapeFormat(s) { + return s.replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g, function (matched, p1, p2, p3, p4) { + return p1 || p2 || p3 || p4; + }); + } - /** - * should we stop this event before firing off callbacks - * - * @param {Event} e - * @return {boolean} - */ - function _stop(e) { - var element = e.target || e.srcElement, - tag_name = element.tagName; + // Code from http://stackoverflow.com/questions/3561493/is-there-a-regexp-escape-function-in-javascript + function regexpEscape(s) { + return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'); + } - // if the element has the class "mousetrap" then no need to stop - if ((' ' + element.className + ' ').indexOf(' mousetrap ') > -1) { - return false; - } + // date from string and array of format strings + function makeDateFromStringAndArray(config) { + var tempConfig, + bestMoment, - // stop for input, select, and textarea - return tag_name == 'INPUT' || tag_name == 'SELECT' || tag_name == 'TEXTAREA' || (element.contentEditable && element.contentEditable == 'true'); - } + scoreToBeat, + i, + currentScore; + + if (config._f.length === 0) { + config._pf.invalidFormat = true; + config._d = new Date(NaN); + return; + } + + for (i = 0; i < config._f.length; i++) { + currentScore = 0; + tempConfig = extend({}, config); + tempConfig._pf = defaultParsingFlags(); + tempConfig._f = config._f[i]; + makeDateFromStringAndFormat(tempConfig); + + if (!isValid(tempConfig)) { + continue; + } - /** - * checks if two arrays are equal - * - * @param {Array} modifiers1 - * @param {Array} modifiers2 - * @returns {boolean} - */ - function _modifiersMatch(modifiers1, modifiers2) { - return modifiers1.sort().join(',') === modifiers2.sort().join(','); - } + // if there is any input that was not parsed add a penalty for that format + currentScore += tempConfig._pf.charsLeftOver; - /** - * resets all sequence counters except for the ones passed in - * - * @param {Object} do_not_reset - * @returns void - */ - function _resetSequences(do_not_reset) { - do_not_reset = do_not_reset || {}; + //or tokens + currentScore += tempConfig._pf.unusedTokens.length * 10; - var active_sequences = false, - key; + tempConfig._pf.score = currentScore; - for (key in _sequence_levels) { - if (do_not_reset[key]) { - active_sequences = true; - continue; - } - _sequence_levels[key] = 0; - } + if (scoreToBeat == null || currentScore < scoreToBeat) { + scoreToBeat = currentScore; + bestMoment = tempConfig; + } + } - if (!active_sequences) { - _inside_sequence = false; - } - } + extend(config, bestMoment || tempConfig); + } - /** - * finds all callbacks that match based on the keycode, modifiers, - * and action - * - * @param {string} character - * @param {Array} modifiers - * @param {string} action - * @param {boolean=} remove - should we remove any matches - * @param {string=} combination - * @returns {Array} - */ - function _getMatches(character, modifiers, action, remove, combination) { - var i, - callback, - matches = []; + // date from iso format + function parseISO(config) { + var i, l, + string = config._i, + match = isoRegex.exec(string); - // if there are no events related to this keycode - if (!_callbacks[character]) { - return []; - } + if (match) { + config._pf.iso = true; + for (i = 0, l = isoDates.length; i < l; i++) { + if (isoDates[i][1].exec(string)) { + // match[5] should be "T" or undefined + config._f = isoDates[i][0] + (match[6] || " "); + break; + } + } + for (i = 0, l = isoTimes.length; i < l; i++) { + if (isoTimes[i][1].exec(string)) { + config._f += isoTimes[i][0]; + break; + } + } + if (string.match(parseTokenTimezone)) { + config._f += "Z"; + } + makeDateFromStringAndFormat(config); + } else { + config._isValid = false; + } + } - // if a modifier key is coming up on its own we should allow it - if (action == 'keyup' && _isModifier(character)) { - modifiers = [character]; - } + // date from iso format or fallback + function makeDateFromString(config) { + parseISO(config); + if (config._isValid === false) { + delete config._isValid; + moment.createFromInputFallback(config); + } + } - // loop through all callbacks for the key that was pressed - // and see if any of them match - for (i = 0; i < _callbacks[character].length; ++i) { - callback = _callbacks[character][i]; + function makeDateFromInput(config) { + var input = config._i, + matched = aspNetJsonRegex.exec(input); - // if this is a sequence but it is not at the right level - // then move onto the next match - if (callback.seq && _sequence_levels[callback.seq] != callback.level) { - continue; - } + if (input === undefined) { + config._d = new Date(); + } else if (matched) { + config._d = new Date(+matched[1]); + } else if (typeof input === 'string') { + makeDateFromString(config); + } else if (isArray(input)) { + config._a = input.slice(0); + dateFromConfig(config); + } else if (isDate(input)) { + config._d = new Date(+input); + } else if (typeof(input) === 'object') { + dateFromObject(config); + } else if (typeof(input) === 'number') { + // from milliseconds + config._d = new Date(input); + } else { + moment.createFromInputFallback(config); + } + } - // if the action we are looking for doesn't match the action we got - // then we should keep going - if (action != callback.action) { - continue; - } + function makeDate(y, m, d, h, M, s, ms) { + //can't just apply() to create a date: + //http://stackoverflow.com/questions/181348/instantiating-a-javascript-object-by-calling-prototype-constructor-apply + var date = new Date(y, m, d, h, M, s, ms); - // if this is a keypress event that means that we need to only - // look at the character, otherwise check the modifiers as - // well - if (action == 'keypress' || _modifiersMatch(modifiers, callback.modifiers)) { + //the date constructor doesn't accept years < 1970 + if (y < 1970) { + date.setFullYear(y); + } + return date; + } - // remove is used so if you change your mind and call bind a - // second time with a new function the first one is overwritten - if (remove && callback.combo == combination) { - _callbacks[character].splice(i, 1); - } + function makeUTCDate(y) { + var date = new Date(Date.UTC.apply(null, arguments)); + if (y < 1970) { + date.setUTCFullYear(y); + } + return date; + } - matches.push(callback); - } - } + function parseWeekday(input, language) { + if (typeof input === 'string') { + if (!isNaN(input)) { + input = parseInt(input, 10); + } + else { + input = language.weekdaysParse(input); + if (typeof input !== 'number') { + return null; + } + } + } + return input; + } - return matches; - } + /************************************ + Relative Time + ************************************/ - /** - * takes a key event and figures out what the modifiers are - * - * @param {Event} e - * @returns {Array} - */ - function _eventModifiers(e) { - var modifiers = []; - if (e.shiftKey) { - modifiers.push('shift'); - } + // helper function for moment.fn.from, moment.fn.fromNow, and moment.duration.fn.humanize + function substituteTimeAgo(string, number, withoutSuffix, isFuture, lang) { + return lang.relativeTime(number || 1, !!withoutSuffix, string, isFuture); + } - if (e.altKey) { - modifiers.push('alt'); - } + function relativeTime(milliseconds, withoutSuffix, lang) { + var seconds = round(Math.abs(milliseconds) / 1000), + minutes = round(seconds / 60), + hours = round(minutes / 60), + days = round(hours / 24), + years = round(days / 365), + args = seconds < relativeTimeThresholds.s && ['s', seconds] || + minutes === 1 && ['m'] || + minutes < relativeTimeThresholds.m && ['mm', minutes] || + hours === 1 && ['h'] || + hours < relativeTimeThresholds.h && ['hh', hours] || + days === 1 && ['d'] || + days <= relativeTimeThresholds.dd && ['dd', days] || + days <= relativeTimeThresholds.dm && ['M'] || + days < relativeTimeThresholds.dy && ['MM', round(days / 30)] || + years === 1 && ['y'] || ['yy', years]; + args[2] = withoutSuffix; + args[3] = milliseconds > 0; + args[4] = lang; + return substituteTimeAgo.apply({}, args); + } - if (e.ctrlKey) { - modifiers.push('ctrl'); - } - if (e.metaKey) { - modifiers.push('meta'); - } + /************************************ + Week of Year + ************************************/ - return modifiers; - } - /** - * actually calls the callback function - * - * if your callback function returns false this will use the jquery - * convention - prevent default and stop propogation on the event - * - * @param {Function} callback - * @param {Event} e - * @returns void - */ - function _fireCallback(callback, e) { - if (callback(e) === false) { - if (e.preventDefault) { - e.preventDefault(); - } + // firstDayOfWeek 0 = sun, 6 = sat + // the day of the week that starts the week + // (usually sunday or monday) + // firstDayOfWeekOfYear 0 = sun, 6 = sat + // the first week is the week that contains the first + // of this day of the week + // (eg. ISO weeks use thursday (4)) + function weekOfYear(mom, firstDayOfWeek, firstDayOfWeekOfYear) { + var end = firstDayOfWeekOfYear - firstDayOfWeek, + daysToDayOfWeek = firstDayOfWeekOfYear - mom.day(), + adjustedMoment; - if (e.stopPropagation) { - e.stopPropagation(); - } - e.returnValue = false; - e.cancelBubble = true; - } - } + if (daysToDayOfWeek > end) { + daysToDayOfWeek -= 7; + } - /** - * handles a character key event - * - * @param {string} character - * @param {Event} e - * @returns void - */ - function _handleCharacter(character, e) { + if (daysToDayOfWeek < end - 7) { + daysToDayOfWeek += 7; + } - // if this event should not happen stop here - if (_stop(e)) { - return; - } + adjustedMoment = moment(mom).add('d', daysToDayOfWeek); + return { + week: Math.ceil(adjustedMoment.dayOfYear() / 7), + year: adjustedMoment.year() + }; + } - var callbacks = _getMatches(character, _eventModifiers(e), e.type), - i, - do_not_reset = {}, - processed_sequence_callback = false; + //http://en.wikipedia.org/wiki/ISO_week_date#Calculating_a_date_given_the_year.2C_week_number_and_weekday + function dayOfYearFromWeeks(year, week, weekday, firstDayOfWeekOfYear, firstDayOfWeek) { + var d = makeUTCDate(year, 0, 1).getUTCDay(), daysToAdd, dayOfYear; - // loop through matching callbacks for this key event - for (i = 0; i < callbacks.length; ++i) { + d = d === 0 ? 7 : d; + weekday = weekday != null ? weekday : firstDayOfWeek; + daysToAdd = firstDayOfWeek - d + (d > firstDayOfWeekOfYear ? 7 : 0) - (d < firstDayOfWeek ? 7 : 0); + dayOfYear = 7 * (week - 1) + (weekday - firstDayOfWeek) + daysToAdd + 1; - // fire for all sequence callbacks - // this is because if for example you have multiple sequences - // bound such as "g i" and "g t" they both need to fire the - // callback for matching g cause otherwise you can only ever - // match the first one - if (callbacks[i].seq) { - processed_sequence_callback = true; + return { + year: dayOfYear > 0 ? year : year - 1, + dayOfYear: dayOfYear > 0 ? dayOfYear : daysInYear(year - 1) + dayOfYear + }; + } - // keep a list of which sequences were matches for later - do_not_reset[callbacks[i].seq] = 1; - _fireCallback(callbacks[i].callback, e); - continue; - } + /************************************ + Top Level Functions + ************************************/ - // if there were no sequence matches but we are still here - // that means this is a regular match so we should fire that - if (!processed_sequence_callback && !_inside_sequence) { - _fireCallback(callbacks[i].callback, e); - } - } + function makeMoment(config) { + var input = config._i, + format = config._f; - // if you are inside of a sequence and the key you are pressing - // is not a modifier key then we should reset all sequences - // that were not matched by this key event - if (e.type == _inside_sequence && !_isModifier(character)) { - _resetSequences(do_not_reset); - } - } + if (input === null || (format === undefined && input === '')) { + return moment.invalid({nullInput: true}); + } - /** - * handles a keydown event - * - * @param {Event} e - * @returns void - */ - function _handleKey(e) { + if (typeof input === 'string') { + config._i = input = getLangDefinition().preparse(input); + } - // normalize e.which for key events - // @see http://stackoverflow.com/questions/4285627/javascript-keycode-vs-charcode-utter-confusion - e.which = typeof e.which == "number" ? e.which : e.keyCode; + if (moment.isMoment(input)) { + config = cloneMoment(input); - var character = _characterFromEvent(e); + config._d = new Date(+input._d); + } else if (format) { + if (isArray(format)) { + makeDateFromStringAndArray(config); + } else { + makeDateFromStringAndFormat(config); + } + } else { + makeDateFromInput(config); + } - // no character found then stop - if (!character) { - return; - } + return new Moment(config); + } - if (e.type == 'keyup' && _ignore_next_keyup == character) { - _ignore_next_keyup = false; - return; - } + moment = function (input, format, lang, strict) { + var c; - _handleCharacter(character, e); - } + if (typeof(lang) === "boolean") { + strict = lang; + lang = undefined; + } + // object construction must be done this way. + // https://github.com/moment/moment/issues/1423 + c = {}; + c._isAMomentObject = true; + c._i = input; + c._f = format; + c._l = lang; + c._strict = strict; + c._isUTC = false; + c._pf = defaultParsingFlags(); - /** - * determines if the keycode specified is a modifier key or not - * - * @param {string} key - * @returns {boolean} - */ - function _isModifier(key) { - return key == 'shift' || key == 'ctrl' || key == 'alt' || key == 'meta'; - } + return makeMoment(c); + }; - /** - * called to set a 1 second timeout on the specified sequence - * - * this is so after each key press in the sequence you have 1 second - * to press the next key before you have to start over - * - * @returns void - */ - function _resetSequenceTimer() { - clearTimeout(_reset_timer); - _reset_timer = setTimeout(_resetSequences, 1000); - } + moment.suppressDeprecationWarnings = false; - /** - * reverses the map lookup so that we can look for specific keys - * to see what can and can't use keypress - * - * @return {Object} - */ - function _getReverseMap() { - if (!_REVERSE_MAP) { - _REVERSE_MAP = {}; - for (var key in _MAP) { + moment.createFromInputFallback = deprecate( + "moment construction falls back to js Date. This is " + + "discouraged and will be removed in upcoming major " + + "release. Please refer to " + + "https://github.com/moment/moment/issues/1407 for more info.", + function (config) { + config._d = new Date(config._i); + }); - // pull out the numeric keypad from here cause keypress should - // be able to detect the keys from the character - if (key > 95 && key < 112) { - continue; - } + // Pick a moment m from moments so that m[fn](other) is true for all + // other. This relies on the function fn to be transitive. + // + // moments should either be an array of moment objects or an array, whose + // first element is an array of moment objects. + function pickBy(fn, moments) { + var res, i; + if (moments.length === 1 && isArray(moments[0])) { + moments = moments[0]; + } + if (!moments.length) { + return moment(); + } + res = moments[0]; + for (i = 1; i < moments.length; ++i) { + if (moments[i][fn](res)) { + res = moments[i]; + } + } + return res; + } - if (_MAP.hasOwnProperty(key)) { - _REVERSE_MAP[_MAP[key]] = key; - } - } - } - return _REVERSE_MAP; - } + moment.min = function () { + var args = [].slice.call(arguments, 0); - /** - * picks the best action based on the key combination - * - * @param {string} key - character for key - * @param {Array} modifiers - * @param {string=} action passed in - */ - function _pickBestAction(key, modifiers, action) { + return pickBy('isBefore', args); + }; - // if no action was picked in we should try to pick the one - // that we think would work best for this key - if (!action) { - action = _getReverseMap()[key] ? 'keydown' : 'keypress'; - } + moment.max = function () { + var args = [].slice.call(arguments, 0); - // modifier keys don't work as expected with keypress, - // switch to keydown - if (action == 'keypress' && modifiers.length) { - action = 'keydown'; - } + return pickBy('isAfter', args); + }; + + // creating with utc + moment.utc = function (input, format, lang, strict) { + var c; + + if (typeof(lang) === "boolean") { + strict = lang; + lang = undefined; + } + // object construction must be done this way. + // https://github.com/moment/moment/issues/1423 + c = {}; + c._isAMomentObject = true; + c._useUTC = true; + c._isUTC = true; + c._l = lang; + c._i = input; + c._f = format; + c._strict = strict; + c._pf = defaultParsingFlags(); - return action; - } + return makeMoment(c).utc(); + }; - /** - * binds a key sequence to an event - * - * @param {string} combo - combo specified in bind call - * @param {Array} keys - * @param {Function} callback - * @param {string=} action - * @returns void - */ - function _bindSequence(combo, keys, callback, action) { + // creating with unix timestamp (in seconds) + moment.unix = function (input) { + return moment(input * 1000); + }; - // start off by adding a sequence level record for this combination - // and setting the level to 0 - _sequence_levels[combo] = 0; + // duration + moment.duration = function (input, key) { + var duration = input, + // matching against regexp is expensive, do it on demand + match = null, + sign, + ret, + parseIso; - // if there is no action pick the best one for the first key - // in the sequence - if (!action) { - action = _pickBestAction(keys[0], []); - } + if (moment.isDuration(input)) { + duration = { + ms: input._milliseconds, + d: input._days, + M: input._months + }; + } else if (typeof input === 'number') { + duration = {}; + if (key) { + duration[key] = input; + } else { + duration.milliseconds = input; + } + } else if (!!(match = aspNetTimeSpanJsonRegex.exec(input))) { + sign = (match[1] === "-") ? -1 : 1; + duration = { + y: 0, + d: toInt(match[DATE]) * sign, + h: toInt(match[HOUR]) * sign, + m: toInt(match[MINUTE]) * sign, + s: toInt(match[SECOND]) * sign, + ms: toInt(match[MILLISECOND]) * sign + }; + } else if (!!(match = isoDurationRegex.exec(input))) { + sign = (match[1] === "-") ? -1 : 1; + parseIso = function (inp) { + // We'd normally use ~~inp for this, but unfortunately it also + // converts floats to ints. + // inp may be undefined, so careful calling replace on it. + var res = inp && parseFloat(inp.replace(',', '.')); + // apply sign while we're at it + return (isNaN(res) ? 0 : res) * sign; + }; + duration = { + y: parseIso(match[2]), + M: parseIso(match[3]), + d: parseIso(match[4]), + h: parseIso(match[5]), + m: parseIso(match[6]), + s: parseIso(match[7]), + w: parseIso(match[8]) + }; + } - /** - * callback to increase the sequence level for this sequence and reset - * all other sequences that were active - * - * @param {Event} e - * @returns void - */ - var _increaseSequence = function(e) { - _inside_sequence = action; - ++_sequence_levels[combo]; - _resetSequenceTimer(); - }, + ret = new Duration(duration); - /** - * wraps the specified callback inside of another function in order - * to reset all sequence counters as soon as this sequence is done - * - * @param {Event} e - * @returns void - */ - _callbackAndReset = function(e) { - _fireCallback(callback, e); + if (moment.isDuration(input) && input.hasOwnProperty('_lang')) { + ret._lang = input._lang; + } - // we should ignore the next key up if the action is key down - // or keypress. this is so if you finish a sequence and - // release the key the final key will not trigger a keyup - if (action !== 'keyup') { - _ignore_next_keyup = _characterFromEvent(e); - } + return ret; + }; - // weird race condition if a sequence ends with the key - // another sequence begins with - setTimeout(_resetSequences, 10); - }, - i; + // version number + moment.version = VERSION; - // loop through keys one at a time and bind the appropriate callback - // function. for any key leading up to the final one it should - // increase the sequence. after the final, it should reset all sequences - for (i = 0; i < keys.length; ++i) { - _bindSingle(keys[i], i < keys.length - 1 ? _increaseSequence : _callbackAndReset, action, combo, i); - } - } + // default format + moment.defaultFormat = isoFormat; - /** - * binds a single keyboard combination - * - * @param {string} combination - * @param {Function} callback - * @param {string=} action - * @param {string=} sequence_name - name of sequence if part of sequence - * @param {number=} level - what part of the sequence the command is - * @returns void - */ - function _bindSingle(combination, callback, action, sequence_name, level) { + // constant that refers to the ISO standard + moment.ISO_8601 = function () {}; - // make sure multiple spaces in a row become a single space - combination = combination.replace(/\s+/g, ' '); + // Plugins that add properties should also add the key here (null value), + // so we can properly clone ourselves. + moment.momentProperties = momentProperties; - var sequence = combination.split(' '), - i, - key, - keys, - modifiers = []; + // This function will be called whenever a moment is mutated. + // It is intended to keep the offset in sync with the timezone. + moment.updateOffset = function () {}; - // if this pattern is a sequence of keys then run through this method - // to reprocess each pattern one key at a time - if (sequence.length > 1) { - return _bindSequence(combination, sequence, callback, action); + // This function allows you to set a threshold for relative time strings + moment.relativeTimeThreshold = function(threshold, limit) { + if (relativeTimeThresholds[threshold] === undefined) { + return false; } + relativeTimeThresholds[threshold] = limit; + return true; + }; - // take the keys from this pattern and figure out what the actual - // pattern is all about - keys = combination === '+' ? ['+'] : combination.split('+'); + // This function will load languages and then set the global language. If + // no arguments are passed in, it will simply return the current global + // language key. + moment.lang = function (key, values) { + var r; + if (!key) { + return moment.fn._lang._abbr; + } + if (values) { + loadLang(normalizeLanguage(key), values); + } else if (values === null) { + unloadLang(key); + key = 'en'; + } else if (!languages[key]) { + getLangDefinition(key); + } + r = moment.duration.fn._lang = moment.fn._lang = getLangDefinition(key); + return r._abbr; + }; - for (i = 0; i < keys.length; ++i) { - key = keys[i]; + // returns language data + moment.langData = function (key) { + if (key && key._lang && key._lang._abbr) { + key = key._lang._abbr; + } + return getLangDefinition(key); + }; - // normalize key names - if (_SPECIAL_ALIASES[key]) { - key = _SPECIAL_ALIASES[key]; - } + // compare moment object + moment.isMoment = function (obj) { + return obj instanceof Moment || + (obj != null && obj.hasOwnProperty('_isAMomentObject')); + }; - // if this is not a keypress event then we should - // be smart about using shift keys - // this will only work for US keyboards however - if (action && action != 'keypress' && _SHIFT_MAP[key]) { - key = _SHIFT_MAP[key]; - modifiers.push('shift'); - } + // for typechecking Duration objects + moment.isDuration = function (obj) { + return obj instanceof Duration; + }; - // if this key is a modifier then add it to the list of modifiers - if (_isModifier(key)) { - modifiers.push(key); - } - } + for (i = lists.length - 1; i >= 0; --i) { + makeList(lists[i]); + } - // depending on what the key combination is - // we will try to pick the best event for it - action = _pickBestAction(key, modifiers, action); + moment.normalizeUnits = function (units) { + return normalizeUnits(units); + }; - // make sure to initialize array if this is the first time - // a callback is added for this key - if (!_callbacks[key]) { - _callbacks[key] = []; - } + moment.invalid = function (flags) { + var m = moment.utc(NaN); + if (flags != null) { + extend(m._pf, flags); + } + else { + m._pf.userInvalidated = true; + } - // remove an existing match if there is one - _getMatches(key, modifiers, action, !sequence_name, combination); + return m; + }; + + moment.parseZone = function () { + return moment.apply(null, arguments).parseZone(); + }; - // add this call back to the array - // if it is a sequence put it at the beginning - // if not put it at the end - // - // this is important because the way these are processed expects - // the sequence ones to come first - _callbacks[key][sequence_name ? 'unshift' : 'push']({ - callback: callback, - modifiers: modifiers, - action: action, - seq: sequence_name, - level: level, - combo: combination - }); - } + moment.parseTwoDigitYear = function (input) { + return toInt(input) + (toInt(input) > 68 ? 1900 : 2000); + }; - /** - * binds multiple combinations to the same callback - * - * @param {Array} combinations - * @param {Function} callback - * @param {string|undefined} action - * @returns void - */ - function _bindMultiple(combinations, callback, action) { - for (var i = 0; i < combinations.length; ++i) { - _bindSingle(combinations[i], callback, action); - } - } + /************************************ + Moment Prototype + ************************************/ - // start! - _addEvent(document, 'keypress', _handleKey); - _addEvent(document, 'keydown', _handleKey); - _addEvent(document, 'keyup', _handleKey); - var mousetrap = { + extend(moment.fn = Moment.prototype, { - /** - * binds an event to mousetrap - * - * can be a single key, a combination of keys separated with +, - * a comma separated list of keys, an array of keys, or - * a sequence of keys separated by spaces - * - * be sure to list the modifier keys first to make sure that the - * correct key ends up getting bound (the last key in the pattern) - * - * @param {string|Array} keys - * @param {Function} callback - * @param {string=} action - 'keypress', 'keydown', or 'keyup' - * @returns void - */ - bind: function(keys, callback, action) { - _bindMultiple(keys instanceof Array ? keys : [keys], callback, action); - _direct_map[keys + ':' + action] = callback; - return this; - }, + clone : function () { + return moment(this); + }, - /** - * unbinds an event to mousetrap - * - * the unbinding sets the callback function of the specified key combo - * to an empty function and deletes the corresponding key in the - * _direct_map dict. - * - * the keycombo+action has to be exactly the same as - * it was defined in the bind method - * - * TODO: actually remove this from the _callbacks dictionary instead - * of binding an empty function - * - * @param {string|Array} keys - * @param {string} action - * @returns void - */ - unbind: function(keys, action) { - if (_direct_map[keys + ':' + action]) { - delete _direct_map[keys + ':' + action]; - this.bind(keys, function() {}, action); - } - return this; - }, + valueOf : function () { + return +this._d + ((this._offset || 0) * 60000); + }, - /** - * triggers an event that has already been bound - * - * @param {string} keys - * @param {string=} action - * @returns void - */ - trigger: function(keys, action) { - _direct_map[keys + ':' + action](); - return this; - }, + unix : function () { + return Math.floor(+this / 1000); + }, - /** - * resets the library back to its initial state. this is useful - * if you want to clear out the current keyboard shortcuts and bind - * new ones - for example if you switch to another page - * - * @returns void - */ - reset: function() { - _callbacks = {}; - _direct_map = {}; - return this; - } - }; + toString : function () { + return this.clone().lang('en').format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ"); + }, - module.exports = mousetrap; + toDate : function () { + return this._offset ? new Date(+this) : this._d; + }, + toISOString : function () { + var m = moment(this).utc(); + if (0 < m.year() && m.year() <= 9999) { + return formatMoment(m, 'YYYY-MM-DD[T]HH:mm:ss.SSS[Z]'); + } else { + return formatMoment(m, 'YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]'); + } + }, + toArray : function () { + var m = this; + return [ + m.year(), + m.month(), + m.date(), + m.hours(), + m.minutes(), + m.seconds(), + m.milliseconds() + ]; + }, -/***/ }, -/* 43 */ -/***/ function(module, exports, __webpack_require__) { + isValid : function () { + return isValid(this); + }, - /** - * Parse a text source containing data in DOT language into a JSON object. - * The object contains two lists: one with nodes and one with edges. - * - * DOT language reference: http://www.graphviz.org/doc/info/lang.html - * - * @param {String} data Text containing a graph in DOT-notation - * @return {Object} graph An object containing two parameters: - * {Object[]} nodes - * {Object[]} edges - */ - function parseDOT (data) { - dot = data; - return parseGraph(); - } + isDSTShifted : function () { - // token types enumeration - var TOKENTYPE = { - NULL : 0, - DELIMITER : 1, - IDENTIFIER: 2, - UNKNOWN : 3 - }; + if (this._a) { + return this.isValid() && compareArrays(this._a, (this._isUTC ? moment.utc(this._a) : moment(this._a)).toArray()) > 0; + } - // map with all delimiters - var DELIMITERS = { - '{': true, - '}': true, - '[': true, - ']': true, - ';': true, - '=': true, - ',': true, + return false; + }, - '->': true, - '--': true - }; + parsingFlags : function () { + return extend({}, this._pf); + }, - var dot = ''; // current dot file - var index = 0; // current index in dot file - var c = ''; // current token character in expr - var token = ''; // current token - var tokenType = TOKENTYPE.NULL; // type of the token + invalidAt: function () { + return this._pf.overflow; + }, - /** - * Get the first character from the dot file. - * The character is stored into the char c. If the end of the dot file is - * reached, the function puts an empty string in c. - */ - function first() { - index = 0; - c = dot.charAt(0); - } + utc : function () { + return this.zone(0); + }, - /** - * Get the next character from the dot file. - * The character is stored into the char c. If the end of the dot file is - * reached, the function puts an empty string in c. - */ - function next() { - index++; - c = dot.charAt(index); - } + local : function () { + this.zone(0); + this._isUTC = false; + return this; + }, - /** - * Preview the next character from the dot file. - * @return {String} cNext - */ - function nextPreview() { - return dot.charAt(index + 1); - } + format : function (inputString) { + var output = formatMoment(this, inputString || moment.defaultFormat); + return this.lang().postformat(output); + }, - /** - * Test whether given character is alphabetic or numeric - * @param {String} c - * @return {Boolean} isAlphaNumeric - */ - var regexAlphaNumeric = /[a-zA-Z_0-9.:#]/; - function isAlphaNumeric(c) { - return regexAlphaNumeric.test(c); - } + add : function (input, val) { + var dur; + // switch args to support add('s', 1) and add(1, 's') + if (typeof input === 'string' && typeof val === 'string') { + dur = moment.duration(isNaN(+val) ? +input : +val, isNaN(+val) ? val : input); + } else if (typeof input === 'string') { + dur = moment.duration(+val, input); + } else { + dur = moment.duration(input, val); + } + addOrSubtractDurationFromMoment(this, dur, 1); + return this; + }, - /** - * Merge all properties of object b into object b - * @param {Object} a - * @param {Object} b - * @return {Object} a - */ - function merge (a, b) { - if (!a) { - a = {}; - } + subtract : function (input, val) { + var dur; + // switch args to support subtract('s', 1) and subtract(1, 's') + if (typeof input === 'string' && typeof val === 'string') { + dur = moment.duration(isNaN(+val) ? +input : +val, isNaN(+val) ? val : input); + } else if (typeof input === 'string') { + dur = moment.duration(+val, input); + } else { + dur = moment.duration(input, val); + } + addOrSubtractDurationFromMoment(this, dur, -1); + return this; + }, - if (b) { - for (var name in b) { - if (b.hasOwnProperty(name)) { - a[name] = b[name]; - } - } - } - return a; - } + diff : function (input, units, asFloat) { + var that = makeAs(input, this), + zoneDiff = (this.zone() - that.zone()) * 6e4, + diff, output; - /** - * Set a value in an object, where the provided parameter name can be a - * path with nested parameters. For example: - * - * var obj = {a: 2}; - * setValue(obj, 'b.c', 3); // obj = {a: 2, b: {c: 3}} - * - * @param {Object} obj - * @param {String} path A parameter name or dot-separated parameter path, - * like "color.highlight.border". - * @param {*} value - */ - function setValue(obj, path, value) { - var keys = path.split('.'); - var o = obj; - while (keys.length) { - var key = keys.shift(); - if (keys.length) { - // this isn't the end point - if (!o[key]) { - o[key] = {}; - } - o = o[key]; - } - else { - // this is the end point - o[key] = value; - } - } - } + units = normalizeUnits(units); - /** - * Add a node to a graph object. If there is already a node with - * the same id, their attributes will be merged. - * @param {Object} graph - * @param {Object} node - */ - function addNode(graph, node) { - var i, len; - var current = null; + if (units === 'year' || units === 'month') { + // average number of days in the months in the given dates + diff = (this.daysInMonth() + that.daysInMonth()) * 432e5; // 24 * 60 * 60 * 1000 / 2 + // difference in months + output = ((this.year() - that.year()) * 12) + (this.month() - that.month()); + // adjust by taking difference in days, average number of days + // and dst in the given months. + output += ((this - moment(this).startOf('month')) - + (that - moment(that).startOf('month'))) / diff; + // same as above but with zones, to negate all dst + output -= ((this.zone() - moment(this).startOf('month').zone()) - + (that.zone() - moment(that).startOf('month').zone())) * 6e4 / diff; + if (units === 'year') { + output = output / 12; + } + } else { + diff = (this - that); + output = units === 'second' ? diff / 1e3 : // 1000 + units === 'minute' ? diff / 6e4 : // 1000 * 60 + units === 'hour' ? diff / 36e5 : // 1000 * 60 * 60 + units === 'day' ? (diff - zoneDiff) / 864e5 : // 1000 * 60 * 60 * 24, negate dst + units === 'week' ? (diff - zoneDiff) / 6048e5 : // 1000 * 60 * 60 * 24 * 7, negate dst + diff; + } + return asFloat ? output : absRound(output); + }, - // find root graph (in case of subgraph) - var graphs = [graph]; // list with all graphs from current graph to root graph - var root = graph; - while (root.parent) { - graphs.push(root.parent); - root = root.parent; - } + from : function (time, withoutSuffix) { + return moment.duration(this.diff(time)).lang(this.lang()._abbr).humanize(!withoutSuffix); + }, - // find existing node (at root level) by its id - if (root.nodes) { - for (i = 0, len = root.nodes.length; i < len; i++) { - if (node.id === root.nodes[i].id) { - current = root.nodes[i]; - break; - } - } - } + fromNow : function (withoutSuffix) { + return this.from(moment(), withoutSuffix); + }, - if (!current) { - // this is a new node - current = { - id: node.id - }; - if (graph.node) { - // clone default attributes - current.attr = merge(current.attr, graph.node); - } - } + calendar : function (time) { + // We want to compare the start of today, vs this. + // Getting start-of-today depends on whether we're zone'd or not. + var now = time || moment(), + sod = makeAs(now, this).startOf('day'), + diff = this.diff(sod, 'days', true), + format = diff < -6 ? 'sameElse' : + diff < -1 ? 'lastWeek' : + diff < 0 ? 'lastDay' : + diff < 1 ? 'sameDay' : + diff < 2 ? 'nextDay' : + diff < 7 ? 'nextWeek' : 'sameElse'; + return this.format(this.lang().calendar(format, this)); + }, - // add node to this (sub)graph and all its parent graphs - for (i = graphs.length - 1; i >= 0; i--) { - var g = graphs[i]; + isLeapYear : function () { + return isLeapYear(this.year()); + }, - if (!g.nodes) { - g.nodes = []; - } - if (g.nodes.indexOf(current) == -1) { - g.nodes.push(current); - } - } + isDST : function () { + return (this.zone() < this.clone().month(0).zone() || + this.zone() < this.clone().month(5).zone()); + }, - // merge attributes - if (node.attr) { - current.attr = merge(current.attr, node.attr); - } - } + day : function (input) { + var day = this._isUTC ? this._d.getUTCDay() : this._d.getDay(); + if (input != null) { + input = parseWeekday(input, this.lang()); + return this.add({ d : input - day }); + } else { + return day; + } + }, - /** - * Add an edge to a graph object - * @param {Object} graph - * @param {Object} edge - */ - function addEdge(graph, edge) { - if (!graph.edges) { - graph.edges = []; - } - graph.edges.push(edge); - if (graph.edge) { - var attr = merge({}, graph.edge); // clone default attributes - edge.attr = merge(attr, edge.attr); // merge attributes - } - } + month : makeAccessor('Month', true), - /** - * Create an edge to a graph object - * @param {Object} graph - * @param {String | Number | Object} from - * @param {String | Number | Object} to - * @param {String} type - * @param {Object | null} attr - * @return {Object} edge - */ - function createEdge(graph, from, to, type, attr) { - var edge = { - from: from, - to: to, - type: type - }; + startOf: function (units) { + units = normalizeUnits(units); + // the following switch intentionally omits break keywords + // to utilize falling through the cases. + switch (units) { + case 'year': + this.month(0); + /* falls through */ + case 'quarter': + case 'month': + this.date(1); + /* falls through */ + case 'week': + case 'isoWeek': + case 'day': + this.hours(0); + /* falls through */ + case 'hour': + this.minutes(0); + /* falls through */ + case 'minute': + this.seconds(0); + /* falls through */ + case 'second': + this.milliseconds(0); + /* falls through */ + } - if (graph.edge) { - edge.attr = merge({}, graph.edge); // clone default attributes - } - edge.attr = merge(edge.attr || {}, attr); // merge attributes + // weeks are a special case + if (units === 'week') { + this.weekday(0); + } else if (units === 'isoWeek') { + this.isoWeekday(1); + } + + // quarters are also special + if (units === 'quarter') { + this.month(Math.floor(this.month() / 3) * 3); + } - return edge; - } + return this; + }, - /** - * Get next token in the current dot file. - * The token and token type are available as token and tokenType - */ - function getToken() { - tokenType = TOKENTYPE.NULL; - token = ''; + endOf: function (units) { + units = normalizeUnits(units); + return this.startOf(units).add((units === 'isoWeek' ? 'week' : units), 1).subtract('ms', 1); + }, - // skip over whitespaces - while (c == ' ' || c == '\t' || c == '\n' || c == '\r') { // space, tab, enter - next(); - } + isAfter: function (input, units) { + units = typeof units !== 'undefined' ? units : 'millisecond'; + return +this.clone().startOf(units) > +moment(input).startOf(units); + }, - do { - var isComment = false; + isBefore: function (input, units) { + units = typeof units !== 'undefined' ? units : 'millisecond'; + return +this.clone().startOf(units) < +moment(input).startOf(units); + }, - // skip comment - if (c == '#') { - // find the previous non-space character - var i = index - 1; - while (dot.charAt(i) == ' ' || dot.charAt(i) == '\t') { - i--; - } - if (dot.charAt(i) == '\n' || dot.charAt(i) == '') { - // the # is at the start of a line, this is indeed a line comment - while (c != '' && c != '\n') { - next(); - } - isComment = true; - } - } - if (c == '/' && nextPreview() == '/') { - // skip line comment - while (c != '' && c != '\n') { - next(); - } - isComment = true; - } - if (c == '/' && nextPreview() == '*') { - // skip block comment - while (c != '') { - if (c == '*' && nextPreview() == '/') { - // end of block comment found. skip these last two characters - next(); - next(); - break; - } - else { - next(); - } - } - isComment = true; - } + isSame: function (input, units) { + units = units || 'ms'; + return +this.clone().startOf(units) === +makeAs(input, this).startOf(units); + }, - // skip over whitespaces - while (c == ' ' || c == '\t' || c == '\n' || c == '\r') { // space, tab, enter - next(); - } - } - while (isComment); + min: deprecate( + "moment().min is deprecated, use moment.min instead. https://github.com/moment/moment/issues/1548", + function (other) { + other = moment.apply(null, arguments); + return other < this ? this : other; + } + ), - // check for end of dot file - if (c == '') { - // token is still empty - tokenType = TOKENTYPE.DELIMITER; - return; - } + max: deprecate( + "moment().max is deprecated, use moment.max instead. https://github.com/moment/moment/issues/1548", + function (other) { + other = moment.apply(null, arguments); + return other > this ? this : other; + } + ), - // check for delimiters consisting of 2 characters - var c2 = c + nextPreview(); - if (DELIMITERS[c2]) { - tokenType = TOKENTYPE.DELIMITER; - token = c2; - next(); - next(); - return; - } + // keepTime = true means only change the timezone, without affecting + // the local hour. So 5:31:26 +0300 --[zone(2, true)]--> 5:31:26 +0200 + // It is possible that 5:31:26 doesn't exist int zone +0200, so we + // adjust the time as needed, to be valid. + // + // Keeping the time actually adds/subtracts (one hour) + // from the actual represented time. That is why we call updateOffset + // a second time. In case it wants us to change the offset again + // _changeInProgress == true case, then we have to adjust, because + // there is no such time in the given timezone. + zone : function (input, keepTime) { + var offset = this._offset || 0; + if (input != null) { + if (typeof input === "string") { + input = timezoneMinutesFromString(input); + } + if (Math.abs(input) < 16) { + input = input * 60; + } + this._offset = input; + this._isUTC = true; + if (offset !== input) { + if (!keepTime || this._changeInProgress) { + addOrSubtractDurationFromMoment(this, + moment.duration(offset - input, 'm'), 1, false); + } else if (!this._changeInProgress) { + this._changeInProgress = true; + moment.updateOffset(this, true); + this._changeInProgress = null; + } + } + } else { + return this._isUTC ? offset : this._d.getTimezoneOffset(); + } + return this; + }, - // check for delimiters consisting of 1 character - if (DELIMITERS[c]) { - tokenType = TOKENTYPE.DELIMITER; - token = c; - next(); - return; - } + zoneAbbr : function () { + return this._isUTC ? "UTC" : ""; + }, - // check for an identifier (number or string) - // TODO: more precise parsing of numbers/strings (and the port separator ':') - if (isAlphaNumeric(c) || c == '-') { - token += c; - next(); + zoneName : function () { + return this._isUTC ? "Coordinated Universal Time" : ""; + }, - while (isAlphaNumeric(c)) { - token += c; - next(); - } - if (token == 'false') { - token = false; // convert to boolean - } - else if (token == 'true') { - token = true; // convert to boolean - } - else if (!isNaN(Number(token))) { - token = Number(token); // convert to number - } - tokenType = TOKENTYPE.IDENTIFIER; - return; - } + parseZone : function () { + if (this._tzm) { + this.zone(this._tzm); + } else if (typeof this._i === 'string') { + this.zone(this._i); + } + return this; + }, - // check for a string enclosed by double quotes - if (c == '"') { - next(); - while (c != '' && (c != '"' || (c == '"' && nextPreview() == '"'))) { - token += c; - if (c == '"') { // skip the escape character - next(); - } - next(); - } - if (c != '"') { - throw newSyntaxError('End of string " expected'); - } - next(); - tokenType = TOKENTYPE.IDENTIFIER; - return; - } + hasAlignedHourOffset : function (input) { + if (!input) { + input = 0; + } + else { + input = moment(input).zone(); + } - // something unknown is found, wrong characters, a syntax error - tokenType = TOKENTYPE.UNKNOWN; - while (c != '') { - token += c; - next(); - } - throw new SyntaxError('Syntax error in part "' + chop(token, 30) + '"'); - } + return (this.zone() - input) % 60 === 0; + }, - /** - * Parse a graph. - * @returns {Object} graph - */ - function parseGraph() { - var graph = {}; + daysInMonth : function () { + return daysInMonth(this.year(), this.month()); + }, - first(); - getToken(); + dayOfYear : function (input) { + var dayOfYear = round((moment(this).startOf('day') - moment(this).startOf('year')) / 864e5) + 1; + return input == null ? dayOfYear : this.add("d", (input - dayOfYear)); + }, - // optional strict keyword - if (token == 'strict') { - graph.strict = true; - getToken(); - } + quarter : function (input) { + return input == null ? Math.ceil((this.month() + 1) / 3) : this.month((input - 1) * 3 + this.month() % 3); + }, - // graph or digraph keyword - if (token == 'graph' || token == 'digraph') { - graph.type = token; - getToken(); - } + weekYear : function (input) { + var year = weekOfYear(this, this.lang()._week.dow, this.lang()._week.doy).year; + return input == null ? year : this.add("y", (input - year)); + }, - // optional graph id - if (tokenType == TOKENTYPE.IDENTIFIER) { - graph.id = token; - getToken(); - } + isoWeekYear : function (input) { + var year = weekOfYear(this, 1, 4).year; + return input == null ? year : this.add("y", (input - year)); + }, - // open angle bracket - if (token != '{') { - throw newSyntaxError('Angle bracket { expected'); - } - getToken(); + week : function (input) { + var week = this.lang().week(this); + return input == null ? week : this.add("d", (input - week) * 7); + }, - // statements - parseStatements(graph); + isoWeek : function (input) { + var week = weekOfYear(this, 1, 4).week; + return input == null ? week : this.add("d", (input - week) * 7); + }, - // close angle bracket - if (token != '}') { - throw newSyntaxError('Angle bracket } expected'); - } - getToken(); + weekday : function (input) { + var weekday = (this.day() + 7 - this.lang()._week.dow) % 7; + return input == null ? weekday : this.add("d", input - weekday); + }, - // end of file - if (token !== '') { - throw newSyntaxError('End of file expected'); - } - getToken(); + isoWeekday : function (input) { + // behaves the same as moment#day except + // as a getter, returns 7 instead of 0 (1-7 range instead of 0-6) + // as a setter, sunday should belong to the previous week. + return input == null ? this.day() || 7 : this.day(this.day() % 7 ? input : input - 7); + }, - // remove temporary default properties - delete graph.node; - delete graph.edge; - delete graph.graph; + isoWeeksInYear : function () { + return weeksInYear(this.year(), 1, 4); + }, - return graph; - } + weeksInYear : function () { + var weekInfo = this._lang._week; + return weeksInYear(this.year(), weekInfo.dow, weekInfo.doy); + }, - /** - * Parse a list with statements. - * @param {Object} graph - */ - function parseStatements (graph) { - while (token !== '' && token != '}') { - parseStatement(graph); - if (token == ';') { - getToken(); - } - } - } + get : function (units) { + units = normalizeUnits(units); + return this[units](); + }, - /** - * Parse a single statement. Can be a an attribute statement, node - * statement, a series of node statements and edge statements, or a - * parameter. - * @param {Object} graph - */ - function parseStatement(graph) { - // parse subgraph - var subgraph = parseSubgraph(graph); - if (subgraph) { - // edge statements - parseEdge(graph, subgraph); + set : function (units, value) { + units = normalizeUnits(units); + if (typeof this[units] === 'function') { + this[units](value); + } + return this; + }, - return; - } + // If passed a language key, it will set the language for this + // instance. Otherwise, it will return the language configuration + // variables for this instance. + lang : function (key) { + if (key === undefined) { + return this._lang; + } else { + this._lang = getLangDefinition(key); + return this; + } + } + }); - // parse an attribute statement - var attr = parseAttributeStatement(graph); - if (attr) { - return; - } + function rawMonthSetter(mom, value) { + var dayOfMonth; - // parse node - if (tokenType != TOKENTYPE.IDENTIFIER) { - throw newSyntaxError('Identifier expected'); - } - var id = token; // id can be a string or a number - getToken(); + // TODO: Move this out of here! + if (typeof value === 'string') { + value = mom.lang().monthsParse(value); + // TODO: Another silent failure? + if (typeof value !== 'number') { + return mom; + } + } - if (token == '=') { - // id statement - getToken(); - if (tokenType != TOKENTYPE.IDENTIFIER) { - throw newSyntaxError('Identifier expected'); + dayOfMonth = Math.min(mom.date(), + daysInMonth(mom.year(), value)); + mom._d['set' + (mom._isUTC ? 'UTC' : '') + 'Month'](value, dayOfMonth); + return mom; } - graph[id] = token; - getToken(); - // TODO: implement comma separated list with "a_list: ID=ID [','] [a_list] " - } - else { - parseNodeStatement(graph, id); - } - } - /** - * Parse a subgraph - * @param {Object} graph parent graph object - * @return {Object | null} subgraph - */ - function parseSubgraph (graph) { - var subgraph = null; + function rawGetter(mom, unit) { + return mom._d['get' + (mom._isUTC ? 'UTC' : '') + unit](); + } - // optional subgraph keyword - if (token == 'subgraph') { - subgraph = {}; - subgraph.type = 'subgraph'; - getToken(); + function rawSetter(mom, unit, value) { + if (unit === 'Month') { + return rawMonthSetter(mom, value); + } else { + return mom._d['set' + (mom._isUTC ? 'UTC' : '') + unit](value); + } + } - // optional graph id - if (tokenType == TOKENTYPE.IDENTIFIER) { - subgraph.id = token; - getToken(); + function makeAccessor(unit, keepTime) { + return function (value) { + if (value != null) { + rawSetter(this, unit, value); + moment.updateOffset(this, keepTime); + return this; + } else { + return rawGetter(this, unit); + } + }; } - } - // open angle bracket - if (token == '{') { - getToken(); + moment.fn.millisecond = moment.fn.milliseconds = makeAccessor('Milliseconds', false); + moment.fn.second = moment.fn.seconds = makeAccessor('Seconds', false); + moment.fn.minute = moment.fn.minutes = makeAccessor('Minutes', false); + // Setting the hour should keep the time, because the user explicitly + // specified which hour he wants. So trying to maintain the same hour (in + // a new timezone) makes sense. Adding/subtracting hours does not follow + // this rule. + moment.fn.hour = moment.fn.hours = makeAccessor('Hours', true); + // moment.fn.month is defined separately + moment.fn.date = makeAccessor('Date', true); + moment.fn.dates = deprecate("dates accessor is deprecated. Use date instead.", makeAccessor('Date', true)); + moment.fn.year = makeAccessor('FullYear', true); + moment.fn.years = deprecate("years accessor is deprecated. Use year instead.", makeAccessor('FullYear', true)); - if (!subgraph) { - subgraph = {}; - } - subgraph.parent = graph; - subgraph.node = graph.node; - subgraph.edge = graph.edge; - subgraph.graph = graph.graph; + // add plural methods + moment.fn.days = moment.fn.day; + moment.fn.months = moment.fn.month; + moment.fn.weeks = moment.fn.week; + moment.fn.isoWeeks = moment.fn.isoWeek; + moment.fn.quarters = moment.fn.quarter; - // statements - parseStatements(subgraph); + // add aliased format methods + moment.fn.toJSON = moment.fn.toISOString; - // close angle bracket - if (token != '}') { - throw newSyntaxError('Angle bracket } expected'); - } - getToken(); + /************************************ + Duration Prototype + ************************************/ - // remove temporary default properties - delete subgraph.node; - delete subgraph.edge; - delete subgraph.graph; - delete subgraph.parent; - // register at the parent graph - if (!graph.subgraphs) { - graph.subgraphs = []; - } - graph.subgraphs.push(subgraph); - } + extend(moment.duration.fn = Duration.prototype, { - return subgraph; - } + _bubble : function () { + var milliseconds = this._milliseconds, + days = this._days, + months = this._months, + data = this._data, + seconds, minutes, hours, years; - /** - * parse an attribute statement like "node [shape=circle fontSize=16]". - * Available keywords are 'node', 'edge', 'graph'. - * The previous list with default attributes will be replaced - * @param {Object} graph - * @returns {String | null} keyword Returns the name of the parsed attribute - * (node, edge, graph), or null if nothing - * is parsed. - */ - function parseAttributeStatement (graph) { - // attribute statements - if (token == 'node') { - getToken(); + // The following code bubbles up values, see the tests for + // examples of what that means. + data.milliseconds = milliseconds % 1000; + + seconds = absRound(milliseconds / 1000); + data.seconds = seconds % 60; - // node attributes - graph.node = parseAttributeList(); - return 'node'; - } - else if (token == 'edge') { - getToken(); + minutes = absRound(seconds / 60); + data.minutes = minutes % 60; - // edge attributes - graph.edge = parseAttributeList(); - return 'edge'; - } - else if (token == 'graph') { - getToken(); + hours = absRound(minutes / 60); + data.hours = hours % 24; - // graph attributes - graph.graph = parseAttributeList(); - return 'graph'; - } + days += absRound(hours / 24); + data.days = days % 30; - return null; - } + months += absRound(days / 30); + data.months = months % 12; - /** - * parse a node statement - * @param {Object} graph - * @param {String | Number} id - */ - function parseNodeStatement(graph, id) { - // node statement - var node = { - id: id - }; - var attr = parseAttributeList(); - if (attr) { - node.attr = attr; - } - addNode(graph, node); + years = absRound(months / 12); + data.years = years; + }, - // edge statements - parseEdge(graph, id); - } + weeks : function () { + return absRound(this.days() / 7); + }, - /** - * Parse an edge or a series of edges - * @param {Object} graph - * @param {String | Number} from Id of the from node - */ - function parseEdge(graph, from) { - while (token == '->' || token == '--') { - var to; - var type = token; - getToken(); + valueOf : function () { + return this._milliseconds + + this._days * 864e5 + + (this._months % 12) * 2592e6 + + toInt(this._months / 12) * 31536e6; + }, - var subgraph = parseSubgraph(graph); - if (subgraph) { - to = subgraph; - } - else { - if (tokenType != TOKENTYPE.IDENTIFIER) { - throw newSyntaxError('Identifier or subgraph expected'); - } - to = token; - addNode(graph, { - id: to - }); - getToken(); - } + humanize : function (withSuffix) { + var difference = +this, + output = relativeTime(difference, !withSuffix, this.lang()); - // parse edge attributes - var attr = parseAttributeList(); + if (withSuffix) { + output = this.lang().pastFuture(difference, output); + } - // create edge - var edge = createEdge(graph, from, to, type, attr); - addEdge(graph, edge); + return this.lang().postformat(output); + }, - from = to; - } - } + add : function (input, val) { + // supports only 2.0-style add(1, 's') or add(moment) + var dur = moment.duration(input, val); - /** - * Parse a set with attributes, - * for example [label="1.000", shape=solid] - * @return {Object | null} attr - */ - function parseAttributeList() { - var attr = null; + this._milliseconds += dur._milliseconds; + this._days += dur._days; + this._months += dur._months; - while (token == '[') { - getToken(); - attr = {}; - while (token !== '' && token != ']') { - if (tokenType != TOKENTYPE.IDENTIFIER) { - throw newSyntaxError('Attribute name expected'); - } - var name = token; + this._bubble(); - getToken(); - if (token != '=') { - throw newSyntaxError('Equal sign = expected'); - } - getToken(); + return this; + }, - if (tokenType != TOKENTYPE.IDENTIFIER) { - throw newSyntaxError('Attribute value expected'); - } - var value = token; - setValue(attr, name, value); // name can be a path + subtract : function (input, val) { + var dur = moment.duration(input, val); - getToken(); - if (token ==',') { - getToken(); - } - } + this._milliseconds -= dur._milliseconds; + this._days -= dur._days; + this._months -= dur._months; - if (token != ']') { - throw newSyntaxError('Bracket ] expected'); - } - getToken(); - } + this._bubble(); - return attr; - } + return this; + }, - /** - * Create a syntax error with extra information on current token and index. - * @param {String} message - * @returns {SyntaxError} err - */ - function newSyntaxError(message) { - return new SyntaxError(message + ', got "' + chop(token, 30) + '" (char ' + index + ')'); - } + get : function (units) { + units = normalizeUnits(units); + return this[units.toLowerCase() + 's'](); + }, - /** - * Chop off text after a maximum length - * @param {String} text - * @param {Number} maxLength - * @returns {String} - */ - function chop (text, maxLength) { - return (text.length <= maxLength) ? text : (text.substr(0, 27) + '...'); - } + as : function (units) { + units = normalizeUnits(units); + return this['as' + units.charAt(0).toUpperCase() + units.slice(1) + 's'](); + }, - /** - * Execute a function fn for each pair of elements in two arrays - * @param {Array | *} array1 - * @param {Array | *} array2 - * @param {function} fn - */ - function forEach2(array1, array2, fn) { - if (array1 instanceof Array) { - array1.forEach(function (elem1) { - if (array2 instanceof Array) { - array2.forEach(function (elem2) { - fn(elem1, elem2); - }); - } - else { - fn(elem1, array2); - } - }); - } - else { - if (array2 instanceof Array) { - array2.forEach(function (elem2) { - fn(array1, elem2); - }); - } - else { - fn(array1, array2); - } - } - } + lang : moment.fn.lang, - /** - * Convert a string containing a graph in DOT language into a map containing - * with nodes and edges in the format of graph. - * @param {String} data Text containing a graph in DOT-notation - * @return {Object} graphData - */ - function DOTToGraph (data) { - // parse the DOT file - var dotData = parseDOT(data); - var graphData = { - nodes: [], - edges: [], - options: {} - }; + toIsoString : function () { + // inspired by https://github.com/dordille/moment-isoduration/blob/master/moment.isoduration.js + var years = Math.abs(this.years()), + months = Math.abs(this.months()), + days = Math.abs(this.days()), + hours = Math.abs(this.hours()), + minutes = Math.abs(this.minutes()), + seconds = Math.abs(this.seconds() + this.milliseconds() / 1000); - // copy the nodes - if (dotData.nodes) { - dotData.nodes.forEach(function (dotNode) { - var graphNode = { - id: dotNode.id, - label: String(dotNode.label || dotNode.id) - }; - merge(graphNode, dotNode.attr); - if (graphNode.image) { - graphNode.shape = 'image'; - } - graphData.nodes.push(graphNode); + if (!this.asSeconds()) { + // this is the same as C#'s (Noda) and python (isodate)... + // but not other JS (goog.date) + return 'P0D'; + } + + return (this.asSeconds() < 0 ? '-' : '') + + 'P' + + (years ? years + 'Y' : '') + + (months ? months + 'M' : '') + + (days ? days + 'D' : '') + + ((hours || minutes || seconds) ? 'T' : '') + + (hours ? hours + 'H' : '') + + (minutes ? minutes + 'M' : '') + + (seconds ? seconds + 'S' : ''); + } }); - } - // copy the edges - if (dotData.edges) { - /** - * Convert an edge in DOT format to an edge with VisGraph format - * @param {Object} dotEdge - * @returns {Object} graphEdge - */ - function convertEdge(dotEdge) { - var graphEdge = { - from: dotEdge.from, - to: dotEdge.to - }; - merge(graphEdge, dotEdge.attr); - graphEdge.style = (dotEdge.type == '->') ? 'arrow' : 'line'; - return graphEdge; + function makeDurationGetter(name) { + moment.duration.fn[name] = function () { + return this._data[name]; + }; } - dotData.edges.forEach(function (dotEdge) { - var from, to; - if (dotEdge.from instanceof Object) { - from = dotEdge.from.nodes; - } - else { - from = { - id: dotEdge.from - } - } + function makeDurationAsGetter(name, factor) { + moment.duration.fn['as' + name] = function () { + return +this / factor; + }; + } - if (dotEdge.to instanceof Object) { - to = dotEdge.to.nodes; - } - else { - to = { - id: dotEdge.to + for (i in unitMillisecondFactors) { + if (unitMillisecondFactors.hasOwnProperty(i)) { + makeDurationAsGetter(i, unitMillisecondFactors[i]); + makeDurationGetter(i.toLowerCase()); } - } + } - if (dotEdge.from instanceof Object && dotEdge.from.edges) { - dotEdge.from.edges.forEach(function (subEdge) { - var graphEdge = convertEdge(subEdge); - graphData.edges.push(graphEdge); - }); - } + makeDurationAsGetter('Weeks', 6048e5); + moment.duration.fn.asMonths = function () { + return (+this - this.years() * 31536e6) / 2592e6 + this.years() * 12; + }; - forEach2(from, to, function (from, to) { - var subEdge = createEdge(graphData, from.id, to.id, dotEdge.type, dotEdge.attr); - var graphEdge = convertEdge(subEdge); - graphData.edges.push(graphEdge); - }); - if (dotEdge.to instanceof Object && dotEdge.to.edges) { - dotEdge.to.edges.forEach(function (subEdge) { - var graphEdge = convertEdge(subEdge); - graphData.edges.push(graphEdge); - }); - } + /************************************ + Default Lang + ************************************/ + + + // Set default language, other languages will inherit from English. + moment.lang('en', { + ordinal : function (number) { + var b = number % 10, + output = (toInt(number % 100 / 10) === 1) ? 'th' : + (b === 1) ? 'st' : + (b === 2) ? 'nd' : + (b === 3) ? 'rd' : 'th'; + return number + output; + } }); - } - // copy the options - if (dotData.attr) { - graphData.options = dotData.attr; - } + /* EMBED_LANGUAGES */ - return graphData; - } + /************************************ + Exposing Moment + ************************************/ - // exports - exports.parseDOT = parseDOT; - exports.DOTToGraph = DOTToGraph; + function makeGlobal(shouldDeprecate) { + /*global ender:false */ + if (typeof ender !== 'undefined') { + return; + } + oldGlobalMoment = globalScope.moment; + if (shouldDeprecate) { + globalScope.moment = deprecate( + "Accessing Moment through the global scope is " + + "deprecated, and will be removed in an upcoming " + + "release.", + moment); + } else { + globalScope.moment = moment; + } + } + + // CommonJS module is defined + if (hasModule) { + module.exports = moment; + } else if (true) { + !(__WEBPACK_AMD_DEFINE_RESULT__ = (function (require, exports, module) { + if (module.config && module.config() && module.config().noGlobal === true) { + // release the global variable + globalScope.moment = oldGlobalMoment; + } + return moment; + }.call(exports, __webpack_require__, exports, module)), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); + makeGlobal(true); + } else { + makeGlobal(); + } + }).call(this); + + /* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }()), __webpack_require__(61)(module))) /***/ }, -/* 44 */ +/* 48 */ /***/ function(module, exports, __webpack_require__) { - - function parseGephi(gephiJSON, options) { - var edges = []; - var nodes = []; - this.options = { - edges: { - inheritColor: true - }, - nodes: { - allowedToMove: false, - parseColor: false - } - }; + var __WEBPACK_AMD_DEFINE_RESULT__;/*! Hammer.JS - v1.1.3 - 2014-05-20 + * http://eightmedia.github.io/hammer.js + * + * Copyright (c) 2014 Jorik Tangelder ; + * Licensed under the MIT license */ - if (options !== undefined) { - this.options.nodes['allowedToMove'] = options.allowedToMove | false; - this.options.nodes['parseColor'] = options.parseColor | false; - this.options.edges['inheritColor'] = options.inheritColor | true; - } + (function(window, undefined) { + 'use strict'; - var gEdges = gephiJSON.edges; - var gNodes = gephiJSON.nodes; - for (var i = 0; i < gEdges.length; i++) { - var edge = {}; - var gEdge = gEdges[i]; - edge['id'] = gEdge.id; - edge['from'] = gEdge.source; - edge['to'] = gEdge.target; - edge['attributes'] = gEdge.attributes; - // edge['value'] = gEdge.attributes !== undefined ? gEdge.attributes.Weight : undefined; - // edge['width'] = edge['value'] !== undefined ? undefined : edgegEdge.size; - edge['color'] = gEdge.color; - edge['inheritColor'] = edge['color'] !== undefined ? false : this.options.inheritColor; - edges.push(edge); - } + /** + * @main + * @module hammer + * + * @class Hammer + * @static + */ - for (var i = 0; i < gNodes.length; i++) { - var node = {}; - var gNode = gNodes[i]; - node['id'] = gNode.id; - node['attributes'] = gNode.attributes; - node['x'] = gNode.x; - node['y'] = gNode.y; - node['label'] = gNode.label; - if (this.options.nodes.parseColor == true) { - node['color'] = gNode.color; - } - else { - node['color'] = gNode.color !== undefined ? {background:gNode.color, border:gNode.color} : undefined; - } - node['radius'] = gNode.size; - node['allowedToMoveX'] = this.options.nodes.allowedToMove; - node['allowedToMoveY'] = this.options.nodes.allowedToMove; - nodes.push(node); - } + /** + * Hammer, use this to create instances + * ```` + * var hammertime = new Hammer(myElement); + * ```` + * + * @method Hammer + * @param {HTMLElement} element + * @param {Object} [options={}] + * @return {Hammer.Instance} + */ + var Hammer = function Hammer(element, options) { + return new Hammer.Instance(element, options || {}); + }; + + /** + * version, as defined in package.json + * the value will be set at each build + * @property VERSION + * @final + * @type {String} + */ + Hammer.VERSION = '1.1.3'; + + /** + * default settings. + * more settings are defined per gesture at `/gestures`. Each gesture can be disabled/enabled + * by setting it's name (like `swipe`) to false. + * You can set the defaults for all instances by changing this object before creating an instance. + * @example + * ```` + * Hammer.defaults.drag = false; + * Hammer.defaults.behavior.touchAction = 'pan-y'; + * delete Hammer.defaults.behavior.userSelect; + * ```` + * @property defaults + * @type {Object} + */ + Hammer.defaults = { + /** + * this setting object adds styles and attributes to the element to prevent the browser from doing + * its native behavior. The css properties are auto prefixed for the browsers when needed. + * @property defaults.behavior + * @type {Object} + */ + behavior: { + /** + * Disables text selection to improve the dragging gesture. When the value is `none` it also sets + * `onselectstart=false` for IE on the element. Mainly for desktop browsers. + * @property defaults.behavior.userSelect + * @type {String} + * @default 'none' + */ + userSelect: 'none', + + /** + * Specifies whether and how a given region can be manipulated by the user (for instance, by panning or zooming). + * Used by Chrome 35> and IE10>. By default this makes the element blocking any touch event. + * @property defaults.behavior.touchAction + * @type {String} + * @default: 'pan-y' + */ + touchAction: 'pan-y', - return {nodes:nodes, edges:edges}; - } + /** + * Disables the default callout shown when you touch and hold a touch target. + * On iOS, when you touch and hold a touch target such as a link, Safari displays + * a callout containing information about the link. This property allows you to disable that callout. + * @property defaults.behavior.touchCallout + * @type {String} + * @default 'none' + */ + touchCallout: 'none', - exports.parseGephi = parseGephi; + /** + * Specifies whether zooming is enabled. Used by IE10> + * @property defaults.behavior.contentZooming + * @type {String} + * @default 'none' + */ + contentZooming: 'none', -/***/ }, -/* 45 */ -/***/ function(module, exports, __webpack_require__) { + /** + * Specifies that an entire element should be draggable instead of its contents. + * Mainly for desktop browsers. + * @property defaults.behavior.userDrag + * @type {String} + * @default 'none' + */ + userDrag: 'none', - var util = __webpack_require__(1); + /** + * Overrides the highlight color shown when the user taps a link or a JavaScript + * clickable element in Safari on iPhone. This property obeys the alpha value, if specified. + * + * If you don't specify an alpha value, Safari on iPhone applies a default alpha value + * to the color. To disable tap highlighting, set the alpha value to 0 (invisible). + * If you set the alpha value to 1.0 (opaque), the element is not visible when tapped. + * @property defaults.behavior.tapHighlightColor + * @type {String} + * @default 'rgba(0,0,0,0)' + */ + tapHighlightColor: 'rgba(0,0,0,0)' + } + }; /** - * @class Groups - * This class can store groups and properties specific for groups. + * hammer document where the base events are added at + * @property DOCUMENT + * @type {HTMLElement} + * @default window.document */ - function Groups() { - this.clear(); - this.defaultIndex = 0; - } - + Hammer.DOCUMENT = document; /** - * default constants for group colors + * detect support for pointer events + * @property HAS_POINTEREVENTS + * @type {Boolean} */ - Groups.DEFAULT = [ - {border: "#2B7CE9", background: "#97C2FC", highlight: {border: "#2B7CE9", background: "#D2E5FF"}, hover: {border: "#2B7CE9", background: "#D2E5FF"}}, // blue - {border: "#FFA500", background: "#FFFF00", highlight: {border: "#FFA500", background: "#FFFFA3"}, hover: {border: "#FFA500", background: "#FFFFA3"}}, // yellow - {border: "#FA0A10", background: "#FB7E81", highlight: {border: "#FA0A10", background: "#FFAFB1"}, hover: {border: "#FA0A10", background: "#FFAFB1"}}, // red - {border: "#41A906", background: "#7BE141", highlight: {border: "#41A906", background: "#A1EC76"}, hover: {border: "#41A906", background: "#A1EC76"}}, // green - {border: "#E129F0", background: "#EB7DF4", highlight: {border: "#E129F0", background: "#F0B3F5"}, hover: {border: "#E129F0", background: "#F0B3F5"}}, // magenta - {border: "#7C29F0", background: "#AD85E4", highlight: {border: "#7C29F0", background: "#D3BDF0"}, hover: {border: "#7C29F0", background: "#D3BDF0"}}, // purple - {border: "#C37F00", background: "#FFA807", highlight: {border: "#C37F00", background: "#FFCA66"}, hover: {border: "#C37F00", background: "#FFCA66"}}, // orange - {border: "#4220FB", background: "#6E6EFD", highlight: {border: "#4220FB", background: "#9B9BFD"}, hover: {border: "#4220FB", background: "#9B9BFD"}}, // darkblue - {border: "#FD5A77", background: "#FFC0CB", highlight: {border: "#FD5A77", background: "#FFD1D9"}, hover: {border: "#FD5A77", background: "#FFD1D9"}}, // pink - {border: "#4AD63A", background: "#C2FABC", highlight: {border: "#4AD63A", background: "#E6FFE3"}, hover: {border: "#4AD63A", background: "#E6FFE3"}} // mint - ]; - + Hammer.HAS_POINTEREVENTS = navigator.pointerEnabled || navigator.msPointerEnabled; /** - * Clear all groups + * detect support for touch events + * @property HAS_TOUCHEVENTS + * @type {Boolean} */ - Groups.prototype.clear = function () { - this.groups = {}; - this.groups.length = function() - { - var i = 0; - for ( var p in this ) { - if (this.hasOwnProperty(p)) { - i++; - } - } - return i; - } - }; - + Hammer.HAS_TOUCHEVENTS = ('ontouchstart' in window); /** - * get group properties of a groupname. If groupname is not found, a new group - * is added. - * @param {*} groupname Can be a number, string, Date, etc. - * @return {Object} group The created group, containing all group properties + * detect mobile browsers + * @property IS_MOBILE + * @type {Boolean} */ - Groups.prototype.get = function (groupname) { - var group = this.groups[groupname]; - if (group == undefined) { - // create new group - var index = this.defaultIndex % Groups.DEFAULT.length; - this.defaultIndex++; - group = {}; - group.color = Groups.DEFAULT[index]; - this.groups[groupname] = group; - } + Hammer.IS_MOBILE = /mobile|tablet|ip(ad|hone|od)|android|silk/i.test(navigator.userAgent); - return group; - }; + /** + * detect if we want to support mouseevents at all + * @property NO_MOUSEEVENTS + * @type {Boolean} + */ + Hammer.NO_MOUSEEVENTS = (Hammer.HAS_TOUCHEVENTS && Hammer.IS_MOBILE) || Hammer.HAS_POINTEREVENTS; /** - * Add a custom group style - * @param {String} groupname - * @param {Object} style An object containing borderColor, - * backgroundColor, etc. - * @return {Object} group The created group object + * interval in which Hammer recalculates current velocity/direction/angle in ms + * @property CALCULATE_INTERVAL + * @type {Number} + * @default 25 */ - Groups.prototype.add = function (groupname, style) { - this.groups[groupname] = style; - if (style.color) { - style.color = util.parseColor(style.color); - } - return style; - }; + Hammer.CALCULATE_INTERVAL = 25; - module.exports = Groups; + /** + * eventtypes per touchevent (start, move, end) are filled by `Event.determineEventTypes` on `setup` + * the object contains the DOM event names per type (`EVENT_START`, `EVENT_MOVE`, `EVENT_END`) + * @property EVENT_TYPES + * @private + * @writeOnce + * @type {Object} + */ + var EVENT_TYPES = {}; + /** + * direction strings, for safe comparisons + * @property DIRECTION_DOWN|LEFT|UP|RIGHT + * @final + * @type {String} + * @default 'down' 'left' 'up' 'right' + */ + var DIRECTION_DOWN = Hammer.DIRECTION_DOWN = 'down'; + var DIRECTION_LEFT = Hammer.DIRECTION_LEFT = 'left'; + var DIRECTION_UP = Hammer.DIRECTION_UP = 'up'; + var DIRECTION_RIGHT = Hammer.DIRECTION_RIGHT = 'right'; -/***/ }, -/* 46 */ -/***/ function(module, exports, __webpack_require__) { + /** + * pointertype strings, for safe comparisons + * @property POINTER_MOUSE|TOUCH|PEN + * @final + * @type {String} + * @default 'mouse' 'touch' 'pen' + */ + var POINTER_MOUSE = Hammer.POINTER_MOUSE = 'mouse'; + var POINTER_TOUCH = Hammer.POINTER_TOUCH = 'touch'; + var POINTER_PEN = Hammer.POINTER_PEN = 'pen'; /** - * @class Images - * This class loads images and keeps them stored. + * eventtypes + * @property EVENT_START|MOVE|END|RELEASE|TOUCH + * @final + * @type {String} + * @default 'start' 'change' 'move' 'end' 'release' 'touch' */ - function Images() { - this.images = {}; + var EVENT_START = Hammer.EVENT_START = 'start'; + var EVENT_MOVE = Hammer.EVENT_MOVE = 'move'; + var EVENT_END = Hammer.EVENT_END = 'end'; + var EVENT_RELEASE = Hammer.EVENT_RELEASE = 'release'; + var EVENT_TOUCH = Hammer.EVENT_TOUCH = 'touch'; - this.callback = undefined; - } + /** + * if the window events are set... + * @property READY + * @writeOnce + * @type {Boolean} + * @default false + */ + Hammer.READY = false; /** - * Set an onload callback function. This will be called each time an image - * is loaded - * @param {function} callback + * plugins namespace + * @property plugins + * @type {Object} */ - Images.prototype.setOnloadCallback = function(callback) { - this.callback = callback; - }; + Hammer.plugins = Hammer.plugins || {}; /** - * - * @param {string} url Url of the image - * @return {Image} img The image object + * gestures namespace + * see `/gestures` for the definitions + * @property gestures + * @type {Object} */ - Images.prototype.load = function(url) { - var img = this.images[url]; - if (img == undefined) { - // create the image - var images = this; - img = new Image(); - this.images[url] = img; - img.onload = function() { - if (images.callback) { - images.callback(this); - } - }; - img.src = url; - } + Hammer.gestures = Hammer.gestures || {}; - return img; - }; + /** + * setup events to detect gestures on the document + * this function is called when creating an new instance + * @private + */ + function setup() { + if(Hammer.READY) { + return; + } - module.exports = Images; + // find what eventtypes we add listeners to + Event.determineEventTypes(); + // Register all gestures inside Hammer.gestures + Utils.each(Hammer.gestures, function(gesture) { + Detection.register(gesture); + }); -/***/ }, -/* 47 */ -/***/ function(module, exports, __webpack_require__) { + // Add touch events on the document + Event.onTouch(Hammer.DOCUMENT, EVENT_MOVE, Detection.detect); + Event.onTouch(Hammer.DOCUMENT, EVENT_END, Detection.detect); - var util = __webpack_require__(1); + // Hammer is ready...! + Hammer.READY = true; + } /** - * @class Node - * A node. A node can be connected to other nodes via one or multiple edges. - * @param {object} properties An object containing properties for the node. All - * properties are optional, except for the id. - * {number} id Id of the node. Required - * {string} label Text label for the node - * {number} x Horizontal position of the node - * {number} y Vertical position of the node - * {string} shape Node shape, available: - * "database", "circle", "ellipse", - * "box", "image", "text", "dot", - * "star", "triangle", "triangleDown", - * "square" - * {string} image An image url - * {string} title An title text, can be HTML - * {anytype} group A group name or number - * @param {Network.Images} imagelist A list with images. Only needed - * when the node has an image - * @param {Network.Groups} grouplist A list with groups. Needed for - * retrieving group properties - * @param {Object} constants An object with default values for - * example for the color + * @module hammer * + * @class Utils + * @static */ - function Node(properties, imagelist, grouplist, networkConstants) { - var constants = util.selectiveBridgeObject(['nodes'],networkConstants); - this.options = constants.nodes; - - this.selected = false; - this.hover = false; - - this.edges = []; // all edges connected to this node - this.dynamicEdges = []; - this.reroutedEdges = {}; + var Utils = Hammer.utils = { + /** + * extend method, could also be used for cloning when `dest` is an empty object. + * changes the dest object + * @method extend + * @param {Object} dest + * @param {Object} src + * @param {Boolean} [merge=false] do a merge + * @return {Object} dest + */ + extend: function extend(dest, src, merge) { + for(var key in src) { + if(!src.hasOwnProperty(key) || (dest[key] !== undefined && merge)) { + continue; + } + dest[key] = src[key]; + } + return dest; + }, - this.fontDrawThreshold = 3; + /** + * simple addEventListener wrapper + * @method on + * @param {HTMLElement} element + * @param {String} type + * @param {Function} handler + */ + on: function on(element, type, handler) { + element.addEventListener(type, handler, false); + }, - // set defaults for the properties - this.id = undefined; - this.x = null; - this.y = null; - this.xFixed = false; - this.yFixed = false; - this.horizontalAlignLeft = true; // these are for the navigation controls - this.verticalAlignTop = true; // these are for the navigation controls - this.baseRadiusValue = networkConstants.nodes.radius; - this.radiusFixed = false; - this.level = -1; - this.preassignedLevel = false; + /** + * simple removeEventListener wrapper + * @method off + * @param {HTMLElement} element + * @param {String} type + * @param {Function} handler + */ + off: function off(element, type, handler) { + element.removeEventListener(type, handler, false); + }, + /** + * forEach over arrays and objects + * @method each + * @param {Object|Array} obj + * @param {Function} iterator + * @param {any} iterator.item + * @param {Number} iterator.index + * @param {Object|Array} iterator.obj the source object + * @param {Object} context value to use as `this` in the iterator + */ + each: function each(obj, iterator, context) { + var i, len; - this.imagelist = imagelist; - this.grouplist = grouplist; + // native forEach on arrays + if('forEach' in obj) { + obj.forEach(iterator, context); + // arrays + } else if(obj.length !== undefined) { + for(i = 0, len = obj.length; i < len; i++) { + if(iterator.call(context, obj[i], i, obj) === false) { + return; + } + } + // objects + } else { + for(i in obj) { + if(obj.hasOwnProperty(i) && + iterator.call(context, obj[i], i, obj) === false) { + return; + } + } + } + }, - // physics properties - this.fx = 0.0; // external force x - this.fy = 0.0; // external force y - this.vx = 0.0; // velocity x - this.vy = 0.0; // velocity y - this.damping = networkConstants.physics.damping; // written every time gravity is calculated - this.fixedData = {x:null,y:null}; + /** + * find if a string contains the string using indexOf + * @method inStr + * @param {String} src + * @param {String} find + * @return {Boolean} found + */ + inStr: function inStr(src, find) { + return src.indexOf(find) > -1; + }, + /** + * find if a array contains the object using indexOf or a simple polyfill + * @method inArray + * @param {String} src + * @param {String} find + * @return {Boolean|Number} false when not found, or the index + */ + inArray: function inArray(src, find) { + if(src.indexOf) { + var index = src.indexOf(find); + return (index === -1) ? false : index; + } else { + for(var i = 0, len = src.length; i < len; i++) { + if(src[i] === find) { + return i; + } + } + return false; + } + }, - this.setProperties(properties, constants); + /** + * convert an array-like object (`arguments`, `touchlist`) to an array + * @method toArray + * @param {Object} obj + * @return {Array} + */ + toArray: function toArray(obj) { + return Array.prototype.slice.call(obj, 0); + }, - // creating the variables for clustering - this.resetCluster(); - this.dynamicEdgesLength = 0; - this.clusterSession = 0; - this.clusterSizeWidthFactor = networkConstants.clustering.nodeScaling.width; - this.clusterSizeHeightFactor = networkConstants.clustering.nodeScaling.height; - this.clusterSizeRadiusFactor = networkConstants.clustering.nodeScaling.radius; - this.maxNodeSizeIncrements = networkConstants.clustering.maxNodeSizeIncrements; - this.growthIndicator = 0; + /** + * find if a node is in the given parent + * @method hasParent + * @param {HTMLElement} node + * @param {HTMLElement} parent + * @return {Boolean} found + */ + hasParent: function hasParent(node, parent) { + while(node) { + if(node == parent) { + return true; + } + node = node.parentNode; + } + return false; + }, - // variables to tell the node about the network. - this.networkScaleInv = 1; - this.networkScale = 1; - this.canvasTopLeft = {"x": -300, "y": -300}; - this.canvasBottomRight = {"x": 300, "y": 300}; - this.parentEdgeId = null; - } + /** + * get the center of all the touches + * @method getCenter + * @param {Array} touches + * @return {Object} center contains `pageX`, `pageY`, `clientX` and `clientY` properties + */ + getCenter: function getCenter(touches) { + var pageX = [], + pageY = [], + clientX = [], + clientY = [], + min = Math.min, + max = Math.max; - /** - * (re)setting the clustering variables and objects - */ - Node.prototype.resetCluster = function() { - // clustering variables - this.formationScale = undefined; // this is used to determine when to open the cluster - this.clusterSize = 1; // this signifies the total amount of nodes in this cluster - this.containedNodes = {}; - this.containedEdges = {}; - this.clusterSessions = []; - }; + // no need to loop when only one touch + if(touches.length === 1) { + return { + pageX: touches[0].pageX, + pageY: touches[0].pageY, + clientX: touches[0].clientX, + clientY: touches[0].clientY + }; + } - /** - * Attach a edge to the node - * @param {Edge} edge - */ - Node.prototype.attachEdge = function(edge) { - if (this.edges.indexOf(edge) == -1) { - this.edges.push(edge); - } - if (this.dynamicEdges.indexOf(edge) == -1) { - this.dynamicEdges.push(edge); - } - this.dynamicEdgesLength = this.dynamicEdges.length; - }; + Utils.each(touches, function(touch) { + pageX.push(touch.pageX); + pageY.push(touch.pageY); + clientX.push(touch.clientX); + clientY.push(touch.clientY); + }); - /** - * Detach a edge from the node - * @param {Edge} edge - */ - Node.prototype.detachEdge = function(edge) { - var index = this.edges.indexOf(edge); - if (index != -1) { - this.edges.splice(index, 1); - this.dynamicEdges.splice(index, 1); - } - this.dynamicEdgesLength = this.dynamicEdges.length; - }; + return { + pageX: (min.apply(Math, pageX) + max.apply(Math, pageX)) / 2, + pageY: (min.apply(Math, pageY) + max.apply(Math, pageY)) / 2, + clientX: (min.apply(Math, clientX) + max.apply(Math, clientX)) / 2, + clientY: (min.apply(Math, clientY) + max.apply(Math, clientY)) / 2 + }; + }, + /** + * calculate the velocity between two points. unit is in px per ms. + * @method getVelocity + * @param {Number} deltaTime + * @param {Number} deltaX + * @param {Number} deltaY + * @return {Object} velocity `x` and `y` + */ + getVelocity: function getVelocity(deltaTime, deltaX, deltaY) { + return { + x: Math.abs(deltaX / deltaTime) || 0, + y: Math.abs(deltaY / deltaTime) || 0 + }; + }, - /** - * Set or overwrite properties for the node - * @param {Object} properties an object with properties - * @param {Object} constants and object with default, global properties - */ - Node.prototype.setProperties = function(properties, constants) { - if (!properties) { - return; - } + /** + * calculate the angle between two coordinates + * @method getAngle + * @param {Touch} touch1 + * @param {Touch} touch2 + * @return {Number} angle + */ + getAngle: function getAngle(touch1, touch2) { + var x = touch2.clientX - touch1.clientX, + y = touch2.clientY - touch1.clientY; - var fields = ['borderWidth','borderWidthSelected','shape','image','radius','fontColor', - 'fontSize','fontFace','group','mass' - ]; - util.selectiveDeepExtend(fields, this.options, properties); + return Math.atan2(y, x) * 180 / Math.PI; + }, - this.originalLabel = undefined; - // basic properties - if (properties.id !== undefined) {this.id = properties.id;} - if (properties.label !== undefined) {this.label = properties.label; this.originalLabel = properties.label;} - if (properties.title !== undefined) {this.title = properties.title;} - if (properties.x !== undefined) {this.x = properties.x;} - if (properties.y !== undefined) {this.y = properties.y;} - if (properties.value !== undefined) {this.value = properties.value;} - if (properties.level !== undefined) {this.level = properties.level; this.preassignedLevel = true;} + /** + * do a small comparision to get the direction between two touches. + * @method getDirection + * @param {Touch} touch1 + * @param {Touch} touch2 + * @return {String} direction matches `DIRECTION_LEFT|RIGHT|UP|DOWN` + */ + getDirection: function getDirection(touch1, touch2) { + var x = Math.abs(touch1.clientX - touch2.clientX), + y = Math.abs(touch1.clientY - touch2.clientY); - // navigation controls properties - if (properties.horizontalAlignLeft !== undefined) {this.horizontalAlignLeft = properties.horizontalAlignLeft;} - if (properties.verticalAlignTop !== undefined) {this.verticalAlignTop = properties.verticalAlignTop;} - if (properties.triggerFunction !== undefined) {this.triggerFunction = properties.triggerFunction;} + if(x >= y) { + return touch1.clientX - touch2.clientX > 0 ? DIRECTION_LEFT : DIRECTION_RIGHT; + } + return touch1.clientY - touch2.clientY > 0 ? DIRECTION_UP : DIRECTION_DOWN; + }, - if (this.id === undefined) { - throw "Node must have an id"; - } + /** + * calculate the distance between two touches + * @method getDistance + * @param {Touch}touch1 + * @param {Touch} touch2 + * @return {Number} distance + */ + getDistance: function getDistance(touch1, touch2) { + var x = touch2.clientX - touch1.clientX, + y = touch2.clientY - touch1.clientY; - // copy group properties - if (typeof this.options.group === 'number' || (typeof this.options.group === 'string' && this.options.group != '')) { - var groupObj = this.grouplist.get(this.options.group); - for (var prop in groupObj) { - if (groupObj.hasOwnProperty(prop)) { - this.options[prop] = groupObj[prop]; - } - } - } + return Math.sqrt((x * x) + (y * y)); + }, + /** + * calculate the scale factor between two touchLists + * no scale is 1, and goes down to 0 when pinched together, and bigger when pinched out + * @method getScale + * @param {Array} start array of touches + * @param {Array} end array of touches + * @return {Number} scale + */ + getScale: function getScale(start, end) { + // need two fingers... + if(start.length >= 2 && end.length >= 2) { + return this.getDistance(end[0], end[1]) / this.getDistance(start[0], start[1]); + } + return 1; + }, - // individual shape properties - if (properties.radius !== undefined) {this.baseRadiusValue = this.options.radius;} - if (properties.color !== undefined) {this.options.color = util.parseColor(properties.color);} + /** + * calculate the rotation degrees between two touchLists + * @method getRotation + * @param {Array} start array of touches + * @param {Array} end array of touches + * @return {Number} rotation + */ + getRotation: function getRotation(start, end) { + // need two fingers + if(start.length >= 2 && end.length >= 2) { + return this.getAngle(end[1], end[0]) - this.getAngle(start[1], start[0]); + } + return 0; + }, - if (this.options.image!== undefined && this.options.image!= "") { - if (this.imagelist) { - this.imageObj = this.imagelist.load(this.options.image); - } - else { - throw "No imagelist provided"; - } - } + /** + * find out if the direction is vertical * + * @method isVertical + * @param {String} direction matches `DIRECTION_UP|DOWN` + * @return {Boolean} is_vertical + */ + isVertical: function isVertical(direction) { + return direction == DIRECTION_UP || direction == DIRECTION_DOWN; + }, - this.xFixed = this.xFixed || (properties.x !== undefined && !properties.allowedToMoveX); - this.yFixed = this.yFixed || (properties.y !== undefined && !properties.allowedToMoveY); - this.radiusFixed = this.radiusFixed || (properties.radius !== undefined); + /** + * set css properties with their prefixes + * @param {HTMLElement} element + * @param {String} prop + * @param {String} value + * @param {Boolean} [toggle=true] + * @return {Boolean} + */ + setPrefixedCss: function setPrefixedCss(element, prop, value, toggle) { + var prefixes = ['', 'Webkit', 'Moz', 'O', 'ms']; + prop = Utils.toCamelCase(prop); - if (this.options.shape == 'image') { - this.options.radiusMin = constants.nodes.widthMin; - this.options.radiusMax = constants.nodes.widthMax; - } + for(var i = 0; i < prefixes.length; i++) { + var p = prop; + // prefixes + if(prefixes[i]) { + p = prefixes[i] + p.slice(0, 1).toUpperCase() + p.slice(1); + } + // test the style + if(p in element.style) { + element.style[p] = (toggle == null || toggle) && value || ''; + break; + } + } + }, - // choose draw method depending on the shape - switch (this.options.shape) { - case 'database': this.draw = this._drawDatabase; this.resize = this._resizeDatabase; break; - case 'box': this.draw = this._drawBox; this.resize = this._resizeBox; break; - case 'circle': this.draw = this._drawCircle; this.resize = this._resizeCircle; break; - case 'ellipse': this.draw = this._drawEllipse; this.resize = this._resizeEllipse; break; - // TODO: add diamond shape - case 'image': this.draw = this._drawImage; this.resize = this._resizeImage; break; - case 'text': this.draw = this._drawText; this.resize = this._resizeText; break; - case 'dot': this.draw = this._drawDot; this.resize = this._resizeShape; break; - case 'square': this.draw = this._drawSquare; this.resize = this._resizeShape; break; - case 'triangle': this.draw = this._drawTriangle; this.resize = this._resizeShape; break; - case 'triangleDown': this.draw = this._drawTriangleDown; this.resize = this._resizeShape; break; - case 'star': this.draw = this._drawStar; this.resize = this._resizeShape; break; - default: this.draw = this._drawEllipse; this.resize = this._resizeEllipse; break; - } - // reset the size of the node, this can be changed - this._reset(); - }; + /** + * toggle browser default behavior by setting css properties. + * `userSelect='none'` also sets `element.onselectstart` to false + * `userDrag='none'` also sets `element.ondragstart` to false + * + * @method toggleBehavior + * @param {HtmlElement} element + * @param {Object} props + * @param {Boolean} [toggle=true] + */ + toggleBehavior: function toggleBehavior(element, props, toggle) { + if(!props || !element || !element.style) { + return; + } - /** - * select this node - */ - Node.prototype.select = function() { - this.selected = true; - this._reset(); - }; + // set the css properties + Utils.each(props, function(value, prop) { + Utils.setPrefixedCss(element, prop, value, toggle); + }); - /** - * unselect this node - */ - Node.prototype.unselect = function() { - this.selected = false; - this._reset(); + var falseFn = toggle && function() { + return false; + }; + + // also the disable onselectstart + if(props.userSelect == 'none') { + element.onselectstart = falseFn; + } + // and disable ondragstart + if(props.userDrag == 'none') { + element.ondragstart = falseFn; + } + }, + + /** + * convert a string with underscores to camelCase + * so prevent_default becomes preventDefault + * @param {String} str + * @return {String} camelCaseStr + */ + toCamelCase: function toCamelCase(str) { + return str.replace(/[_-]([a-z])/g, function(s) { + return s[1].toUpperCase(); + }); + } }; /** - * Reset the calculated size of the node, forces it to recalculate its size + * @module hammer */ - Node.prototype.clearSizeCache = function() { - this._reset(); - }; - /** - * Reset the calculated size of the node, forces it to recalculate its size - * @private + * @class Event + * @static */ - Node.prototype._reset = function() { - this.width = undefined; - this.height = undefined; - }; + var Event = Hammer.event = { + /** + * when touch events have been fired, this is true + * this is used to stop mouse events + * @property prevent_mouseevents + * @private + * @type {Boolean} + */ + preventMouseEvents: false, - /** - * get the title of this node. - * @return {string} title The title of the node, or undefined when no title - * has been set. - */ - Node.prototype.getTitle = function() { - return typeof this.title === "function" ? this.title() : this.title; - }; + /** + * if EVENT_START has been fired + * @property started + * @private + * @type {Boolean} + */ + started: false, - /** - * Calculate the distance to the border of the Node - * @param {CanvasRenderingContext2D} ctx - * @param {Number} angle Angle in radians - * @returns {number} distance Distance to the border in pixels - */ - Node.prototype.distanceToBorder = function (ctx, angle) { - var borderWidth = 1; + /** + * when the mouse is hold down, this is true + * @property should_detect + * @private + * @type {Boolean} + */ + shouldDetect: false, - if (!this.width) { - this.resize(ctx); - } + /** + * simple event binder with a hook and support for multiple types + * @method on + * @param {HTMLElement} element + * @param {String} type + * @param {Function} handler + * @param {Function} [hook] + * @param {Object} hook.type + */ + on: function on(element, type, handler, hook) { + var types = type.split(' '); + Utils.each(types, function(type) { + Utils.on(element, type, handler); + hook && hook(type); + }); + }, - switch (this.options.shape) { - case 'circle': - case 'dot': - return this.options.radius+ borderWidth; + /** + * simple event unbinder with a hook and support for multiple types + * @method off + * @param {HTMLElement} element + * @param {String} type + * @param {Function} handler + * @param {Function} [hook] + * @param {Object} hook.type + */ + off: function off(element, type, handler, hook) { + var types = type.split(' '); + Utils.each(types, function(type) { + Utils.off(element, type, handler); + hook && hook(type); + }); + }, - case 'ellipse': - var a = this.width / 2; - var b = this.height / 2; - var w = (Math.sin(angle) * a); - var h = (Math.cos(angle) * b); - return a * b / Math.sqrt(w * w + h * h); + /** + * the core touch event handler. + * this finds out if we should to detect gestures + * @method onTouch + * @param {HTMLElement} element + * @param {String} eventType matches `EVENT_START|MOVE|END` + * @param {Function} handler + * @return onTouchHandler {Function} the core event handler + */ + onTouch: function onTouch(element, eventType, handler) { + var self = this; - // TODO: implement distanceToBorder for database - // TODO: implement distanceToBorder for triangle - // TODO: implement distanceToBorder for triangleDown + var onTouchHandler = function onTouchHandler(ev) { + var srcType = ev.type.toLowerCase(), + isPointer = Hammer.HAS_POINTEREVENTS, + isMouse = Utils.inStr(srcType, 'mouse'), + triggerType; - case 'box': - case 'image': - case 'text': - default: - if (this.width) { - return Math.min( - Math.abs(this.width / 2 / Math.cos(angle)), - Math.abs(this.height / 2 / Math.sin(angle))) + borderWidth; - // TODO: reckon with border radius too in case of box - } - else { - return 0; - } + // if we are in a mouseevent, but there has been a touchevent triggered in this session + // we want to do nothing. simply break out of the event. + if(isMouse && self.preventMouseEvents) { + return; - } - // TODO: implement calculation of distance to border for all shapes - }; + // mousebutton must be down + } else if(isMouse && eventType == EVENT_START && ev.button === 0) { + self.preventMouseEvents = false; + self.shouldDetect = true; + } else if(isPointer && eventType == EVENT_START) { + self.shouldDetect = (ev.buttons === 1 || PointerEvent.matchType(POINTER_TOUCH, ev)); + // just a valid start event, but no mouse + } else if(!isMouse && eventType == EVENT_START) { + self.preventMouseEvents = true; + self.shouldDetect = true; + } - /** - * Set forces acting on the node - * @param {number} fx Force in horizontal direction - * @param {number} fy Force in vertical direction - */ - Node.prototype._setForce = function(fx, fy) { - this.fx = fx; - this.fy = fy; - }; + // update the pointer event before entering the detection + if(isPointer && eventType != EVENT_END) { + PointerEvent.updatePointer(eventType, ev); + } - /** - * Add forces acting on the node - * @param {number} fx Force in horizontal direction - * @param {number} fy Force in vertical direction - * @private - */ - Node.prototype._addForce = function(fx, fy) { - this.fx += fx; - this.fy += fy; - }; + // we are in a touch/down state, so allowed detection of gestures + if(self.shouldDetect) { + triggerType = self.doDetect.call(self, ev, eventType, element, handler); + } - /** - * Perform one discrete step for the node - * @param {number} interval Time interval in seconds - */ - Node.prototype.discreteStep = function(interval) { - if (!this.xFixed) { - var dx = this.damping * this.vx; // damping force - var ax = (this.fx - dx) / this.options.mass; // acceleration - this.vx += ax * interval; // velocity - this.x += this.vx * interval; // position - } + // ...and we are done with the detection + // so reset everything to start each detection totally fresh + if(triggerType == EVENT_END) { + self.preventMouseEvents = false; + self.shouldDetect = false; + PointerEvent.reset(); + // update the pointerevent object after the detection + } - if (!this.yFixed) { - var dy = this.damping * this.vy; // damping force - var ay = (this.fy - dy) / this.options.mass; // acceleration - this.vy += ay * interval; // velocity - this.y += this.vy * interval; // position - } - }; + if(isPointer && eventType == EVENT_END) { + PointerEvent.updatePointer(eventType, ev); + } + }; + this.on(element, EVENT_TYPES[eventType], onTouchHandler); + return onTouchHandler; + }, + /** + * the core detection method + * this finds out what hammer-touch-events to trigger + * @method doDetect + * @param {Object} ev + * @param {String} eventType matches `EVENT_START|MOVE|END` + * @param {HTMLElement} element + * @param {Function} handler + * @return {String} triggerType matches `EVENT_START|MOVE|END` + */ + doDetect: function doDetect(ev, eventType, element, handler) { + var touchList = this.getTouchList(ev, eventType); + var touchListLength = touchList.length; + var triggerType = eventType; + var triggerChange = touchList.trigger; // used by fakeMultitouch plugin + var changedLength = touchListLength; - /** - * Perform one discrete step for the node - * @param {number} interval Time interval in seconds - * @param {number} maxVelocity The speed limit imposed on the velocity - */ - Node.prototype.discreteStepLimited = function(interval, maxVelocity) { - if (!this.xFixed) { - var dx = this.damping * this.vx; // damping force - var ax = (this.fx - dx) / this.options.mass; // acceleration - this.vx += ax * interval; // velocity - this.vx = (Math.abs(this.vx) > maxVelocity) ? ((this.vx > 0) ? maxVelocity : -maxVelocity) : this.vx; - this.x += this.vx * interval; // position - } - else { - this.fx = 0; - } + // at each touchstart-like event we want also want to trigger a TOUCH event... + if(eventType == EVENT_START) { + triggerChange = EVENT_TOUCH; + // ...the same for a touchend-like event + } else if(eventType == EVENT_END) { + triggerChange = EVENT_RELEASE; - if (!this.yFixed) { - var dy = this.damping * this.vy; // damping force - var ay = (this.fy - dy) / this.options.mass; // acceleration - this.vy += ay * interval; // velocity - this.vy = (Math.abs(this.vy) > maxVelocity) ? ((this.vy > 0) ? maxVelocity : -maxVelocity) : this.vy; - this.y += this.vy * interval; // position - } - else { - this.fy = 0; - } - }; + // keep track of how many touches have been removed + changedLength = touchList.length - ((ev.changedTouches) ? ev.changedTouches.length : 1); + } - /** - * Check if this node has a fixed x and y position - * @return {boolean} true if fixed, false if not - */ - Node.prototype.isFixed = function() { - return (this.xFixed && this.yFixed); - }; + // after there are still touches on the screen, + // we just want to trigger a MOVE event. so change the START or END to a MOVE + // but only after detection has been started, the first time we actualy want a START + if(changedLength > 0 && this.started) { + triggerType = EVENT_MOVE; + } - /** - * Check if this node is moving - * @param {number} vmin the minimum velocity considered as "moving" - * @return {boolean} true if moving, false if it has no velocity - */ - // TODO: replace this method with calculating the kinetic energy - Node.prototype.isMoving = function(vmin) { - return (Math.abs(this.vx) > vmin || Math.abs(this.vy) > vmin); - }; + // detection has been started, we keep track of this, see above + this.started = true; - /** - * check if this node is selecte - * @return {boolean} selected True if node is selected, else false - */ - Node.prototype.isSelected = function() { - return this.selected; - }; + // generate some event data, some basic information + var evData = this.collectEventData(element, triggerType, touchList, ev); - /** - * Retrieve the value of the node. Can be undefined - * @return {Number} value - */ - Node.prototype.getValue = function() { - return this.value; - }; + // trigger the triggerType event before the change (TOUCH, RELEASE) events + // but the END event should be at last + if(eventType != EVENT_END) { + handler.call(Detection, evData); + } - /** - * Calculate the distance from the nodes location to the given location (x,y) - * @param {Number} x - * @param {Number} y - * @return {Number} value - */ - Node.prototype.getDistance = function(x, y) { - var dx = this.x - x, - dy = this.y - y; - return Math.sqrt(dx * dx + dy * dy); - }; + // trigger a change (TOUCH, RELEASE) event, this means the length of the touches changed + if(triggerChange) { + evData.changedLength = changedLength; + evData.eventType = triggerChange; + handler.call(Detection, evData); - /** - * Adjust the value range of the node. The node will adjust it's radius - * based on its value. - * @param {Number} min - * @param {Number} max - */ - Node.prototype.setValueRange = function(min, max) { - if (!this.radiusFixed && this.value !== undefined) { - if (max == min) { - this.options.radius= (this.options.radiusMin + this.options.radiusMax) / 2; - } - else { - var scale = (this.options.radiusMax - this.options.radiusMin) / (max - min); - this.options.radius= (this.value - min) * scale + this.options.radiusMin; - } - } - this.baseRadiusValue = this.options.radius; - }; + evData.eventType = triggerType; + delete evData.changedLength; + } - /** - * Draw this node in the given canvas - * The 2d context of a HTML canvas can be retrieved by canvas.getContext("2d"); - * @param {CanvasRenderingContext2D} ctx - */ - Node.prototype.draw = function(ctx) { - throw "Draw method not initialized for node"; - }; + // trigger the END event + if(triggerType == EVENT_END) { + handler.call(Detection, evData); - /** - * Recalculate the size of this node in the given canvas - * The 2d context of a HTML canvas can be retrieved by canvas.getContext("2d"); - * @param {CanvasRenderingContext2D} ctx - */ - Node.prototype.resize = function(ctx) { - throw "Resize method not initialized for node"; - }; + // ...and we are done with the detection + // so reset everything to start each detection totally fresh + this.started = false; + } - /** - * Check if this object is overlapping with the provided object - * @param {Object} obj an object with parameters left, top, right, bottom - * @return {boolean} True if location is located on node - */ - Node.prototype.isOverlappingWith = function(obj) { - return (this.left < obj.right && - this.left + this.width > obj.left && - this.top < obj.bottom && - this.top + this.height > obj.top); - }; + return triggerType; + }, - Node.prototype._resizeImage = function (ctx) { - // TODO: pre calculate the image size + /** + * we have different events for each device/browser + * determine what we need and set them in the EVENT_TYPES constant + * the `onTouch` method is bind to these properties. + * @method determineEventTypes + * @return {Object} events + */ + determineEventTypes: function determineEventTypes() { + var types; + if(Hammer.HAS_POINTEREVENTS) { + if(window.PointerEvent) { + types = [ + 'pointerdown', + 'pointermove', + 'pointerup pointercancel lostpointercapture' + ]; + } else { + types = [ + 'MSPointerDown', + 'MSPointerMove', + 'MSPointerUp MSPointerCancel MSLostPointerCapture' + ]; + } + } else if(Hammer.NO_MOUSEEVENTS) { + types = [ + 'touchstart', + 'touchmove', + 'touchend touchcancel' + ]; + } else { + types = [ + 'touchstart mousedown', + 'touchmove mousemove', + 'touchend touchcancel mouseup' + ]; + } - if (!this.width || !this.height) { // undefined or 0 - var width, height; - if (this.value) { - this.options.radius= this.baseRadiusValue; - var scale = this.imageObj.height / this.imageObj.width; - if (scale !== undefined) { - width = this.options.radius|| this.imageObj.width; - height = this.options.radius* scale || this.imageObj.height; - } - else { - width = 0; - height = 0; - } - } - else { - width = this.imageObj.width; - height = this.imageObj.height; - } - this.width = width; - this.height = height; + EVENT_TYPES[EVENT_START] = types[0]; + EVENT_TYPES[EVENT_MOVE] = types[1]; + EVENT_TYPES[EVENT_END] = types[2]; + return EVENT_TYPES; + }, - this.growthIndicator = 0; - if (this.width > 0 && this.height > 0) { - this.width += Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * this.clusterSizeWidthFactor; - this.height += Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * this.clusterSizeHeightFactor; - this.options.radius+= Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * this.clusterSizeRadiusFactor; - this.growthIndicator = this.width - width; - } - } + /** + * create touchList depending on the event + * @method getTouchList + * @param {Object} ev + * @param {String} eventType + * @return {Array} touches + */ + getTouchList: function getTouchList(ev, eventType) { + // get the fake pointerEvent touchlist + if(Hammer.HAS_POINTEREVENTS) { + return PointerEvent.getTouchList(); + } - }; + // get the touchlist + if(ev.touches) { + if(eventType == EVENT_MOVE) { + return ev.touches; + } - Node.prototype._drawImage = function (ctx) { - this._resizeImage(ctx); + var identifiers = []; + var concat = [].concat(Utils.toArray(ev.touches), Utils.toArray(ev.changedTouches)); + var touchList = []; - this.left = this.x - this.width / 2; - this.top = this.y - this.height / 2; + Utils.each(concat, function(touch) { + if(Utils.inArray(identifiers, touch.identifier) === false) { + touchList.push(touch); + } + identifiers.push(touch.identifier); + }); + + return touchList; + } + + // make fake touchList from mouse position + ev.identifier = 1; + return [ev]; + }, + + /** + * collect basic event data + * @method collectEventData + * @param {HTMLElement} element + * @param {String} eventType matches `EVENT_START|MOVE|END` + * @param {Array} touches + * @param {Object} ev + * @return {Object} ev + */ + collectEventData: function collectEventData(element, eventType, touches, ev) { + // find out pointerType + var pointerType = POINTER_TOUCH; + if(Utils.inStr(ev.type, 'mouse') || PointerEvent.matchType(POINTER_MOUSE, ev)) { + pointerType = POINTER_MOUSE; + } else if(PointerEvent.matchType(POINTER_PEN, ev)) { + pointerType = POINTER_PEN; + } - var yLabel; - if (this.imageObj.width != 0 ) { - // draw the shade - if (this.clusterSize > 1) { - var lineWidth = ((this.clusterSize > 1) ? 10 : 0.0); - lineWidth *= this.networkScaleInv; - lineWidth = Math.min(0.2 * this.width,lineWidth); + return { + center: Utils.getCenter(touches), + timeStamp: Date.now(), + target: ev.target, + touches: touches, + eventType: eventType, + pointerType: pointerType, + srcEvent: ev, - ctx.globalAlpha = 0.5; - ctx.drawImage(this.imageObj, this.left - lineWidth, this.top - lineWidth, this.width + 2*lineWidth, this.height + 2*lineWidth); - } + /** + * prevent the browser default actions + * mostly used to disable scrolling of the browser + */ + preventDefault: function() { + var srcEvent = this.srcEvent; + srcEvent.preventManipulation && srcEvent.preventManipulation(); + srcEvent.preventDefault && srcEvent.preventDefault(); + }, - // draw the image - ctx.globalAlpha = 1.0; - ctx.drawImage(this.imageObj, this.left, this.top, this.width, this.height); - yLabel = this.y + this.height / 2; - } - else { - // image still loading... just draw the label for now - yLabel = this.y; - } + /** + * stop bubbling the event up to its parents + */ + stopPropagation: function() { + this.srcEvent.stopPropagation(); + }, - this._label(ctx, this.label, this.x, yLabel, undefined, "top"); + /** + * immediately stop gesture detection + * might be useful after a swipe was detected + * @return {*} + */ + stopDetect: function() { + return Detection.stopDetect(); + } + }; + } }; - Node.prototype._resizeBox = function (ctx) { - if (!this.width) { - var margin = 5; - var textSize = this.getTextSize(ctx); - this.width = textSize.width + 2 * margin; - this.height = textSize.height + 2 * margin; - - this.width += Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * 0.5 * this.clusterSizeWidthFactor; - this.height += Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * 0.5 * this.clusterSizeHeightFactor; - this.growthIndicator = this.width - (textSize.width + 2 * margin); - // this.options.radius+= Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * 0.5 * this.clusterSizeRadiusFactor; - - } - }; + /** + * @module hammer + * + * @class PointerEvent + * @static + */ + var PointerEvent = Hammer.PointerEvent = { + /** + * holds all pointers, by `identifier` + * @property pointers + * @type {Object} + */ + pointers: {}, - Node.prototype._drawBox = function (ctx) { - this._resizeBox(ctx); + /** + * get the pointers as an array + * @method getTouchList + * @return {Array} touchlist + */ + getTouchList: function getTouchList() { + var touchlist = []; + // we can use forEach since pointerEvents only is in IE10 + Utils.each(this.pointers, function(pointer) { + touchlist.push(pointer); + }); + return touchlist; + }, - this.left = this.x - this.width / 2; - this.top = this.y - this.height / 2; + /** + * update the position of a pointer + * @method updatePointer + * @param {String} eventType matches `EVENT_START|MOVE|END` + * @param {Object} pointerEvent + */ + updatePointer: function updatePointer(eventType, pointerEvent) { + if(eventType == EVENT_END || (eventType != EVENT_END && pointerEvent.buttons !== 1)) { + delete this.pointers[pointerEvent.pointerId]; + } else { + pointerEvent.identifier = pointerEvent.pointerId; + this.pointers[pointerEvent.pointerId] = pointerEvent; + } + }, - var clusterLineWidth = 2.5; - var borderWidth = this.options.borderWidth; - var selectionLineWidth = this.options.borderWidthSelected || 2 * this.options.borderWidth; + /** + * check if ev matches pointertype + * @method matchType + * @param {String} pointerType matches `POINTER_MOUSE|TOUCH|PEN` + * @param {PointerEvent} ev + */ + matchType: function matchType(pointerType, ev) { + if(!ev.pointerType) { + return false; + } - ctx.strokeStyle = this.selected ? this.options.color.highlight.border : this.hover ? this.options.color.hover.border : this.options.color.border; + var pt = ev.pointerType, + types = {}; - // draw the outer border - if (this.clusterSize > 1) { - ctx.lineWidth = (this.selected ? selectionLineWidth : borderWidth) + ((this.clusterSize > 1) ? clusterLineWidth : 0.0); - ctx.lineWidth *= this.networkScaleInv; - ctx.lineWidth = Math.min(this.width,ctx.lineWidth); + types[POINTER_MOUSE] = (pt === (ev.MSPOINTER_TYPE_MOUSE || POINTER_MOUSE)); + types[POINTER_TOUCH] = (pt === (ev.MSPOINTER_TYPE_TOUCH || POINTER_TOUCH)); + types[POINTER_PEN] = (pt === (ev.MSPOINTER_TYPE_PEN || POINTER_PEN)); + return types[pointerType]; + }, - ctx.roundRect(this.left-2*ctx.lineWidth, this.top-2*ctx.lineWidth, this.width+4*ctx.lineWidth, this.height+4*ctx.lineWidth, this.options.radius); - ctx.stroke(); - } - ctx.lineWidth = (this.selected ? selectionLineWidth : borderWidth) + ((this.clusterSize > 1) ? clusterLineWidth : 0.0); - ctx.lineWidth *= this.networkScaleInv; - ctx.lineWidth = Math.min(this.width,ctx.lineWidth); + /** + * reset the stored pointers + * @method reset + */ + reset: function resetList() { + this.pointers = {}; + } + }; - ctx.fillStyle = this.selected ? this.options.color.highlight.background : this.options.color.background; - ctx.roundRect(this.left, this.top, this.width, this.height, this.options.radius); - ctx.fill(); - ctx.stroke(); + /** + * @module hammer + * + * @class Detection + * @static + */ + var Detection = Hammer.detection = { + // contains all registred Hammer.gestures in the correct order + gestures: [], - this._label(ctx, this.label, this.x, this.y); - }; + // data of the current Hammer.gesture detection session + current: null, + // the previous Hammer.gesture session data + // is a full clone of the previous gesture.current object + previous: null, - Node.prototype._resizeDatabase = function (ctx) { - if (!this.width) { - var margin = 5; - var textSize = this.getTextSize(ctx); - var size = textSize.width + 2 * margin; - this.width = size; - this.height = size; + // when this becomes true, no gestures are fired + stopped: false, - // scaling used for clustering - this.width += Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * this.clusterSizeWidthFactor; - this.height += Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * this.clusterSizeHeightFactor; - this.options.radius+= Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * this.clusterSizeRadiusFactor; - this.growthIndicator = this.width - size; - } - }; + /** + * start Hammer.gesture detection + * @method startDetect + * @param {Hammer.Instance} inst + * @param {Object} eventData + */ + startDetect: function startDetect(inst, eventData) { + // already busy with a Hammer.gesture detection on an element + if(this.current) { + return; + } - Node.prototype._drawDatabase = function (ctx) { - this._resizeDatabase(ctx); - this.left = this.x - this.width / 2; - this.top = this.y - this.height / 2; + this.stopped = false; - var clusterLineWidth = 2.5; - var borderWidth = this.options.borderWidth; - var selectionLineWidth = this.options.borderWidthSelected || 2 * this.options.borderWidth; + // holds current session + this.current = { + inst: inst, // reference to HammerInstance we're working for + startEvent: Utils.extend({}, eventData), // start eventData for distances, timing etc + lastEvent: false, // last eventData + lastCalcEvent: false, // last eventData for calculations. + futureCalcEvent: false, // last eventData for calculations. + lastCalcData: {}, // last lastCalcData + name: '' // current gesture we're in/detected, can be 'tap', 'hold' etc + }; - ctx.strokeStyle = this.selected ? this.options.color.highlight.border : this.hover ? this.options.color.hover.border : this.options.color.border; + this.detect(eventData); + }, - // draw the outer border - if (this.clusterSize > 1) { - ctx.lineWidth = (this.selected ? selectionLineWidth : borderWidth) + ((this.clusterSize > 1) ? clusterLineWidth : 0.0); - ctx.lineWidth *= this.networkScaleInv; - ctx.lineWidth = Math.min(this.width,ctx.lineWidth); + /** + * Hammer.gesture detection + * @method detect + * @param {Object} eventData + * @return {any} + */ + detect: function detect(eventData) { + if(!this.current || this.stopped) { + return; + } - ctx.database(this.x - this.width/2 - 2*ctx.lineWidth, this.y - this.height*0.5 - 2*ctx.lineWidth, this.width + 4*ctx.lineWidth, this.height + 4*ctx.lineWidth); - ctx.stroke(); - } - ctx.lineWidth = (this.selected ? selectionLineWidth : borderWidth) + ((this.clusterSize > 1) ? clusterLineWidth : 0.0); - ctx.lineWidth *= this.networkScaleInv; - ctx.lineWidth = Math.min(this.width,ctx.lineWidth); + // extend event data with calculations about scale, distance etc + eventData = this.extendEventData(eventData); - ctx.fillStyle = this.selected ? this.options.color.highlight.background : this.hover ? this.options.color.hover.background : this.options.color.background; - ctx.database(this.x - this.width/2, this.y - this.height*0.5, this.width, this.height); - ctx.fill(); - ctx.stroke(); + // hammer instance and instance options + var inst = this.current.inst, + instOptions = inst.options; - this._label(ctx, this.label, this.x, this.y); - }; + // call Hammer.gesture handlers + Utils.each(this.gestures, function triggerGesture(gesture) { + // only when the instance options have enabled this gesture + if(!this.stopped && inst.enabled && instOptions[gesture.name]) { + gesture.handler.call(gesture, eventData, inst); + } + }, this); + // store as previous event event + if(this.current) { + this.current.lastEvent = eventData; + } - Node.prototype._resizeCircle = function (ctx) { - if (!this.width) { - var margin = 5; - var textSize = this.getTextSize(ctx); - var diameter = Math.max(textSize.width, textSize.height) + 2 * margin; - this.options.radius = diameter / 2; + if(eventData.eventType == EVENT_END) { + this.stopDetect(); + } - this.width = diameter; - this.height = diameter; + return eventData; + }, - // scaling used for clustering - // this.width += Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * 0.5 * this.clusterSizeWidthFactor; - // this.height += Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * 0.5 * this.clusterSizeHeightFactor; - this.options.radius += Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * 0.5 * this.clusterSizeRadiusFactor; - this.growthIndicator = this.options.radius- 0.5*diameter; - } - }; + /** + * clear the Hammer.gesture vars + * this is called on endDetect, but can also be used when a final Hammer.gesture has been detected + * to stop other Hammer.gestures from being fired + * @method stopDetect + */ + stopDetect: function stopDetect() { + // clone current data to the store as the previous gesture + // used for the double tap gesture, since this is an other gesture detect session + this.previous = Utils.extend({}, this.current); - Node.prototype._drawCircle = function (ctx) { - this._resizeCircle(ctx); - this.left = this.x - this.width / 2; - this.top = this.y - this.height / 2; + // reset the current + this.current = null; + this.stopped = true; + }, - var clusterLineWidth = 2.5; - var borderWidth = this.options.borderWidth; - var selectionLineWidth = this.options.borderWidthSelected || 2 * this.options.borderWidth; + /** + * calculate velocity, angle and direction + * @method getVelocityData + * @param {Object} ev + * @param {Object} center + * @param {Number} deltaTime + * @param {Number} deltaX + * @param {Number} deltaY + */ + getCalculatedData: function getCalculatedData(ev, center, deltaTime, deltaX, deltaY) { + var cur = this.current, + recalc = false, + calcEv = cur.lastCalcEvent, + calcData = cur.lastCalcData; - ctx.strokeStyle = this.selected ? this.options.color.highlight.border : this.hover ? this.options.color.hover.border : this.options.color.border; + if(calcEv && ev.timeStamp - calcEv.timeStamp > Hammer.CALCULATE_INTERVAL) { + center = calcEv.center; + deltaTime = ev.timeStamp - calcEv.timeStamp; + deltaX = ev.center.clientX - calcEv.center.clientX; + deltaY = ev.center.clientY - calcEv.center.clientY; + recalc = true; + } - // draw the outer border - if (this.clusterSize > 1) { - ctx.lineWidth = (this.selected ? selectionLineWidth : borderWidth) + ((this.clusterSize > 1) ? clusterLineWidth : 0.0); - ctx.lineWidth *= this.networkScaleInv; - ctx.lineWidth = Math.min(this.width,ctx.lineWidth); + if(ev.eventType == EVENT_TOUCH || ev.eventType == EVENT_RELEASE) { + cur.futureCalcEvent = ev; + } - ctx.circle(this.x, this.y, this.options.radius+2*ctx.lineWidth); - ctx.stroke(); - } - ctx.lineWidth = (this.selected ? selectionLineWidth : borderWidth) + ((this.clusterSize > 1) ? clusterLineWidth : 0.0); - ctx.lineWidth *= this.networkScaleInv; - ctx.lineWidth = Math.min(this.width,ctx.lineWidth); + if(!cur.lastCalcEvent || recalc) { + calcData.velocity = Utils.getVelocity(deltaTime, deltaX, deltaY); + calcData.angle = Utils.getAngle(center, ev.center); + calcData.direction = Utils.getDirection(center, ev.center); - ctx.fillStyle = this.selected ? this.options.color.highlight.background : this.hover ? this.options.color.hover.background : this.options.color.background; - ctx.circle(this.x, this.y, this.options.radius); - ctx.fill(); - ctx.stroke(); + cur.lastCalcEvent = cur.futureCalcEvent || ev; + cur.futureCalcEvent = ev; + } - this._label(ctx, this.label, this.x, this.y); - }; + ev.velocityX = calcData.velocity.x; + ev.velocityY = calcData.velocity.y; + ev.interimAngle = calcData.angle; + ev.interimDirection = calcData.direction; + }, - Node.prototype._resizeEllipse = function (ctx) { - if (!this.width) { - var textSize = this.getTextSize(ctx); + /** + * extend eventData for Hammer.gestures + * @method extendEventData + * @param {Object} ev + * @return {Object} ev + */ + extendEventData: function extendEventData(ev) { + var cur = this.current, + startEv = cur.startEvent, + lastEv = cur.lastEvent || startEv; - this.width = textSize.width * 1.5; - this.height = textSize.height * 2; - if (this.width < this.height) { - this.width = this.height; - } - var defaultSize = this.width; + // update the start touchlist to calculate the scale/rotation + if(ev.eventType == EVENT_TOUCH || ev.eventType == EVENT_RELEASE) { + startEv.touches = []; + Utils.each(ev.touches, function(touch) { + startEv.touches.push({ + clientX: touch.clientX, + clientY: touch.clientY + }); + }); + } - // scaling used for clustering - this.width += Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * this.clusterSizeWidthFactor; - this.height += Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * this.clusterSizeHeightFactor; - this.options.radius += Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * this.clusterSizeRadiusFactor; - this.growthIndicator = this.width - defaultSize; - } - }; + var deltaTime = ev.timeStamp - startEv.timeStamp, + deltaX = ev.center.clientX - startEv.center.clientX, + deltaY = ev.center.clientY - startEv.center.clientY; - Node.prototype._drawEllipse = function (ctx) { - this._resizeEllipse(ctx); - this.left = this.x - this.width / 2; - this.top = this.y - this.height / 2; + this.getCalculatedData(ev, lastEv.center, deltaTime, deltaX, deltaY); - var clusterLineWidth = 2.5; - var borderWidth = this.options.borderWidth; - var selectionLineWidth = this.options.borderWidthSelected || 2 * this.options.borderWidth; + Utils.extend(ev, { + startEvent: startEv, - ctx.strokeStyle = this.selected ? this.options.color.highlight.border : this.hover ? this.options.color.hover.border : this.options.color.border; + deltaTime: deltaTime, + deltaX: deltaX, + deltaY: deltaY, - // draw the outer border - if (this.clusterSize > 1) { - ctx.lineWidth = (this.selected ? selectionLineWidth : borderWidth) + ((this.clusterSize > 1) ? clusterLineWidth : 0.0); - ctx.lineWidth *= this.networkScaleInv; - ctx.lineWidth = Math.min(this.width,ctx.lineWidth); + distance: Utils.getDistance(startEv.center, ev.center), + angle: Utils.getAngle(startEv.center, ev.center), + direction: Utils.getDirection(startEv.center, ev.center), + scale: Utils.getScale(startEv.touches, ev.touches), + rotation: Utils.getRotation(startEv.touches, ev.touches) + }); - ctx.ellipse(this.left-2*ctx.lineWidth, this.top-2*ctx.lineWidth, this.width+4*ctx.lineWidth, this.height+4*ctx.lineWidth); - ctx.stroke(); - } - ctx.lineWidth = (this.selected ? selectionLineWidth : borderWidth) + ((this.clusterSize > 1) ? clusterLineWidth : 0.0); - ctx.lineWidth *= this.networkScaleInv; - ctx.lineWidth = Math.min(this.width,ctx.lineWidth); + return ev; + }, - ctx.fillStyle = this.selected ? this.options.color.highlight.background : this.hover ? this.options.color.hover.background : this.options.color.background; + /** + * register new gesture + * @method register + * @param {Object} gesture object, see `gestures/` for documentation + * @return {Array} gestures + */ + register: function register(gesture) { + // add an enable gesture options if there is no given + var options = gesture.defaults || {}; + if(options[gesture.name] === undefined) { + options[gesture.name] = true; + } - ctx.ellipse(this.left, this.top, this.width, this.height); - ctx.fill(); - ctx.stroke(); - this._label(ctx, this.label, this.x, this.y); - }; + // extend Hammer default options with the Hammer.gesture options + Utils.extend(Hammer.defaults, options, true); - Node.prototype._drawDot = function (ctx) { - this._drawShape(ctx, 'circle'); - }; + // set its index + gesture.index = gesture.index || 1000; - Node.prototype._drawTriangle = function (ctx) { - this._drawShape(ctx, 'triangle'); - }; + // add Hammer.gesture to the list + this.gestures.push(gesture); - Node.prototype._drawTriangleDown = function (ctx) { - this._drawShape(ctx, 'triangleDown'); - }; + // sort the list by index + this.gestures.sort(function(a, b) { + if(a.index < b.index) { + return -1; + } + if(a.index > b.index) { + return 1; + } + return 0; + }); - Node.prototype._drawSquare = function (ctx) { - this._drawShape(ctx, 'square'); + return this.gestures; + } }; - Node.prototype._drawStar = function (ctx) { - this._drawShape(ctx, 'star'); - }; - Node.prototype._resizeShape = function (ctx) { - if (!this.width) { - this.options.radius= this.baseRadiusValue; - var size = 2 * this.options.radius; - this.width = size; - this.height = size; + /** + * @module hammer + */ - // scaling used for clustering - this.width += Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * this.clusterSizeWidthFactor; - this.height += Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * this.clusterSizeHeightFactor; - this.options.radius+= Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * 0.5 * this.clusterSizeRadiusFactor; - this.growthIndicator = this.width - size; - } - }; + /** + * create new hammer instance + * all methods should return the instance itself, so it is chainable. + * + * @class Instance + * @constructor + * @param {HTMLElement} element + * @param {Object} [options={}] options are merged with `Hammer.defaults` + * @return {Hammer.Instance} + */ + Hammer.Instance = function(element, options) { + var self = this; - Node.prototype._drawShape = function (ctx, shape) { - this._resizeShape(ctx); + // setup HammerJS window events and register all gestures + // this also sets up the default options + setup(); - this.left = this.x - this.width / 2; - this.top = this.y - this.height / 2; + /** + * @property element + * @type {HTMLElement} + */ + this.element = element; - var clusterLineWidth = 2.5; - var borderWidth = this.options.borderWidth; - var selectionLineWidth = this.options.borderWidthSelected || 2 * this.options.borderWidth; - var radiusMultiplier = 2; + /** + * @property enabled + * @type {Boolean} + * @protected + */ + this.enabled = true; - // choose draw method depending on the shape - switch (shape) { - case 'dot': radiusMultiplier = 2; break; - case 'square': radiusMultiplier = 2; break; - case 'triangle': radiusMultiplier = 3; break; - case 'triangleDown': radiusMultiplier = 3; break; - case 'star': radiusMultiplier = 4; break; - } + /** + * options, merged with the defaults + * options with an _ are converted to camelCase + * @property options + * @type {Object} + */ + Utils.each(options, function(value, name) { + delete options[name]; + options[Utils.toCamelCase(name)] = value; + }); - ctx.strokeStyle = this.selected ? this.options.color.highlight.border : this.hover ? this.options.color.hover.border : this.options.color.border; - // draw the outer border - if (this.clusterSize > 1) { - ctx.lineWidth = (this.selected ? selectionLineWidth : borderWidth) + ((this.clusterSize > 1) ? clusterLineWidth : 0.0); - ctx.lineWidth *= this.networkScaleInv; - ctx.lineWidth = Math.min(this.width,ctx.lineWidth); + this.options = Utils.extend(Utils.extend({}, Hammer.defaults), options || {}); - ctx[shape](this.x, this.y, this.options.radius+ radiusMultiplier * ctx.lineWidth); - ctx.stroke(); - } - ctx.lineWidth = (this.selected ? selectionLineWidth : borderWidth) + ((this.clusterSize > 1) ? clusterLineWidth : 0.0); - ctx.lineWidth *= this.networkScaleInv; - ctx.lineWidth = Math.min(this.width,ctx.lineWidth); + // add some css to the element to prevent the browser from doing its native behavoir + if(this.options.behavior) { + Utils.toggleBehavior(this.element, this.options.behavior, true); + } - ctx.fillStyle = this.selected ? this.options.color.highlight.background : this.hover ? this.options.color.hover.background : this.options.color.background; - ctx[shape](this.x, this.y, this.options.radius); - ctx.fill(); - ctx.stroke(); + /** + * event start handler on the element to start the detection + * @property eventStartHandler + * @type {Object} + */ + this.eventStartHandler = Event.onTouch(element, EVENT_START, function(ev) { + if(self.enabled && ev.eventType == EVENT_START) { + Detection.startDetect(self, ev); + } else if(ev.eventType == EVENT_TOUCH) { + Detection.detect(ev); + } + }); - if (this.label) { - this._label(ctx, this.label, this.x, this.y + this.height / 2, undefined, 'top',true); - } + /** + * keep a list of user event handlers which needs to be removed when calling 'dispose' + * @property eventHandlers + * @type {Array} + */ + this.eventHandlers = []; }; - Node.prototype._resizeText = function (ctx) { - if (!this.width) { - var margin = 5; - var textSize = this.getTextSize(ctx); - this.width = textSize.width + 2 * margin; - this.height = textSize.height + 2 * margin; + Hammer.Instance.prototype = { + /** + * bind events to the instance + * @method on + * @chainable + * @param {String} gestures multiple gestures by splitting with a space + * @param {Function} handler + * @param {Object} handler.ev event object + */ + on: function onEvent(gestures, handler) { + var self = this; + Event.on(self.element, gestures, handler, function(type) { + self.eventHandlers.push({ gesture: type, handler: handler }); + }); + return self; + }, - // scaling used for clustering - this.width += Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * this.clusterSizeWidthFactor; - this.height += Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * this.clusterSizeHeightFactor; - this.options.radius+= Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * this.clusterSizeRadiusFactor; - this.growthIndicator = this.width - (textSize.width + 2 * margin); - } - }; + /** + * unbind events to the instance + * @method off + * @chainable + * @param {String} gestures + * @param {Function} handler + */ + off: function offEvent(gestures, handler) { + var self = this; - Node.prototype._drawText = function (ctx) { - this._resizeText(ctx); - this.left = this.x - this.width / 2; - this.top = this.y - this.height / 2; + Event.off(self.element, gestures, handler, function(type) { + var index = Utils.inArray({ gesture: type, handler: handler }); + if(index !== false) { + self.eventHandlers.splice(index, 1); + } + }); + return self; + }, - this._label(ctx, this.label, this.x, this.y); - }; + /** + * trigger gesture event + * @method trigger + * @chainable + * @param {String} gesture + * @param {Object} [eventData] + */ + trigger: function triggerEvent(gesture, eventData) { + // optional + if(!eventData) { + eventData = {}; + } + // create DOM event + var event = Hammer.DOCUMENT.createEvent('Event'); + event.initEvent(gesture, true, true); + event.gesture = eventData; - Node.prototype._label = function (ctx, text, x, y, align, baseline, labelUnderNode) { - if (text && Number(this.options.fontSize) * this.networkScale > this.fontDrawThreshold) { - ctx.font = (this.selected ? "bold " : "") + this.options.fontSize + "px " + this.options.fontFace; - ctx.fillStyle = this.options.fontColor || "black"; - ctx.textAlign = align || "center"; - ctx.textBaseline = baseline || "middle"; + // trigger on the target if it is in the instance element, + // this is for event delegation tricks + var element = this.element; + if(Utils.hasParent(eventData.target, element)) { + element = eventData.target; + } - var lines = text.split('\n'); - var lineCount = lines.length; - var fontSize = (Number(this.options.fontSize) + 4); - var yLine = y + (1 - lineCount) / 2 * fontSize; - if (labelUnderNode == true) { - yLine = y + (1 - lineCount) / (2 * fontSize); - } + element.dispatchEvent(event); + return this; + }, - for (var i = 0; i < lineCount; i++) { - ctx.fillText(lines[i], x, yLine); - yLine += fontSize; - } - } - }; + /** + * enable of disable hammer.js detection + * @method enable + * @chainable + * @param {Boolean} state + */ + enable: function enable(state) { + this.enabled = state; + return this; + }, + + /** + * dispose this hammer instance + * @method dispose + * @return {Null} + */ + dispose: function dispose() { + var i, eh; + // undo all changes made by stop_browser_behavior + Utils.toggleBehavior(this.element, this.options.behavior, false); - Node.prototype.getTextSize = function(ctx) { - if (this.label !== undefined) { - ctx.font = (this.selected ? "bold " : "") + this.options.fontSize + "px " + this.options.fontFace; + // unbind all custom event handlers + for(i = -1; (eh = this.eventHandlers[++i]);) { + Utils.off(this.element, eh.gesture, eh.handler); + } - var lines = this.label.split('\n'), - height = (Number(this.options.fontSize) + 4) * lines.length, - width = 0; + this.eventHandlers = []; - for (var i = 0, iMax = lines.length; i < iMax; i++) { - width = Math.max(width, ctx.measureText(lines[i]).width); - } + // unbind the start event listener + Event.off(this.element, EVENT_TYPES[EVENT_START], this.eventStartHandler); - return {"width": width, "height": height}; - } - else { - return {"width": 0, "height": 0}; - } + return null; + } }; + /** - * this is used to determine if a node is visible at all. this is used to determine when it needs to be drawn. - * there is a safety margin of 0.3 * width; + * @module gestures + */ + /** + * Move with x fingers (default 1) around on the page. + * Preventing the default browser behavior is a good way to improve feel and working. + * ```` + * hammertime.on("drag", function(ev) { + * console.log(ev); + * ev.gesture.preventDefault(); + * }); + * ```` * - * @returns {boolean} + * @class Drag + * @static */ - Node.prototype.inArea = function() { - if (this.width !== undefined) { - return (this.x + this.width *this.networkScaleInv >= this.canvasTopLeft.x && - this.x - this.width *this.networkScaleInv < this.canvasBottomRight.x && - this.y + this.height*this.networkScaleInv >= this.canvasTopLeft.y && - this.y - this.height*this.networkScaleInv < this.canvasBottomRight.y); - } - else { - return true; - } - }; - /** - * checks if the core of the node is in the display area, this is used for opening clusters around zoom - * @returns {boolean} + * @event drag + * @param {Object} ev + */ + /** + * @event dragstart + * @param {Object} ev + */ + /** + * @event dragend + * @param {Object} ev */ - Node.prototype.inView = function() { - return (this.x >= this.canvasTopLeft.x && - this.x < this.canvasBottomRight.x && - this.y >= this.canvasTopLeft.y && - this.y < this.canvasBottomRight.y); - }; - /** - * This allows the zoom level of the network to influence the rendering - * We store the inverted scale and the coordinates of the top left, and bottom right points of the canvas - * - * @param scale - * @param canvasTopLeft - * @param canvasBottomRight + * @event drapleft + * @param {Object} ev */ - Node.prototype.setScaleAndPos = function(scale,canvasTopLeft,canvasBottomRight) { - this.networkScaleInv = 1.0/scale; - this.networkScale = scale; - this.canvasTopLeft = canvasTopLeft; - this.canvasBottomRight = canvasBottomRight; - }; - - /** - * This allows the zoom level of the network to influence the rendering - * - * @param scale + * @event dragright + * @param {Object} ev */ - Node.prototype.setScale = function(scale) { - this.networkScaleInv = 1.0/scale; - this.networkScale = scale; - }; - - - /** - * set the velocity at 0. Is called when this node is contained in another during clustering + * @event dragup + * @param {Object} ev */ - Node.prototype.clearVelocity = function() { - this.vx = 0; - this.vy = 0; - }; - - /** - * Basic preservation of (kinectic) energy - * - * @param massBeforeClustering + * @event dragdown + * @param {Object} ev */ - Node.prototype.updateVelocity = function(massBeforeClustering) { - var energyBefore = this.vx * this.vx * massBeforeClustering; - //this.vx = (this.vx < 0) ? -Math.sqrt(energyBefore/this.options.mass) : Math.sqrt(energyBefore/this.options.mass); - this.vx = Math.sqrt(energyBefore/this.options.mass); - energyBefore = this.vy * this.vy * massBeforeClustering; - //this.vy = (this.vy < 0) ? -Math.sqrt(energyBefore/this.options.mass) : Math.sqrt(energyBefore/this.options.mass); - this.vy = Math.sqrt(energyBefore/this.options.mass); - }; - - module.exports = Node; - - -/***/ }, -/* 48 */ -/***/ function(module, exports, __webpack_require__) { - - var util = __webpack_require__(1); - var Node = __webpack_require__(47); /** - * @class Edge - * - * A edge connects two nodes - * @param {Object} properties Object with properties. Must contain - * At least properties from and to. - * Available properties: from (number), - * to (number), label (string, color (string), - * width (number), style (string), - * length (number), title (string) - * @param {Network} network A Network object, used to find and edge to - * nodes. - * @param {Object} constants An object with default values for - * example for the color + * @param {String} name */ - function Edge (properties, network, networkConstants) { - if (!network) { - throw "No network provided"; - } - var fields = ['edges','physics']; - var constants = util.selectiveBridgeObject(fields,networkConstants); - this.options = constants.edges; - this.physics = constants.physics; - this.options['smoothCurves'] = networkConstants['smoothCurves']; + (function(name) { + var triggered = false; + function dragGesture(ev, inst) { + var cur = Detection.current; - this.network = network; + // max touches + if(inst.options.dragMaxTouches > 0 && + ev.touches.length > inst.options.dragMaxTouches) { + return; + } - // initialize variables - this.id = undefined; - this.fromId = undefined; - this.toId = undefined; - this.title = undefined; - this.widthSelected = this.options.width * this.options.widthSelectionMultiplier; - this.value = undefined; - this.selected = false; - this.hover = false; + switch(ev.eventType) { + case EVENT_START: + triggered = false; + break; - this.from = null; // a node - this.to = null; // a node - this.via = null; // a temp node + case EVENT_MOVE: + // when the distance we moved is too small we skip this gesture + // or we can be already in dragging + if(ev.distance < inst.options.dragMinDistance && + cur.name != name) { + return; + } - // we use this to be able to reconnect the edge to a cluster if its node is put into a cluster - // by storing the original information we can revert to the original connection when the cluser is opened. - this.originalFromId = []; - this.originalToId = []; + var startCenter = cur.startEvent.center; - this.connected = false; + // we are dragging! + if(cur.name != name) { + cur.name = name; + if(inst.options.dragDistanceCorrection && ev.distance > 0) { + // When a drag is triggered, set the event center to dragMinDistance pixels from the original event center. + // Without this correction, the dragged distance would jumpstart at dragMinDistance pixels instead of at 0. + // It might be useful to save the original start point somewhere + var factor = Math.abs(inst.options.dragMinDistance / ev.distance); + startCenter.pageX += ev.deltaX * factor; + startCenter.pageY += ev.deltaY * factor; + startCenter.clientX += ev.deltaX * factor; + startCenter.clientY += ev.deltaY * factor; - this.widthFixed = false; - this.lengthFixed = false; + // recalculate event data using new start point + ev = Detection.extendEventData(ev); + } + } - this.setProperties(properties); + // lock drag to axis? + if(cur.lastEvent.dragLockToAxis || + ( inst.options.dragLockToAxis && + inst.options.dragLockMinDistance <= ev.distance + )) { + ev.dragLockToAxis = true; + } - this.controlNodesEnabled = false; - this.controlNodes = {from:null, to:null, positions:{}}; - this.connectedNode = null; - } + // keep direction on the axis that the drag gesture started on + var lastDirection = cur.lastEvent.direction; + if(ev.dragLockToAxis && lastDirection !== ev.direction) { + if(Utils.isVertical(lastDirection)) { + ev.direction = (ev.deltaY < 0) ? DIRECTION_UP : DIRECTION_DOWN; + } else { + ev.direction = (ev.deltaX < 0) ? DIRECTION_LEFT : DIRECTION_RIGHT; + } + } - /** - * Set or overwrite properties for the edge - * @param {Object} properties an object with properties - * @param {Object} constants and object with default, global properties - */ - Edge.prototype.setProperties = function(properties) { - if (!properties) { - return; - } + // first time, trigger dragstart event + if(!triggered) { + inst.trigger(name + 'start', ev); + triggered = true; + } - var fields = ['style','fontSize','fontFace','fontColor','fontFill','width', - 'widthSelectionMultiplier','hoverWidth','arrowScaleFactor','dash' - ]; - util.selectiveDeepExtend(fields, this.options, properties); + // trigger events + inst.trigger(name, ev); + inst.trigger(name + ev.direction, ev); - if (properties.from !== undefined) {this.fromId = properties.from;} - if (properties.to !== undefined) {this.toId = properties.to;} + var isVertical = Utils.isVertical(ev.direction); - if (properties.id !== undefined) {this.id = properties.id;} - if (properties.label !== undefined) {this.label = properties.label;} + // block the browser events + if((inst.options.dragBlockVertical && isVertical) || + (inst.options.dragBlockHorizontal && !isVertical)) { + ev.preventDefault(); + } + break; - if (properties.title !== undefined) {this.title = properties.title;} - if (properties.value !== undefined) {this.value = properties.value;} - if (properties.length !== undefined) {this.physics.springLength = properties.length;} + case EVENT_RELEASE: + if(triggered && ev.changedLength <= inst.options.dragMaxTouches) { + inst.trigger(name + 'end', ev); + triggered = false; + } + break; - // scale the arrow - if (properties.arrowScaleFactor !== undefined) {this.options.arrowScaleFactor = properties.arrowScaleFactor;} + case EVENT_END: + triggered = false; + break; + } + } - if (properties.inheritColor !== undefined) {this.options.inheritColor = properties.inheritColor;} + Hammer.gestures.Drag = { + name: name, + index: 50, + handler: dragGesture, + defaults: { + /** + * minimal movement that have to be made before the drag event gets triggered + * @property dragMinDistance + * @type {Number} + * @default 10 + */ + dragMinDistance: 10, - if (properties.color !== undefined) { - this.options.inheritColor = false; - if (util.isString(properties.color)) { - this.options.color.color = properties.color; - this.options.color.highlight = properties.color; - } - else { - if (properties.color.color !== undefined) {this.options.color.color = properties.color.color;} - if (properties.color.highlight !== undefined) {this.options.color.highlight = properties.color.highlight;} - if (properties.color.hover !== undefined) {this.options.color.hover = properties.color.hover;} - } - } + /** + * Set dragDistanceCorrection to true to make the starting point of the drag + * be calculated from where the drag was triggered, not from where the touch started. + * Useful to avoid a jerk-starting drag, which can make fine-adjustments + * through dragging difficult, and be visually unappealing. + * @property dragDistanceCorrection + * @type {Boolean} + * @default true + */ + dragDistanceCorrection: true, + + /** + * set 0 for unlimited, but this can conflict with transform + * @property dragMaxTouches + * @type {Number} + * @default 1 + */ + dragMaxTouches: 1, - // A node is connected when it has a from and to node. - this.connect(); + /** + * prevent default browser behavior when dragging occurs + * be careful with it, it makes the element a blocking element + * when you are using the drag gesture, it is a good practice to set this true + * @property dragBlockHorizontal + * @type {Boolean} + * @default false + */ + dragBlockHorizontal: false, - this.widthFixed = this.widthFixed || (properties.width !== undefined); - this.lengthFixed = this.lengthFixed || (properties.length !== undefined); + /** + * same as `dragBlockHorizontal`, but for vertical movement + * @property dragBlockVertical + * @type {Boolean} + * @default false + */ + dragBlockVertical: false, - this.widthSelected = this.options.width* this.options.widthSelectionMultiplier; + /** + * dragLockToAxis keeps the drag gesture on the axis that it started on, + * It disallows vertical directions if the initial direction was horizontal, and vice versa. + * @property dragLockToAxis + * @type {Boolean} + * @default false + */ + dragLockToAxis: false, - // set draw method based on style - switch (this.options.style) { - case 'line': this.draw = this._drawLine; break; - case 'arrow': this.draw = this._drawArrow; break; - case 'arrow-center': this.draw = this._drawArrowCenter; break; - case 'dash-line': this.draw = this._drawDashLine; break; - default: this.draw = this._drawLine; break; - } - }; + /** + * drag lock only kicks in when distance > dragLockMinDistance + * This way, locking occurs only when the distance has become large enough to reliably determine the direction + * @property dragLockMinDistance + * @type {Number} + * @default 25 + */ + dragLockMinDistance: 25 + } + }; + })('drag'); /** - * Connect an edge to its nodes + * @module gestures */ - Edge.prototype.connect = function () { - this.disconnect(); - - this.from = this.network.nodes[this.fromId] || null; - this.to = this.network.nodes[this.toId] || null; - this.connected = (this.from && this.to); - - if (this.connected) { - this.from.attachEdge(this); - this.to.attachEdge(this); - } - else { - if (this.from) { - this.from.detachEdge(this); - } - if (this.to) { - this.to.detachEdge(this); - } - } - }; - /** - * Disconnect an edge from its nodes + * trigger a simple gesture event, so you can do anything in your handler. + * only usable if you know what your doing... + * + * @class Gesture + * @static */ - Edge.prototype.disconnect = function () { - if (this.from) { - this.from.detachEdge(this); - this.from = null; - } - if (this.to) { - this.to.detachEdge(this); - this.to = null; - } - - this.connected = false; - }; - /** - * get the title of this edge. - * @return {string} title The title of the edge, or undefined when no title - * has been set. + * @event gesture + * @param {Object} ev */ - Edge.prototype.getTitle = function() { - return typeof this.title === "function" ? this.title() : this.title; + Hammer.gestures.Gesture = { + name: 'gesture', + index: 1337, + handler: function releaseGesture(ev, inst) { + inst.trigger(this.name, ev); + } }; - /** - * Retrieve the value of the edge. Can be undefined - * @return {Number} value + * @module gestures */ - Edge.prototype.getValue = function() { - return this.value; - }; - /** - * Adjust the value range of the edge. The edge will adjust it's width - * based on its value. - * @param {Number} min - * @param {Number} max + * Touch stays at the same place for x time + * + * @class Hold + * @static */ - Edge.prototype.setValueRange = function(min, max) { - if (!this.widthFixed && this.value !== undefined) { - var scale = (this.options.widthMax - this.options.widthMin) / (max - min); - this.options.width= (this.value - min) * scale + this.options.widthMin; - this.widthSelected = this.options.width* this.options.widthSelectionMultiplier; - } - }; - /** - * Redraw a edge - * Draw this edge in the given canvas - * The 2d context of a HTML canvas can be retrieved by canvas.getContext("2d"); - * @param {CanvasRenderingContext2D} ctx + * @event hold + * @param {Object} ev */ - Edge.prototype.draw = function(ctx) { - throw "Method draw not initialized in edge"; - }; /** - * Check if this object is overlapping with the provided object - * @param {Object} obj an object with parameters left, top - * @return {boolean} True if location is located on the edge + * @param {String} name */ - Edge.prototype.isOverlappingWith = function(obj) { - if (this.connected) { - var distMax = 10; - var xFrom = this.from.x; - var yFrom = this.from.y; - var xTo = this.to.x; - var yTo = this.to.y; - var xObj = obj.left; - var yObj = obj.top; - - var dist = this._getDistanceToEdge(xFrom, yFrom, xTo, yTo, xObj, yObj); - - return (dist < distMax); - } - else { - return false - } - }; + (function(name) { + var timer; - Edge.prototype._getColor = function() { - var colorObj = this.options.color; - if (this.options.inheritColor == "to") { - colorObj = { - highlight: this.to.options.color.highlight.border, - hover: this.to.options.color.hover.border, - color: this.to.options.color.border - }; - } - else if (this.options.inheritColor == "from" || this.options.inheritColor == true) { - colorObj = { - highlight: this.from.options.color.highlight.border, - hover: this.from.options.color.hover.border, - color: this.from.options.color.border - }; - } + function holdGesture(ev, inst) { + var options = inst.options, + current = Detection.current; - if (this.selected == true) {return colorObj.highlight;} - else if (this.hover == true) {return colorObj.hover;} - else {return colorObj.color;} - } + switch(ev.eventType) { + case EVENT_START: + clearTimeout(timer); + // set the gesture so we can check in the timeout if it still is + current.name = name; - /** - * Redraw a edge as a line - * Draw this edge in the given canvas - * The 2d context of a HTML canvas can be retrieved by canvas.getContext("2d"); - * @param {CanvasRenderingContext2D} ctx - * @private - */ - Edge.prototype._drawLine = function(ctx) { - // set style - ctx.strokeStyle = this._getColor(); - ctx.lineWidth = this._getLineWidth(); + // set timer and if after the timeout it still is hold, + // we trigger the hold event + timer = setTimeout(function() { + if(current && current.name == name) { + inst.trigger(name, ev); + } + }, options.holdTimeout); + break; - if (this.from != this.to) { - // draw line - var via = this._line(ctx); + case EVENT_MOVE: + if(ev.distance > options.holdThreshold) { + clearTimeout(timer); + } + break; - // draw label - var point; - if (this.label) { - if (this.options.smoothCurves.enabled == true && via != null) { - var midpointX = 0.5*(0.5*(this.from.x + via.x) + 0.5*(this.to.x + via.x)); - var midpointY = 0.5*(0.5*(this.from.y + via.y) + 0.5*(this.to.y + via.y)); - point = {x:midpointX, y:midpointY}; - } - else { - point = this._pointOnLine(0.5); - } - this._label(ctx, this.label, point.x, point.y); - } - } - else { - var x, y; - var radius = this.physics.springLength / 4; - var node = this.from; - if (!node.width) { - node.resize(ctx); - } - if (node.width > node.height) { - x = node.x + node.width / 2; - y = node.y - radius; - } - else { - x = node.x + radius; - y = node.y - node.height / 2; - } - this._circle(ctx, x, y, radius); - point = this._pointOnCircle(x, y, radius, 0.5); - this._label(ctx, this.label, point.x, point.y); - } - }; + case EVENT_RELEASE: + clearTimeout(timer); + break; + } + } + + Hammer.gestures.Hold = { + name: name, + index: 10, + defaults: { + /** + * @property holdTimeout + * @type {Number} + * @default 500 + */ + holdTimeout: 500, + + /** + * movement allowed while holding + * @property holdThreshold + * @type {Number} + * @default 2 + */ + holdThreshold: 2 + }, + handler: holdGesture + }; + })('hold'); /** - * Get the line width of the edge. Depends on width and whether one of the - * connected nodes is selected. - * @return {Number} width - * @private + * @module gestures */ - Edge.prototype._getLineWidth = function() { - if (this.selected == true) { - return Math.min(this.widthSelected, this.options.widthMax)*this.networkScaleInv; - } - else { - if (this.hover == true) { - return Math.min(this.options.hoverWidth, this.options.widthMax)*this.networkScaleInv; - } - else { - return this.options.width*this.networkScaleInv; + /** + * when a touch is being released from the page + * + * @class Release + * @static + */ + /** + * @event release + * @param {Object} ev + */ + Hammer.gestures.Release = { + name: 'release', + index: Infinity, + handler: function releaseGesture(ev, inst) { + if(ev.eventType == EVENT_RELEASE) { + inst.trigger(this.name, ev); + } } - } }; - Edge.prototype._getViaCoordinates = function () { - var xVia = null; - var yVia = null; - var factor = this.options.smoothCurves.roundness; - var type = this.options.smoothCurves.type; + /** + * @module gestures + */ + /** + * triggers swipe events when the end velocity is above the threshold + * for best usage, set `preventDefault` (on the drag gesture) to `true` + * ```` + * hammertime.on("dragleft swipeleft", function(ev) { + * console.log(ev); + * ev.gesture.preventDefault(); + * }); + * ```` + * + * @class Swipe + * @static + */ + /** + * @event swipe + * @param {Object} ev + */ + /** + * @event swipeleft + * @param {Object} ev + */ + /** + * @event swiperight + * @param {Object} ev + */ + /** + * @event swipeup + * @param {Object} ev + */ + /** + * @event swipedown + * @param {Object} ev + */ + Hammer.gestures.Swipe = { + name: 'swipe', + index: 40, + defaults: { + /** + * @property swipeMinTouches + * @type {Number} + * @default 1 + */ + swipeMinTouches: 1, - var dx = Math.abs(this.from.x - this.to.x); - var dy = Math.abs(this.from.y - this.to.y); - if (type == 'discrete' || type == 'diagonalCross') { - if (Math.abs(this.from.x - this.to.x) < Math.abs(this.from.y - this.to.y)) { - if (this.from.y > this.to.y) { - if (this.from.x < this.to.x) { - xVia = this.from.x + factor * dy; - yVia = this.from.y - factor * dy; - } - else if (this.from.x > this.to.x) { - xVia = this.from.x - factor * dy; - yVia = this.from.y - factor * dy; - } - } - else if (this.from.y < this.to.y) { - if (this.from.x < this.to.x) { - xVia = this.from.x + factor * dy; - yVia = this.from.y + factor * dy; - } - else if (this.from.x > this.to.x) { - xVia = this.from.x - factor * dy; - yVia = this.from.y + factor * dy; - } - } - if (type == "discrete") { - xVia = dx < factor * dy ? this.from.x : xVia; - } - } - else if (Math.abs(this.from.x - this.to.x) > Math.abs(this.from.y - this.to.y)) { - if (this.from.y > this.to.y) { - if (this.from.x < this.to.x) { - xVia = this.from.x + factor * dx; - yVia = this.from.y - factor * dx; - } - else if (this.from.x > this.to.x) { - xVia = this.from.x - factor * dx; - yVia = this.from.y - factor * dx; - } - } - else if (this.from.y < this.to.y) { - if (this.from.x < this.to.x) { - xVia = this.from.x + factor * dx; - yVia = this.from.y + factor * dx; - } - else if (this.from.x > this.to.x) { - xVia = this.from.x - factor * dx; - yVia = this.from.y + factor * dx; - } - } - if (type == "discrete") { - yVia = dy < factor * dx ? this.from.y : yVia; - } - } - } - else if (type == "straightCross") { - if (Math.abs(this.from.x - this.to.x) < Math.abs(this.from.y - this.to.y)) { // up - down - xVia = this.from.x; - if (this.from.y < this.to.y) { - yVia = this.to.y - (1-factor) * dy; - } - else { - yVia = this.to.y + (1-factor) * dy; - } - } - else if (Math.abs(this.from.x - this.to.x) > Math.abs(this.from.y - this.to.y)) { // left - right - if (this.from.x < this.to.x) { - xVia = this.to.x - (1-factor) * dx; - } - else { - xVia = this.to.x + (1-factor) * dx; - } - yVia = this.from.y; - } - } - else if (type == 'horizontal') { - if (this.from.x < this.to.x) { - xVia = this.to.x - (1-factor) * dx; - } - else { - xVia = this.to.x + (1-factor) * dx; - } - yVia = this.from.y; - } - else if (type == 'vertical') { - xVia = this.from.x; - if (this.from.y < this.to.y) { - yVia = this.to.y - (1-factor) * dy; - } - else { - yVia = this.to.y + (1-factor) * dy; - } - } - else { // continuous - if (Math.abs(this.from.x - this.to.x) < Math.abs(this.from.y - this.to.y)) { - if (this.from.y > this.to.y) { - if (this.from.x < this.to.x) { - // console.log(1) - xVia = this.from.x + factor * dy; - yVia = this.from.y - factor * dy; - xVia = this.to.x < xVia ? this.to.x : xVia; - } - else if (this.from.x > this.to.x) { - // console.log(2) - xVia = this.from.x - factor * dy; - yVia = this.from.y - factor * dy; - xVia = this.to.x > xVia ? this.to.x :xVia; - } - } - else if (this.from.y < this.to.y) { - if (this.from.x < this.to.x) { - // console.log(3) - xVia = this.from.x + factor * dy; - yVia = this.from.y + factor * dy; - xVia = this.to.x < xVia ? this.to.x : xVia; - } - else if (this.from.x > this.to.x) { - // console.log(4, this.from.x, this.to.x) - xVia = this.from.x - factor * dy; - yVia = this.from.y + factor * dy; - xVia = this.to.x > xVia ? this.to.x : xVia; + /** + * @property swipeMaxTouches + * @type {Number} + * @default 1 + */ + swipeMaxTouches: 1, + + /** + * horizontal swipe velocity + * @property swipeVelocityX + * @type {Number} + * @default 0.6 + */ + swipeVelocityX: 0.6, + + /** + * vertical swipe velocity + * @property swipeVelocityY + * @type {Number} + * @default 0.6 + */ + swipeVelocityY: 0.6 + }, + + handler: function swipeGesture(ev, inst) { + if(ev.eventType == EVENT_RELEASE) { + var touches = ev.touches.length, + options = inst.options; + + // max touches + if(touches < options.swipeMinTouches || + touches > options.swipeMaxTouches) { + return; + } + + // when the distance we moved is too small we skip this gesture + // or we can be already in dragging + if(ev.velocityX > options.swipeVelocityX || + ev.velocityY > options.swipeVelocityY) { + // trigger swipe events + inst.trigger(this.name, ev); + inst.trigger(this.name + ev.direction, ev); + } } - } } - else if (Math.abs(this.from.x - this.to.x) > Math.abs(this.from.y - this.to.y)) { - if (this.from.y > this.to.y) { - if (this.from.x < this.to.x) { - // console.log(5) - xVia = this.from.x + factor * dx; - yVia = this.from.y - factor * dx; - yVia = this.to.y > yVia ? this.to.y : yVia; - } - else if (this.from.x > this.to.x) { - // console.log(6) - xVia = this.from.x - factor * dx; - yVia = this.from.y - factor * dx; - yVia = this.to.y > yVia ? this.to.y : yVia; - } - } - else if (this.from.y < this.to.y) { - if (this.from.x < this.to.x) { - // console.log(7) - xVia = this.from.x + factor * dx; - yVia = this.from.y + factor * dx; - yVia = this.to.y < yVia ? this.to.y : yVia; - } - else if (this.from.x > this.to.x) { - // console.log(8) - xVia = this.from.x - factor * dx; - yVia = this.from.y + factor * dx; - yVia = this.to.y < yVia ? this.to.y : yVia; + }; + + /** + * @module gestures + */ + /** + * Single tap and a double tap on a place + * + * @class Tap + * @static + */ + /** + * @event tap + * @param {Object} ev + */ + /** + * @event doubletap + * @param {Object} ev + */ + + /** + * @param {String} name + */ + (function(name) { + var hasMoved = false; + + function tapGesture(ev, inst) { + var options = inst.options, + current = Detection.current, + prev = Detection.previous, + sincePrev, + didDoubleTap; + + switch(ev.eventType) { + case EVENT_START: + hasMoved = false; + break; + + case EVENT_MOVE: + hasMoved = hasMoved || (ev.distance > options.tapMaxDistance); + break; + + case EVENT_END: + if(!Utils.inStr(ev.srcEvent.type, 'cancel') && ev.deltaTime < options.tapMaxTime && !hasMoved) { + // previous gesture, for the double tap since these are two different gesture detections + sincePrev = prev && prev.lastEvent && ev.timeStamp - prev.lastEvent.timeStamp; + didDoubleTap = false; + + // check if double tap + if(prev && prev.name == name && + (sincePrev && sincePrev < options.doubleTapInterval) && + ev.distance < options.doubleTapDistance) { + inst.trigger('doubletap', ev); + didDoubleTap = true; + } + + // do a single tap + if(!didDoubleTap || options.tapAlways) { + current.name = name; + inst.trigger(current.name, ev); + } + } + break; } - } } - } + Hammer.gestures.Tap = { + name: name, + index: 100, + handler: tapGesture, + defaults: { + /** + * max time of a tap, this is for the slow tappers + * @property tapMaxTime + * @type {Number} + * @default 250 + */ + tapMaxTime: 250, - return {x:xVia, y:yVia}; - } + /** + * max distance of movement of a tap, this is for the slow tappers + * @property tapMaxDistance + * @type {Number} + * @default 10 + */ + tapMaxDistance: 10, + + /** + * always trigger the `tap` event, even while double-tapping + * @property tapAlways + * @type {Boolean} + * @default true + */ + tapAlways: true, + + /** + * max distance between two taps + * @property doubleTapDistance + * @type {Number} + * @default 20 + */ + doubleTapDistance: 20, + + /** + * max time between two taps + * @property doubleTapInterval + * @type {Number} + * @default 300 + */ + doubleTapInterval: 300 + } + }; + })('tap'); /** - * Draw a line between two nodes - * @param {CanvasRenderingContext2D} ctx - * @private + * @module gestures */ - Edge.prototype._line = function (ctx) { - // draw a straight line - ctx.beginPath(); - ctx.moveTo(this.from.x, this.from.y); - if (this.options.smoothCurves.enabled == true) { - if (this.options.smoothCurves.dynamic == false) { - var via = this._getViaCoordinates(); - if (via.x == null) { - ctx.lineTo(this.to.x, this.to.y); - ctx.stroke(); - return null; - } - else { - // this.via.x = via.x; - // this.via.y = via.y; - ctx.quadraticCurveTo(via.x,via.y,this.to.x, this.to.y); - ctx.stroke(); - return via; - } - } - else { - ctx.quadraticCurveTo(this.via.x,this.via.y,this.to.x, this.to.y); - ctx.stroke(); - return this.via; + /** + * when a touch is being touched at the page + * + * @class Touch + * @static + */ + /** + * @event touch + * @param {Object} ev + */ + Hammer.gestures.Touch = { + name: 'touch', + index: -Infinity, + defaults: { + /** + * call preventDefault at touchstart, and makes the element blocking by disabling the scrolling of the page, + * but it improves gestures like transforming and dragging. + * be careful with using this, it can be very annoying for users to be stuck on the page + * @property preventDefault + * @type {Boolean} + * @default false + */ + preventDefault: false, + + /** + * disable mouse events, so only touch (or pen!) input triggers events + * @property preventMouse + * @type {Boolean} + * @default false + */ + preventMouse: false + }, + handler: function touchGesture(ev, inst) { + if(inst.options.preventMouse && ev.pointerType == POINTER_MOUSE) { + ev.stopDetect(); + return; + } + + if(inst.options.preventDefault) { + ev.preventDefault(); + } + + if(ev.eventType == EVENT_TOUCH) { + inst.trigger('touch', ev); + } } - } - else { - ctx.lineTo(this.to.x, this.to.y); - ctx.stroke(); - return null; - } }; /** - * Draw a line from a node to itself, a circle - * @param {CanvasRenderingContext2D} ctx - * @param {Number} x - * @param {Number} y - * @param {Number} radius - * @private + * @module gestures + */ + /** + * User want to scale or rotate with 2 fingers + * Preventing the default browser behavior is a good way to improve feel and working. This can be done with the + * `preventDefault` option. + * + * @class Transform + * @static + */ + /** + * @event transform + * @param {Object} ev + */ + /** + * @event transformstart + * @param {Object} ev + */ + /** + * @event transformend + * @param {Object} ev + */ + /** + * @event pinchin + * @param {Object} ev + */ + /** + * @event pinchout + * @param {Object} ev + */ + /** + * @event rotate + * @param {Object} ev */ - Edge.prototype._circle = function (ctx, x, y, radius) { - // draw a circle - ctx.beginPath(); - ctx.arc(x, y, radius, 0, 2 * Math.PI, false); - ctx.stroke(); - }; /** - * Draw label with white background and with the middle at (x, y) - * @param {CanvasRenderingContext2D} ctx - * @param {String} text - * @param {Number} x - * @param {Number} y - * @private + * @param {String} name */ - Edge.prototype._label = function (ctx, text, x, y) { - if (text) { - // TODO: cache the calculated size - ctx.font = ((this.from.selected || this.to.selected) ? "bold " : "") + - this.options.fontSize + "px " + this.options.fontFace; - ctx.fillStyle = this.options.fontFill; - var width = ctx.measureText(text).width; - var height = this.options.fontSize; - var left = x - width / 2; - var top = y - height / 2; + (function(name) { + var triggered = false; - ctx.fillRect(left, top, width, height); + function transformGesture(ev, inst) { + switch(ev.eventType) { + case EVENT_START: + triggered = false; + break; - // draw text - ctx.fillStyle = this.options.fontColor || "black"; - ctx.textAlign = "left"; - ctx.textBaseline = "top"; - ctx.fillText(text, left, top); - } - }; + case EVENT_MOVE: + // at least multitouch + if(ev.touches.length < 2) { + return; + } - /** - * Redraw a edge as a dashed line - * Draw this edge in the given canvas - * @author David Jordan - * @date 2012-08-08 - * The 2d context of a HTML canvas can be retrieved by canvas.getContext("2d"); - * @param {CanvasRenderingContext2D} ctx - * @private - */ - Edge.prototype._drawDashLine = function(ctx) { - // set style - if (this.selected == true) {ctx.strokeStyle = this.options.color.highlight;} - else if (this.hover == true) {ctx.strokeStyle = this.options.color.hover;} - else {ctx.strokeStyle = this.options.color.color;} + var scaleThreshold = Math.abs(1 - ev.scale); + var rotationThreshold = Math.abs(ev.rotation); - ctx.lineWidth = this._getLineWidth(); + // when the distance we moved is too small we skip this gesture + // or we can be already in dragging + if(scaleThreshold < inst.options.transformMinScale && + rotationThreshold < inst.options.transformMinRotation) { + return; + } - var via = null; - // only firefox and chrome support this method, else we use the legacy one. - if (ctx.mozDash !== undefined || ctx.setLineDash !== undefined) { - // configure the dash pattern - var pattern = [0]; - if (this.options.dash.length !== undefined && this.options.dash.gap !== undefined) { - pattern = [this.options.dash.length,this.options.dash.gap]; - } - else { - pattern = [5,5]; - } + // we are transforming! + Detection.current.name = name; - // set dash settings for chrome or firefox - if (typeof ctx.setLineDash !== 'undefined') { //Chrome - ctx.setLineDash(pattern); - ctx.lineDashOffset = 0; + // first time, trigger dragstart event + if(!triggered) { + inst.trigger(name + 'start', ev); + triggered = true; + } - } else { //Firefox - ctx.mozDash = pattern; - ctx.mozDashOffset = 0; - } + inst.trigger(name, ev); // basic transform event - // draw the line - via = this._line(ctx); + // trigger rotate event + if(rotationThreshold > inst.options.transformMinRotation) { + inst.trigger('rotate', ev); + } - // restore the dash settings. - if (typeof ctx.setLineDash !== 'undefined') { //Chrome - ctx.setLineDash([0]); - ctx.lineDashOffset = 0; + // trigger pinch event + if(scaleThreshold > inst.options.transformMinScale) { + inst.trigger('pinch', ev); + inst.trigger('pinch' + (ev.scale < 1 ? 'in' : 'out'), ev); + } + break; - } else { //Firefox - ctx.mozDash = [0]; - ctx.mozDashOffset = 0; - } - } - else { // unsupporting smooth lines - // draw dashed line - ctx.beginPath(); - ctx.lineCap = 'round'; - if (this.options.dash.altLength !== undefined) //If an alt dash value has been set add to the array this value - { - ctx.dashedLine(this.from.x,this.from.y,this.to.x,this.to.y, - [this.options.dash.length,this.options.dash.gap,this.options.dash.altLength,this.options.dash.gap]); - } - else if (this.options.dash.length !== undefined && this.options.dash.gap !== undefined) //If a dash and gap value has been set add to the array this value - { - ctx.dashedLine(this.from.x,this.from.y,this.to.x,this.to.y, - [this.options.dash.length,this.options.dash.gap]); - } - else //If all else fails draw a line - { - ctx.moveTo(this.from.x, this.from.y); - ctx.lineTo(this.to.x, this.to.y); + case EVENT_RELEASE: + if(triggered && ev.changedLength < 2) { + inst.trigger(name + 'end', ev); + triggered = false; + } + break; + } } - ctx.stroke(); - } - // draw label - if (this.label) { - var point; - if (this.options.smoothCurves.enabled == true && via != null) { - var midpointX = 0.5*(0.5*(this.from.x + via.x) + 0.5*(this.to.x + via.x)); - var midpointY = 0.5*(0.5*(this.from.y + via.y) + 0.5*(this.to.y + via.y)); - point = {x:midpointX, y:midpointY}; - } - else { - point = this._pointOnLine(0.5); - } - this._label(ctx, this.label, point.x, point.y); - } - }; + Hammer.gestures.Transform = { + name: name, + index: 45, + defaults: { + /** + * minimal scale factor, no scale is 1, zoomin is to 0 and zoomout until higher then 1 + * @property transformMinScale + * @type {Number} + * @default 0.01 + */ + transformMinScale: 0.01, + + /** + * rotation in degrees + * @property transformMinRotation + * @type {Number} + * @default 1 + */ + transformMinRotation: 1 + }, + + handler: transformGesture + }; + })('transform'); + + /** + * @module hammer + */ + + // AMD export + if(true) { + !(__WEBPACK_AMD_DEFINE_RESULT__ = (function() { + return Hammer; + }.call(exports, __webpack_require__, exports, module)), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); + // commonjs export + } else if(typeof module !== 'undefined' && module.exports) { + module.exports = Hammer; + // browser export + } else { + window.Hammer = Hammer; + } + + })(window); + +/***/ }, +/* 49 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * Copyright 2012 Craig Campbell + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Mousetrap is a simple keyboard shortcut library for Javascript with + * no external dependencies + * + * @version 1.1.2 + * @url craig.is/killing/mice + */ + + /** + * mapping of special keycodes to their corresponding keys + * + * everything in this dictionary cannot use keypress events + * so it has to be here to map to the correct keycodes for + * keyup/keydown events + * + * @type {Object} + */ + var _MAP = { + 8: 'backspace', + 9: 'tab', + 13: 'enter', + 16: 'shift', + 17: 'ctrl', + 18: 'alt', + 20: 'capslock', + 27: 'esc', + 32: 'space', + 33: 'pageup', + 34: 'pagedown', + 35: 'end', + 36: 'home', + 37: 'left', + 38: 'up', + 39: 'right', + 40: 'down', + 45: 'ins', + 46: 'del', + 91: 'meta', + 93: 'meta', + 224: 'meta' + }, - /** - * Get a point on a line - * @param {Number} percentage. Value between 0 (line start) and 1 (line end) - * @return {Object} point - * @private - */ - Edge.prototype._pointOnLine = function (percentage) { - return { - x: (1 - percentage) * this.from.x + percentage * this.to.x, - y: (1 - percentage) * this.from.y + percentage * this.to.y - } - }; + /** + * mapping for special characters so they can support + * + * this dictionary is only used incase you want to bind a + * keyup or keydown event to one of these keys + * + * @type {Object} + */ + _KEYCODE_MAP = { + 106: '*', + 107: '+', + 109: '-', + 110: '.', + 111 : '/', + 186: ';', + 187: '=', + 188: ',', + 189: '-', + 190: '.', + 191: '/', + 192: '`', + 219: '[', + 220: '\\', + 221: ']', + 222: '\'' + }, - /** - * Get a point on a circle - * @param {Number} x - * @param {Number} y - * @param {Number} radius - * @param {Number} percentage. Value between 0 (line start) and 1 (line end) - * @return {Object} point - * @private - */ - Edge.prototype._pointOnCircle = function (x, y, radius, percentage) { - var angle = (percentage - 3/8) * 2 * Math.PI; - return { - x: x + radius * Math.cos(angle), - y: y - radius * Math.sin(angle) - } - }; + /** + * this is a mapping of keys that require shift on a US keypad + * back to the non shift equivelents + * + * this is so you can use keyup events with these keys + * + * note that this will only work reliably on US keyboards + * + * @type {Object} + */ + _SHIFT_MAP = { + '~': '`', + '!': '1', + '@': '2', + '#': '3', + '$': '4', + '%': '5', + '^': '6', + '&': '7', + '*': '8', + '(': '9', + ')': '0', + '_': '-', + '+': '=', + ':': ';', + '\"': '\'', + '<': ',', + '>': '.', + '?': '/', + '|': '\\' + }, - /** - * Redraw a edge as a line with an arrow halfway the line - * Draw this edge in the given canvas - * The 2d context of a HTML canvas can be retrieved by canvas.getContext("2d"); - * @param {CanvasRenderingContext2D} ctx - * @private - */ - Edge.prototype._drawArrowCenter = function(ctx) { - var point; - // set style - if (this.selected == true) {ctx.strokeStyle = this.options.color.highlight; ctx.fillStyle = this.options.color.highlight;} - else if (this.hover == true) {ctx.strokeStyle = this.options.color.hover; ctx.fillStyle = this.options.color.hover;} - else {ctx.strokeStyle = this.options.color.color; ctx.fillStyle = this.options.color.color;} - ctx.lineWidth = this._getLineWidth(); + /** + * this is a list of special strings you can use to map + * to modifier keys when you specify your keyboard shortcuts + * + * @type {Object} + */ + _SPECIAL_ALIASES = { + 'option': 'alt', + 'command': 'meta', + 'return': 'enter', + 'escape': 'esc' + }, - if (this.from != this.to) { - // draw line - var via = this._line(ctx); + /** + * variable to store the flipped version of _MAP from above + * needed to check if we should use keypress or not when no action + * is specified + * + * @type {Object|undefined} + */ + _REVERSE_MAP, - var angle = Math.atan2((this.to.y - this.from.y), (this.to.x - this.from.x)); - var length = (10 + 5 * this.options.width) * this.options.arrowScaleFactor; - // draw an arrow halfway the line - if (this.options.smoothCurves.enabled == true && via != null) { - var midpointX = 0.5*(0.5*(this.from.x + via.x) + 0.5*(this.to.x + via.x)); - var midpointY = 0.5*(0.5*(this.from.y + via.y) + 0.5*(this.to.y + via.y)); - point = {x:midpointX, y:midpointY}; - } - else { - point = this._pointOnLine(0.5); - } + /** + * a list of all the callbacks setup via Mousetrap.bind() + * + * @type {Object} + */ + _callbacks = {}, - ctx.arrow(point.x, point.y, angle, length); - ctx.fill(); - ctx.stroke(); + /** + * direct map of string combinations to callbacks used for trigger() + * + * @type {Object} + */ + _direct_map = {}, - // draw label - if (this.label) { - this._label(ctx, this.label, point.x, point.y); - } - } - else { - // draw circle - var x, y; - var radius = 0.25 * Math.max(100,this.physics.springLength); - var node = this.from; - if (!node.width) { - node.resize(ctx); - } - if (node.width > node.height) { - x = node.x + node.width * 0.5; - y = node.y - radius; - } - else { - x = node.x + radius; - y = node.y - node.height * 0.5; - } - this._circle(ctx, x, y, radius); + /** + * keeps track of what level each sequence is at since multiple + * sequences can start out with the same sequence + * + * @type {Object} + */ + _sequence_levels = {}, - // draw all arrows - var angle = 0.2 * Math.PI; - var length = (10 + 5 * this.options.width) * this.options.arrowScaleFactor; - point = this._pointOnCircle(x, y, radius, 0.5); - ctx.arrow(point.x, point.y, angle, length); - ctx.fill(); - ctx.stroke(); + /** + * variable to store the setTimeout call + * + * @type {null|number} + */ + _reset_timer, - // draw label - if (this.label) { - point = this._pointOnCircle(x, y, radius, 0.5); - this._label(ctx, this.label, point.x, point.y); - } - } - }; + /** + * temporary state where we will ignore the next keyup + * + * @type {boolean|string} + */ + _ignore_next_keyup = false, + /** + * are we currently inside of a sequence? + * type of action ("keyup" or "keydown" or "keypress") or false + * + * @type {boolean|string} + */ + _inside_sequence = false; + /** + * loop through the f keys, f1 to f19 and add them to the map + * programatically + */ + for (var i = 1; i < 20; ++i) { + _MAP[111 + i] = 'f' + i; + } - /** - * Redraw a edge as a line with an arrow - * Draw this edge in the given canvas - * The 2d context of a HTML canvas can be retrieved by canvas.getContext("2d"); - * @param {CanvasRenderingContext2D} ctx - * @private - */ - Edge.prototype._drawArrow = function(ctx) { - // set style - if (this.selected == true) {ctx.strokeStyle = this.options.color.highlight; ctx.fillStyle = this.options.color.highlight;} - else if (this.hover == true) {ctx.strokeStyle = this.options.color.hover; ctx.fillStyle = this.options.color.hover;} - else {ctx.strokeStyle = this.options.color.color; ctx.fillStyle = this.options.color.color;} + /** + * loop through to map numbers on the numeric keypad + */ + for (i = 0; i <= 9; ++i) { + _MAP[i + 96] = i; + } - ctx.lineWidth = this._getLineWidth(); + /** + * cross browser add event method + * + * @param {Element|HTMLDocument} object + * @param {string} type + * @param {Function} callback + * @returns void + */ + function _addEvent(object, type, callback) { + if (object.addEventListener) { + return object.addEventListener(type, callback, false); + } - var angle, length; - //draw a line - if (this.from != this.to) { - angle = Math.atan2((this.to.y - this.from.y), (this.to.x - this.from.x)); - var dx = (this.to.x - this.from.x); - var dy = (this.to.y - this.from.y); - var edgeSegmentLength = Math.sqrt(dx * dx + dy * dy); + object.attachEvent('on' + type, callback); + } - var fromBorderDist = this.from.distanceToBorder(ctx, angle + Math.PI); - var fromBorderPoint = (edgeSegmentLength - fromBorderDist) / edgeSegmentLength; - var xFrom = (fromBorderPoint) * this.from.x + (1 - fromBorderPoint) * this.to.x; - var yFrom = (fromBorderPoint) * this.from.y + (1 - fromBorderPoint) * this.to.y; + /** + * takes the event and returns the key character + * + * @param {Event} e + * @return {string} + */ + function _characterFromEvent(e) { - var via; - if (this.options.smoothCurves.dynamic == true && this.options.smoothCurves.enabled == true ) { - via = this.via; - } - else if (this.options.smoothCurves.enabled == true) { - via = this._getViaCoordinates(); - } + // for keypress events we should return the character as is + if (e.type == 'keypress') { + return String.fromCharCode(e.which); + } - if (this.options.smoothCurves.enabled == true && via.x != null) { - angle = Math.atan2((this.to.y - via.y), (this.to.x - via.x)); - dx = (this.to.x - via.x); - dy = (this.to.y - via.y); - edgeSegmentLength = Math.sqrt(dx * dx + dy * dy); - } - var toBorderDist = this.to.distanceToBorder(ctx, angle); - var toBorderPoint = (edgeSegmentLength - toBorderDist) / edgeSegmentLength; + // for non keypress events the special maps are needed + if (_MAP[e.which]) { + return _MAP[e.which]; + } - var xTo,yTo; - if (this.options.smoothCurves.enabled == true && via.x != null) { - xTo = (1 - toBorderPoint) * via.x + toBorderPoint * this.to.x; - yTo = (1 - toBorderPoint) * via.y + toBorderPoint * this.to.y; - } - else { - xTo = (1 - toBorderPoint) * this.from.x + toBorderPoint * this.to.x; - yTo = (1 - toBorderPoint) * this.from.y + toBorderPoint * this.to.y; - } + if (_KEYCODE_MAP[e.which]) { + return _KEYCODE_MAP[e.which]; + } - ctx.beginPath(); - ctx.moveTo(xFrom,yFrom); - if (this.options.smoothCurves.enabled == true && via.x != null) { - ctx.quadraticCurveTo(via.x,via.y,xTo, yTo); - } - else { - ctx.lineTo(xTo, yTo); - } - ctx.stroke(); + // if it is not in the special map + return String.fromCharCode(e.which).toLowerCase(); + } - // draw arrow at the end of the line - length = (10 + 5 * this.options.width) * this.options.arrowScaleFactor; - ctx.arrow(xTo, yTo, angle, length); - ctx.fill(); - ctx.stroke(); + /** + * should we stop this event before firing off callbacks + * + * @param {Event} e + * @return {boolean} + */ + function _stop(e) { + var element = e.target || e.srcElement, + tag_name = element.tagName; - // draw label - if (this.label) { - var point; - if (this.options.smoothCurves.enabled == true && via != null) { - var midpointX = 0.5*(0.5*(this.from.x + via.x) + 0.5*(this.to.x + via.x)); - var midpointY = 0.5*(0.5*(this.from.y + via.y) + 0.5*(this.to.y + via.y)); - point = {x:midpointX, y:midpointY}; - } - else { - point = this._pointOnLine(0.5); + // if the element has the class "mousetrap" then no need to stop + if ((' ' + element.className + ' ').indexOf(' mousetrap ') > -1) { + return false; } - this._label(ctx, this.label, point.x, point.y); - } - } - else { - // draw circle - var node = this.from; - var x, y, arrow; - var radius = 0.25 * Math.max(100,this.physics.springLength); - if (!node.width) { - node.resize(ctx); - } - if (node.width > node.height) { - x = node.x + node.width * 0.5; - y = node.y - radius; - arrow = { - x: x, - y: node.y, - angle: 0.9 * Math.PI - }; - } - else { - x = node.x + radius; - y = node.y - node.height * 0.5; - arrow = { - x: node.x, - y: y, - angle: 0.6 * Math.PI - }; - } - ctx.beginPath(); - // TODO: similarly, for a line without arrows, draw to the border of the nodes instead of the center - ctx.arc(x, y, radius, 0, 2 * Math.PI, false); - ctx.stroke(); - // draw all arrows - var length = (10 + 5 * this.options.width) * this.options.arrowScaleFactor; - ctx.arrow(arrow.x, arrow.y, arrow.angle, length); - ctx.fill(); - ctx.stroke(); + // stop for input, select, and textarea + return tag_name == 'INPUT' || tag_name == 'SELECT' || tag_name == 'TEXTAREA' || (element.contentEditable && element.contentEditable == 'true'); + } - // draw label - if (this.label) { - point = this._pointOnCircle(x, y, radius, 0.5); - this._label(ctx, this.label, point.x, point.y); - } + /** + * checks if two arrays are equal + * + * @param {Array} modifiers1 + * @param {Array} modifiers2 + * @returns {boolean} + */ + function _modifiersMatch(modifiers1, modifiers2) { + return modifiers1.sort().join(',') === modifiers2.sort().join(','); } - }; + /** + * resets all sequence counters except for the ones passed in + * + * @param {Object} do_not_reset + * @returns void + */ + function _resetSequences(do_not_reset) { + do_not_reset = do_not_reset || {}; + var active_sequences = false, + key; - /** - * Calculate the distance between a point (x3,y3) and a line segment from - * (x1,y1) to (x2,y2). - * http://stackoverflow.com/questions/849211/shortest-distancae-between-a-point-and-a-line-segment - * @param {number} x1 - * @param {number} y1 - * @param {number} x2 - * @param {number} y2 - * @param {number} x3 - * @param {number} y3 - * @private - */ - Edge.prototype._getDistanceToEdge = function (x1,y1, x2,y2, x3,y3) { // x3,y3 is the point - if (this.from != this.to) { - if (this.options.smoothCurves.enabled == true) { - var xVia, yVia; - if (this.options.smoothCurves.enabled == true && this.options.smoothCurves.dynamic == true) { - xVia = this.via.x; - yVia = this.via.y; - } - else { - var via = this._getViaCoordinates(); - xVia = via.x; - yVia = via.y; + for (key in _sequence_levels) { + if (do_not_reset[key]) { + active_sequences = true; + continue; + } + _sequence_levels[key] = 0; } - var minDistance = 1e9; - var distance; - var i,t,x,y, lastX, lastY; - for (i = 0; i < 10; i++) { - t = 0.1*i; - x = Math.pow(1-t,2)*x1 + (2*t*(1 - t))*xVia + Math.pow(t,2)*x2; - y = Math.pow(1-t,2)*y1 + (2*t*(1 - t))*yVia + Math.pow(t,2)*y2; - if (i > 0) { - distance = this._getDistanceToLine(lastX,lastY,x,y, x3,y3); - minDistance = distance < minDistance ? distance : minDistance; - } - lastX = x; lastY = y; + + if (!active_sequences) { + _inside_sequence = false; } - return minDistance - } - else { - return this._getDistanceToLine(x1,y1,x2,y2,x3,y3); - } - } - else { - var x, y, dx, dy; - var radius = this.physics.springLength / 4; - var node = this.from; - if (!node.width) { - node.resize(ctx); - } - if (node.width > node.height) { - x = node.x + node.width / 2; - y = node.y - radius; - } - else { - x = node.x + radius; - y = node.y - node.height / 2; - } - dx = x - x3; - dy = y - y3; - return Math.abs(Math.sqrt(dx*dx + dy*dy) - radius); } - }; - Edge.prototype._getDistanceToLine = function(x1,y1,x2,y2,x3,y3) { - var px = x2-x1, - py = y2-y1, - something = px*px + py*py, - u = ((x3 - x1) * px + (y3 - y1) * py) / something; + /** + * finds all callbacks that match based on the keycode, modifiers, + * and action + * + * @param {string} character + * @param {Array} modifiers + * @param {string} action + * @param {boolean=} remove - should we remove any matches + * @param {string=} combination + * @returns {Array} + */ + function _getMatches(character, modifiers, action, remove, combination) { + var i, + callback, + matches = []; - if (u > 1) { - u = 1; - } - else if (u < 0) { - u = 0; - } + // if there are no events related to this keycode + if (!_callbacks[character]) { + return []; + } - var x = x1 + u * px, - y = y1 + u * py, - dx = x - x3, - dy = y - y3; + // if a modifier key is coming up on its own we should allow it + if (action == 'keyup' && _isModifier(character)) { + modifiers = [character]; + } - //# Note: If the actual distance does not matter, - //# if you only want to compare what this function - //# returns to other results of this function, you - //# can just return the squared distance instead - //# (i.e. remove the sqrt) to gain a little performance + // loop through all callbacks for the key that was pressed + // and see if any of them match + for (i = 0; i < _callbacks[character].length; ++i) { + callback = _callbacks[character][i]; - return Math.sqrt(dx*dx + dy*dy); - } + // if this is a sequence but it is not at the right level + // then move onto the next match + if (callback.seq && _sequence_levels[callback.seq] != callback.level) { + continue; + } - /** - * This allows the zoom level of the network to influence the rendering - * - * @param scale - */ - Edge.prototype.setScale = function(scale) { - this.networkScaleInv = 1.0/scale; - }; + // if the action we are looking for doesn't match the action we got + // then we should keep going + if (action != callback.action) { + continue; + } + // if this is a keypress event that means that we need to only + // look at the character, otherwise check the modifiers as + // well + if (action == 'keypress' || _modifiersMatch(modifiers, callback.modifiers)) { - Edge.prototype.select = function() { - this.selected = true; - }; + // remove is used so if you change your mind and call bind a + // second time with a new function the first one is overwritten + if (remove && callback.combo == combination) { + _callbacks[character].splice(i, 1); + } - Edge.prototype.unselect = function() { - this.selected = false; - }; + matches.push(callback); + } + } - Edge.prototype.positionBezierNode = function() { - if (this.via !== null && this.from !== null && this.to !== null) { - this.via.x = 0.5 * (this.from.x + this.to.x); - this.via.y = 0.5 * (this.from.y + this.to.y); + return matches; } - }; - /** - * This function draws the control nodes for the manipulator. In order to enable this, only set the this.controlNodesEnabled to true. - * @param ctx - */ - Edge.prototype._drawControlNodes = function(ctx) { - if (this.controlNodesEnabled == true) { - if (this.controlNodes.from === null && this.controlNodes.to === null) { - var nodeIdFrom = "edgeIdFrom:".concat(this.id); - var nodeIdTo = "edgeIdTo:".concat(this.id); - var constants = { - nodes:{group:'', radius:8}, - physics:{damping:0}, - clustering: {maxNodeSizeIncrements: 0 ,nodeScaling: {width:0, height: 0, radius:0}} - }; - this.controlNodes.from = new Node( - {id:nodeIdFrom, - shape:'dot', - color:{background:'#ff4e00', border:'#3c3c3c', highlight: {background:'#07f968'}} - },{},{},constants); - this.controlNodes.to = new Node( - {id:nodeIdTo, - shape:'dot', - color:{background:'#ff4e00', border:'#3c3c3c', highlight: {background:'#07f968'}} - },{},{},constants); - } + /** + * takes a key event and figures out what the modifiers are + * + * @param {Event} e + * @returns {Array} + */ + function _eventModifiers(e) { + var modifiers = []; - if (this.controlNodes.from.selected == false && this.controlNodes.to.selected == false) { - this.controlNodes.positions = this.getControlNodePositions(ctx); - this.controlNodes.from.x = this.controlNodes.positions.from.x; - this.controlNodes.from.y = this.controlNodes.positions.from.y; - this.controlNodes.to.x = this.controlNodes.positions.to.x; - this.controlNodes.to.y = this.controlNodes.positions.to.y; - } + if (e.shiftKey) { + modifiers.push('shift'); + } - this.controlNodes.from.draw(ctx); - this.controlNodes.to.draw(ctx); + if (e.altKey) { + modifiers.push('alt'); + } + + if (e.ctrlKey) { + modifiers.push('ctrl'); + } + + if (e.metaKey) { + modifiers.push('meta'); + } + + return modifiers; } - else { - this.controlNodes = {from:null, to:null, positions:{}}; + + /** + * actually calls the callback function + * + * if your callback function returns false this will use the jquery + * convention - prevent default and stop propogation on the event + * + * @param {Function} callback + * @param {Event} e + * @returns void + */ + function _fireCallback(callback, e) { + if (callback(e) === false) { + if (e.preventDefault) { + e.preventDefault(); + } + + if (e.stopPropagation) { + e.stopPropagation(); + } + + e.returnValue = false; + e.cancelBubble = true; + } } - }; - /** - * Enable control nodes. - * @private - */ - Edge.prototype._enableControlNodes = function() { - this.controlNodesEnabled = true; - }; + /** + * handles a character key event + * + * @param {string} character + * @param {Event} e + * @returns void + */ + function _handleCharacter(character, e) { - /** - * disable control nodes - * @private - */ - Edge.prototype._disableControlNodes = function() { - this.controlNodesEnabled = false; - }; + // if this event should not happen stop here + if (_stop(e)) { + return; + } - /** - * This checks if one of the control nodes is selected and if so, returns the control node object. Else it returns null. - * @param x - * @param y - * @returns {null} - * @private - */ - Edge.prototype._getSelectedControlNode = function(x,y) { - var positions = this.controlNodes.positions; - var fromDistance = Math.sqrt(Math.pow(x - positions.from.x,2) + Math.pow(y - positions.from.y,2)); - var toDistance = Math.sqrt(Math.pow(x - positions.to.x ,2) + Math.pow(y - positions.to.y ,2)); + var callbacks = _getMatches(character, _eventModifiers(e), e.type), + i, + do_not_reset = {}, + processed_sequence_callback = false; - if (fromDistance < 15) { - this.connectedNode = this.from; - this.from = this.controlNodes.from; - return this.controlNodes.from; - } - else if (toDistance < 15) { - this.connectedNode = this.to; - this.to = this.controlNodes.to; - return this.controlNodes.to; - } - else { - return null; + // loop through matching callbacks for this key event + for (i = 0; i < callbacks.length; ++i) { + + // fire for all sequence callbacks + // this is because if for example you have multiple sequences + // bound such as "g i" and "g t" they both need to fire the + // callback for matching g cause otherwise you can only ever + // match the first one + if (callbacks[i].seq) { + processed_sequence_callback = true; + + // keep a list of which sequences were matches for later + do_not_reset[callbacks[i].seq] = 1; + _fireCallback(callbacks[i].callback, e); + continue; + } + + // if there were no sequence matches but we are still here + // that means this is a regular match so we should fire that + if (!processed_sequence_callback && !_inside_sequence) { + _fireCallback(callbacks[i].callback, e); + } + } + + // if you are inside of a sequence and the key you are pressing + // is not a modifier key then we should reset all sequences + // that were not matched by this key event + if (e.type == _inside_sequence && !_isModifier(character)) { + _resetSequences(do_not_reset); + } } - }; + /** + * handles a keydown event + * + * @param {Event} e + * @returns void + */ + function _handleKey(e) { + + // normalize e.which for key events + // @see http://stackoverflow.com/questions/4285627/javascript-keycode-vs-charcode-utter-confusion + e.which = typeof e.which == "number" ? e.which : e.keyCode; - /** - * this resets the control nodes to their original position. - * @private - */ - Edge.prototype._restoreControlNodes = function() { - if (this.controlNodes.from.selected == true) { - this.from = this.connectedNode; - this.connectedNode = null; - this.controlNodes.from.unselect(); - } - if (this.controlNodes.to.selected == true) { - this.to = this.connectedNode; - this.connectedNode = null; - this.controlNodes.to.unselect(); - } - }; + var character = _characterFromEvent(e); - /** - * this calculates the position of the control nodes on the edges of the parent nodes. - * - * @param ctx - * @returns {{from: {x: number, y: number}, to: {x: *, y: *}}} - */ - Edge.prototype.getControlNodePositions = function(ctx) { - var angle = Math.atan2((this.to.y - this.from.y), (this.to.x - this.from.x)); - var dx = (this.to.x - this.from.x); - var dy = (this.to.y - this.from.y); - var edgeSegmentLength = Math.sqrt(dx * dx + dy * dy); - var fromBorderDist = this.from.distanceToBorder(ctx, angle + Math.PI); - var fromBorderPoint = (edgeSegmentLength - fromBorderDist) / edgeSegmentLength; - var xFrom = (fromBorderPoint) * this.from.x + (1 - fromBorderPoint) * this.to.x; - var yFrom = (fromBorderPoint) * this.from.y + (1 - fromBorderPoint) * this.to.y; + // no character found then stop + if (!character) { + return; + } - var via; - if (this.options.smoothCurves.dynamic == true && this.options.smoothCurves.enabled == true) { - via = this.via; - } - else if (this.options.smoothCurves.enabled == true) { - via = this._getViaCoordinates(); + if (e.type == 'keyup' && _ignore_next_keyup == character) { + _ignore_next_keyup = false; + return; + } + + _handleCharacter(character, e); } - if (this.options.smoothCurves.enabled == true && via.x != null) { - angle = Math.atan2((this.to.y - via.y), (this.to.x - via.x)); - dx = (this.to.x - via.x); - dy = (this.to.y - via.y); - edgeSegmentLength = Math.sqrt(dx * dx + dy * dy); + /** + * determines if the keycode specified is a modifier key or not + * + * @param {string} key + * @returns {boolean} + */ + function _isModifier(key) { + return key == 'shift' || key == 'ctrl' || key == 'alt' || key == 'meta'; } - var toBorderDist = this.to.distanceToBorder(ctx, angle); - var toBorderPoint = (edgeSegmentLength - toBorderDist) / edgeSegmentLength; - var xTo,yTo; - if (this.options.smoothCurves.enabled == true && via.x != null) { - xTo = (1 - toBorderPoint) * via.x + toBorderPoint * this.to.x; - yTo = (1 - toBorderPoint) * via.y + toBorderPoint * this.to.y; + /** + * called to set a 1 second timeout on the specified sequence + * + * this is so after each key press in the sequence you have 1 second + * to press the next key before you have to start over + * + * @returns void + */ + function _resetSequenceTimer() { + clearTimeout(_reset_timer); + _reset_timer = setTimeout(_resetSequences, 1000); } - else { - xTo = (1 - toBorderPoint) * this.from.x + toBorderPoint * this.to.x; - yTo = (1 - toBorderPoint) * this.from.y + toBorderPoint * this.to.y; + + /** + * reverses the map lookup so that we can look for specific keys + * to see what can and can't use keypress + * + * @return {Object} + */ + function _getReverseMap() { + if (!_REVERSE_MAP) { + _REVERSE_MAP = {}; + for (var key in _MAP) { + + // pull out the numeric keypad from here cause keypress should + // be able to detect the keys from the character + if (key > 95 && key < 112) { + continue; + } + + if (_MAP.hasOwnProperty(key)) { + _REVERSE_MAP[_MAP[key]] = key; + } + } + } + return _REVERSE_MAP; } - return {from:{x:xFrom,y:yFrom},to:{x:xTo,y:yTo}}; - }; + /** + * picks the best action based on the key combination + * + * @param {string} key - character for key + * @param {Array} modifiers + * @param {string=} action passed in + */ + function _pickBestAction(key, modifiers, action) { - module.exports = Edge; + // if no action was picked in we should try to pick the one + // that we think would work best for this key + if (!action) { + action = _getReverseMap()[key] ? 'keydown' : 'keypress'; + } -/***/ }, -/* 49 */ -/***/ function(module, exports, __webpack_require__) { + // modifier keys don't work as expected with keypress, + // switch to keydown + if (action == 'keypress' && modifiers.length) { + action = 'keydown'; + } - /** - * Popup is a class to create a popup window with some text - * @param {Element} container The container object. - * @param {Number} [x] - * @param {Number} [y] - * @param {String} [text] - * @param {Object} [style] An object containing borderColor, - * backgroundColor, etc. - */ - function Popup(container, x, y, text, style) { - if (container) { - this.container = container; - } - else { - this.container = document.body; + return action; } - // x, y and text are optional, see if a style object was passed in their place - if (style === undefined) { - if (typeof x === "object") { - style = x; - x = undefined; - } else if (typeof text === "object") { - style = text; - text = undefined; - } else { - // for backwards compatibility, in case clients other than Network are creating Popup directly - style = { - fontColor: 'black', - fontSize: 14, // px - fontFace: 'verdana', - color: { - border: '#666', - background: '#FFFFC6' - } + /** + * binds a key sequence to an event + * + * @param {string} combo - combo specified in bind call + * @param {Array} keys + * @param {Function} callback + * @param {string=} action + * @returns void + */ + function _bindSequence(combo, keys, callback, action) { + + // start off by adding a sequence level record for this combination + // and setting the level to 0 + _sequence_levels[combo] = 0; + + // if there is no action pick the best one for the first key + // in the sequence + if (!action) { + action = _pickBestAction(keys[0], []); } - } - } - this.x = 0; - this.y = 0; - this.padding = 5; + /** + * callback to increase the sequence level for this sequence and reset + * all other sequences that were active + * + * @param {Event} e + * @returns void + */ + var _increaseSequence = function(e) { + _inside_sequence = action; + ++_sequence_levels[combo]; + _resetSequenceTimer(); + }, - if (x !== undefined && y !== undefined ) { - this.setPosition(x, y); - } - if (text !== undefined) { - this.setText(text); - } + /** + * wraps the specified callback inside of another function in order + * to reset all sequence counters as soon as this sequence is done + * + * @param {Event} e + * @returns void + */ + _callbackAndReset = function(e) { + _fireCallback(callback, e); - // create the frame - this.frame = document.createElement("div"); - var styleAttr = this.frame.style; - styleAttr.position = "absolute"; - styleAttr.visibility = "hidden"; - styleAttr.border = "1px solid " + style.color.border; - styleAttr.color = style.fontColor; - styleAttr.fontSize = style.fontSize + "px"; - styleAttr.fontFamily = style.fontFace; - styleAttr.padding = this.padding + "px"; - styleAttr.backgroundColor = style.color.background; - styleAttr.borderRadius = "3px"; - styleAttr.MozBorderRadius = "3px"; - styleAttr.WebkitBorderRadius = "3px"; - styleAttr.boxShadow = "3px 3px 10px rgba(128, 128, 128, 0.5)"; - styleAttr.whiteSpace = "nowrap"; - this.container.appendChild(this.frame); - } + // we should ignore the next key up if the action is key down + // or keypress. this is so if you finish a sequence and + // release the key the final key will not trigger a keyup + if (action !== 'keyup') { + _ignore_next_keyup = _characterFromEvent(e); + } + + // weird race condition if a sequence ends with the key + // another sequence begins with + setTimeout(_resetSequences, 10); + }, + i; + + // loop through keys one at a time and bind the appropriate callback + // function. for any key leading up to the final one it should + // increase the sequence. after the final, it should reset all sequences + for (i = 0; i < keys.length; ++i) { + _bindSingle(keys[i], i < keys.length - 1 ? _increaseSequence : _callbackAndReset, action, combo, i); + } + } - /** - * @param {number} x Horizontal position of the popup window - * @param {number} y Vertical position of the popup window - */ - Popup.prototype.setPosition = function(x, y) { - this.x = parseInt(x); - this.y = parseInt(y); - }; + /** + * binds a single keyboard combination + * + * @param {string} combination + * @param {Function} callback + * @param {string=} action + * @param {string=} sequence_name - name of sequence if part of sequence + * @param {number=} level - what part of the sequence the command is + * @returns void + */ + function _bindSingle(combination, callback, action, sequence_name, level) { - /** - * Set the text for the popup window. This can be HTML code - * @param {string} text - */ - Popup.prototype.setText = function(text) { - this.frame.innerHTML = text; - }; + // make sure multiple spaces in a row become a single space + combination = combination.replace(/\s+/g, ' '); - /** - * Show the popup window - * @param {boolean} show Optional. Show or hide the window - */ - Popup.prototype.show = function (show) { - if (show === undefined) { - show = true; - } + var sequence = combination.split(' '), + i, + key, + keys, + modifiers = []; - if (show) { - var height = this.frame.clientHeight; - var width = this.frame.clientWidth; - var maxHeight = this.frame.parentNode.clientHeight; - var maxWidth = this.frame.parentNode.clientWidth; + // if this pattern is a sequence of keys then run through this method + // to reprocess each pattern one key at a time + if (sequence.length > 1) { + return _bindSequence(combination, sequence, callback, action); + } - var top = (this.y - height); - if (top + height + this.padding > maxHeight) { - top = maxHeight - height - this.padding; - } - if (top < this.padding) { - top = this.padding; - } + // take the keys from this pattern and figure out what the actual + // pattern is all about + keys = combination === '+' ? ['+'] : combination.split('+'); - var left = this.x; - if (left + width + this.padding > maxWidth) { - left = maxWidth - width - this.padding; - } - if (left < this.padding) { - left = this.padding; - } + for (i = 0; i < keys.length; ++i) { + key = keys[i]; - this.frame.style.left = left + "px"; - this.frame.style.top = top + "px"; - this.frame.style.visibility = "visible"; - } - else { - this.hide(); - } - }; + // normalize key names + if (_SPECIAL_ALIASES[key]) { + key = _SPECIAL_ALIASES[key]; + } - /** - * Hide the popup window - */ - Popup.prototype.hide = function () { - this.frame.style.visibility = "hidden"; - }; + // if this is not a keypress event then we should + // be smart about using shift keys + // this will only work for US keyboards however + if (action && action != 'keypress' && _SHIFT_MAP[key]) { + key = _SHIFT_MAP[key]; + modifiers.push('shift'); + } - module.exports = Popup; + // if this key is a modifier then add it to the list of modifiers + if (_isModifier(key)) { + modifiers.push(key); + } + } + // depending on what the key combination is + // we will try to pick the best event for it + action = _pickBestAction(key, modifiers, action); -/***/ }, -/* 50 */ -/***/ function(module, exports, __webpack_require__) { + // make sure to initialize array if this is the first time + // a callback is added for this key + if (!_callbacks[key]) { + _callbacks[key] = []; + } - var PhysicsMixin = __webpack_require__(51); - var ClusterMixin = __webpack_require__(55); - var SectorsMixin = __webpack_require__(56); - var SelectionMixin = __webpack_require__(57); - var ManipulationMixin = __webpack_require__(58); - var NavigationMixin = __webpack_require__(59); - var HierarchicalLayoutMixin = __webpack_require__(60); + // remove an existing match if there is one + _getMatches(key, modifiers, action, !sequence_name, combination); - /** - * Load a mixin into the network object - * - * @param {Object} sourceVariable | this object has to contain functions. - * @private - */ - exports._loadMixin = function (sourceVariable) { - for (var mixinFunction in sourceVariable) { - if (sourceVariable.hasOwnProperty(mixinFunction)) { - this[mixinFunction] = sourceVariable[mixinFunction]; - } + // add this call back to the array + // if it is a sequence put it at the beginning + // if not put it at the end + // + // this is important because the way these are processed expects + // the sequence ones to come first + _callbacks[key][sequence_name ? 'unshift' : 'push']({ + callback: callback, + modifiers: modifiers, + action: action, + seq: sequence_name, + level: level, + combo: combination + }); } - }; - - /** - * removes a mixin from the network object. - * - * @param {Object} sourceVariable | this object has to contain functions. - * @private - */ - exports._clearMixin = function (sourceVariable) { - for (var mixinFunction in sourceVariable) { - if (sourceVariable.hasOwnProperty(mixinFunction)) { - this[mixinFunction] = undefined; - } + /** + * binds multiple combinations to the same callback + * + * @param {Array} combinations + * @param {Function} callback + * @param {string|undefined} action + * @returns void + */ + function _bindMultiple(combinations, callback, action) { + for (var i = 0; i < combinations.length; ++i) { + _bindSingle(combinations[i], callback, action); + } } - }; + // start! + _addEvent(document, 'keypress', _handleKey); + _addEvent(document, 'keydown', _handleKey); + _addEvent(document, 'keyup', _handleKey); - /** - * Mixin the physics system and initialize the parameters required. - * - * @private - */ - exports._loadPhysicsSystem = function () { - this._loadMixin(PhysicsMixin); - this._loadSelectedForceSolver(); - if (this.constants.configurePhysics == true) { - this._loadPhysicsConfiguration(); - } - }; + var mousetrap = { + + /** + * binds an event to mousetrap + * + * can be a single key, a combination of keys separated with +, + * a comma separated list of keys, an array of keys, or + * a sequence of keys separated by spaces + * + * be sure to list the modifier keys first to make sure that the + * correct key ends up getting bound (the last key in the pattern) + * + * @param {string|Array} keys + * @param {Function} callback + * @param {string=} action - 'keypress', 'keydown', or 'keyup' + * @returns void + */ + bind: function(keys, callback, action) { + _bindMultiple(keys instanceof Array ? keys : [keys], callback, action); + _direct_map[keys + ':' + action] = callback; + return this; + }, + + /** + * unbinds an event to mousetrap + * + * the unbinding sets the callback function of the specified key combo + * to an empty function and deletes the corresponding key in the + * _direct_map dict. + * + * the keycombo+action has to be exactly the same as + * it was defined in the bind method + * + * TODO: actually remove this from the _callbacks dictionary instead + * of binding an empty function + * + * @param {string|Array} keys + * @param {string} action + * @returns void + */ + unbind: function(keys, action) { + if (_direct_map[keys + ':' + action]) { + delete _direct_map[keys + ':' + action]; + this.bind(keys, function() {}, action); + } + return this; + }, + + /** + * triggers an event that has already been bound + * + * @param {string} keys + * @param {string=} action + * @returns void + */ + trigger: function(keys, action) { + _direct_map[keys + ':' + action](); + return this; + }, + + /** + * resets the library back to its initial state. this is useful + * if you want to clear out the current keyboard shortcuts and bind + * new ones - for example if you switch to another page + * + * @returns void + */ + reset: function() { + _callbacks = {}; + _direct_map = {}; + return this; + } + }; + + module.exports = mousetrap; - /** - * Mixin the cluster system and initialize the parameters required. - * - * @private - */ - exports._loadClusterSystem = function () { - this.clusterSession = 0; - this.hubThreshold = 5; - this._loadMixin(ClusterMixin); - }; +/***/ }, +/* 50 */ +/***/ function(module, exports, __webpack_require__) { /** - * Mixin the sector system and initialize the parameters required + * Creation of the ClusterMixin var. * - * @private + * This contains all the functions the Network object can use to employ clustering */ - exports._loadSectorSystem = function () { - this.sectors = {}; - this.activeSector = ["default"]; - this.sectors["active"] = {}; - this.sectors["active"]["default"] = {"nodes": {}, - "edges": {}, - "nodeIndices": [], - "formationScale": 1.0, - "drawingNode": undefined }; - this.sectors["frozen"] = {}; - this.sectors["support"] = {"nodes": {}, - "edges": {}, - "nodeIndices": [], - "formationScale": 1.0, - "drawingNode": undefined }; - this.nodeIndices = this.sectors["active"]["default"]["nodeIndices"]; // the node indices list is used to speed up the computation of the repulsion fields + /** + * This is only called in the constructor of the network object + * + */ + exports.startWithClustering = function() { + // cluster if the data set is big + this.clusterToFit(this.constants.clustering.initialMaxNodes, true); - this._loadMixin(SectorsMixin); - }; + // updates the lables after clustering + this.updateLabels(); + // this is called here because if clusterin is disabled, the start and stabilize are called in + // the setData function. + if (this.stabilize) { + this._stabilize(); + } + this.start(); + }; /** - * Mixin the selection system and initialize the parameters required + * This function clusters until the initialMaxNodes has been reached * - * @private + * @param {Number} maxNumberOfNodes + * @param {Boolean} reposition */ - exports._loadSelectionSystem = function () { - this.selectionObj = {nodes: {}, edges: {}}; + exports.clusterToFit = function(maxNumberOfNodes, reposition) { + var numberOfNodes = this.nodeIndices.length; - this._loadMixin(SelectionMixin); - }; + var maxLevels = 50; + var level = 0; + // we first cluster the hubs, then we pull in the outliers, repeat + while (numberOfNodes > maxNumberOfNodes && level < maxLevels) { + if (level % 3 == 0) { + this.forceAggregateHubs(true); + this.normalizeClusterLevels(); + } + else { + this.increaseClusterLevel(); // this also includes a cluster normalization + } + + numberOfNodes = this.nodeIndices.length; + level += 1; + } + + // after the clustering we reposition the nodes to reduce the initial chaos + if (level > 0 && reposition == true) { + this.repositionNodes(); + } + this._updateCalculationNodes(); + }; /** - * Mixin the navigationUI (User Interface) system and initialize the parameters required + * This function can be called to open up a specific cluster. It is only called by + * It will unpack the cluster back one level. * - * @private + * @param node | Node object: cluster to open. */ - exports._loadManipulationSystem = function () { - // reset global variables -- these are used by the selection of nodes and edges. - this.blockConnectingEdgeSelection = false; - this.forceAppendSelection = false; - - if (this.constants.dataManipulation.enabled == true) { - // load the manipulator HTML elements. All styling done in css. - if (this.manipulationDiv === undefined) { - this.manipulationDiv = document.createElement('div'); - this.manipulationDiv.className = 'network-manipulationDiv'; - this.manipulationDiv.id = 'network-manipulationDiv'; - if (this.editMode == true) { - this.manipulationDiv.style.display = "block"; - } - else { - this.manipulationDiv.style.display = "none"; - } - this.containerElement.insertBefore(this.manipulationDiv, this.frame); - } - - if (this.editModeDiv === undefined) { - this.editModeDiv = document.createElement('div'); - this.editModeDiv.className = 'network-manipulation-editMode'; - this.editModeDiv.id = 'network-manipulation-editMode'; - if (this.editMode == true) { - this.editModeDiv.style.display = "none"; - } - else { - this.editModeDiv.style.display = "block"; - } - this.containerElement.insertBefore(this.editModeDiv, this.frame); - } + exports.openCluster = function(node) { + var isMovingBeforeClustering = this.moving; + if (node.clusterSize > this.constants.clustering.sectorThreshold && this._nodeInActiveArea(node) && + !(this._sector() == "default" && this.nodeIndices.length == 1)) { + // this loads a new sector, loads the nodes and edges and nodeIndices of it. + this._addSector(node); + var level = 0; - if (this.closeDiv === undefined) { - this.closeDiv = document.createElement('div'); - this.closeDiv.className = 'network-manipulation-closeDiv'; - this.closeDiv.id = 'network-manipulation-closeDiv'; - this.closeDiv.style.display = this.manipulationDiv.style.display; - this.containerElement.insertBefore(this.closeDiv, this.frame); + // we decluster until we reach a decent number of nodes + while ((this.nodeIndices.length < this.constants.clustering.initialMaxNodes) && (level < 10)) { + this.decreaseClusterLevel(); + level += 1; } - // load the manipulation functions - this._loadMixin(ManipulationMixin); - - // create the manipulator toolbar - this._createManipulatorBar(); } else { - if (this.manipulationDiv !== undefined) { - // removes all the bindings and overloads - this._createManipulatorBar(); - // remove the manipulation divs - this.containerElement.removeChild(this.manipulationDiv); - this.containerElement.removeChild(this.editModeDiv); - this.containerElement.removeChild(this.closeDiv); + this._expandClusterNode(node,false,true); - this.manipulationDiv = undefined; - this.editModeDiv = undefined; - this.closeDiv = undefined; - // remove the mixin functions - this._clearMixin(ManipulationMixin); - } + // update the index list, dynamic edges and labels + this._updateNodeIndexList(); + this._updateDynamicEdges(); + this._updateCalculationNodes(); + this.updateLabels(); + } + + // if the simulation was settled, we restart the simulation if a cluster has been formed or expanded + if (this.moving != isMovingBeforeClustering) { + this.start(); } }; /** - * Mixin the navigation (User Interface) system and initialize the parameters required - * - * @private + * This calls the updateClustes with default arguments */ - exports._loadNavigationControls = function () { - this._loadMixin(NavigationMixin); - - // the clean function removes the button divs, this is done to remove the bindings. - this._cleanNavigation(); - if (this.constants.navigation.enabled == true) { - this._loadNavigationElements(); + exports.updateClustersDefault = function() { + if (this.constants.clustering.enabled == true) { + this.updateClusters(0,false,false); } }; /** - * Mixin the hierarchical layout system. - * - * @private + * This function can be called to increase the cluster level. This means that the nodes with only one edge connection will + * be clustered with their connected node. This can be repeated as many times as needed. + * This can be called externally (by a keybind for instance) to reduce the complexity of big datasets. */ - exports._loadHierarchySystem = function () { - this._loadMixin(HierarchicalLayoutMixin); + exports.increaseClusterLevel = function() { + this.updateClusters(-1,false,true); }; -/***/ }, -/* 51 */ -/***/ function(module, exports, __webpack_require__) { - - var util = __webpack_require__(1); - var RepulsionMixin = __webpack_require__(52); - var HierarchialRepulsionMixin = __webpack_require__(53); - var BarnesHutMixin = __webpack_require__(54); - /** - * Toggling barnes Hut calculation on and off. - * - * @private + * This function can be called to decrease the cluster level. This means that the nodes with only one edge connection will + * be unpacked if they are a cluster. This can be repeated as many times as needed. + * This can be called externally (by a key-bind for instance) to look into clusters without zooming. */ - exports._toggleBarnesHut = function () { - this.constants.physics.barnesHut.enabled = !this.constants.physics.barnesHut.enabled; - this._loadSelectedForceSolver(); - this.moving = true; - this.start(); + exports.decreaseClusterLevel = function() { + this.updateClusters(1,false,true); }; /** - * This loads the node force solver based on the barnes hut or repulsion algorithm + * This is the main clustering function. It clusters and declusters on zoom or forced + * This function clusters on zoom, it can be called with a predefined zoom direction + * If out, check if we can form clusters, if in, check if we can open clusters. + * This function is only called from _zoom() + * + * @param {Number} zoomDirection | -1 / 0 / +1 for zoomOut / determineByZoom / zoomIn + * @param {Boolean} recursive | enabled or disable recursive calling of the opening of clusters + * @param {Boolean} force | enabled or disable forcing + * @param {Boolean} doNotStart | if true do not call start * - * @private */ - exports._loadSelectedForceSolver = function () { - // this overloads the this._calculateNodeForces - if (this.constants.physics.barnesHut.enabled == true) { - this._clearMixin(RepulsionMixin); - this._clearMixin(HierarchialRepulsionMixin); + exports.updateClusters = function(zoomDirection,recursive,force,doNotStart) { + var isMovingBeforeClustering = this.moving; + var amountOfNodes = this.nodeIndices.length; - this.constants.physics.centralGravity = this.constants.physics.barnesHut.centralGravity; - this.constants.physics.springLength = this.constants.physics.barnesHut.springLength; - this.constants.physics.springConstant = this.constants.physics.barnesHut.springConstant; - this.constants.physics.damping = this.constants.physics.barnesHut.damping; + // on zoom out collapse the sector if the scale is at the level the sector was made + if (this.previousScale > this.scale && zoomDirection == 0) { + this._collapseSector(); + } - this._loadMixin(BarnesHutMixin); + // check if we zoom in or out + if (this.previousScale > this.scale || zoomDirection == -1) { // zoom out + // forming clusters when forced pulls outliers in. When not forced, the edge length of the + // outer nodes determines if it is being clustered + this._formClusters(force); } - else if (this.constants.physics.hierarchicalRepulsion.enabled == true) { - this._clearMixin(BarnesHutMixin); - this._clearMixin(RepulsionMixin); + else if (this.previousScale < this.scale || zoomDirection == 1) { // zoom in + if (force == true) { + // _openClusters checks for each node if the formationScale of the cluster is smaller than + // the current scale and if so, declusters. When forced, all clusters are reduced by one step + this._openClusters(recursive,force); + } + else { + // if a cluster takes up a set percentage of the active window + this._openClustersBySize(); + } + } + this._updateNodeIndexList(); - this.constants.physics.centralGravity = this.constants.physics.hierarchicalRepulsion.centralGravity; - this.constants.physics.springLength = this.constants.physics.hierarchicalRepulsion.springLength; - this.constants.physics.springConstant = this.constants.physics.hierarchicalRepulsion.springConstant; - this.constants.physics.damping = this.constants.physics.hierarchicalRepulsion.damping; + // if a cluster was NOT formed and the user zoomed out, we try clustering by hubs + if (this.nodeIndices.length == amountOfNodes && (this.previousScale > this.scale || zoomDirection == -1)) { + this._aggregateHubs(force); + this._updateNodeIndexList(); + } - this._loadMixin(HierarchialRepulsionMixin); + // we now reduce chains. + if (this.previousScale > this.scale || zoomDirection == -1) { // zoom out + this.handleChains(); + this._updateNodeIndexList(); } - else { - this._clearMixin(BarnesHutMixin); - this._clearMixin(HierarchialRepulsionMixin); - this.barnesHutTree = undefined; - this.constants.physics.centralGravity = this.constants.physics.repulsion.centralGravity; - this.constants.physics.springLength = this.constants.physics.repulsion.springLength; - this.constants.physics.springConstant = this.constants.physics.repulsion.springConstant; - this.constants.physics.damping = this.constants.physics.repulsion.damping; + this.previousScale = this.scale; - this._loadMixin(RepulsionMixin); - } - }; + // rest of the update the index list, dynamic edges and labels + this._updateDynamicEdges(); + this.updateLabels(); - /** - * Before calculating the forces, we check if we need to cluster to keep up performance and we check - * if there is more than one node. If it is just one node, we dont calculate anything. - * - * @private - */ - exports._initializeForceCalculation = function () { - // stop calculation if there is only one node - if (this.nodeIndices.length == 1) { - this.nodes[this.nodeIndices[0]]._setForce(0, 0); + // if a cluster was formed, we increase the clusterSession + if (this.nodeIndices.length < amountOfNodes) { // this means a clustering operation has taken place + this.clusterSession += 1; + // if clusters have been made, we normalize the cluster level + this.normalizeClusterLevels(); } - else { - // if there are too many nodes on screen, we cluster without repositioning - if (this.nodeIndices.length > this.constants.clustering.clusterThreshold && this.constants.clustering.enabled == true) { - this.clusterToFit(this.constants.clustering.reduceToNodes, false); - } - // we now start the force calculation - this._calculateForces(); + if (doNotStart == false || doNotStart === undefined) { + // if the simulation was settled, we restart the simulation if a cluster has been formed or expanded + if (this.moving != isMovingBeforeClustering) { + this.start(); + } } - }; + this._updateCalculationNodes(); + }; /** - * Calculate the external forces acting on the nodes - * Forces are caused by: edges, repulsing forces between nodes, gravity - * @private + * This function handles the chains. It is called on every updateClusters(). */ - exports._calculateForces = function () { - // Gravity is required to keep separated groups from floating off - // the forces are reset to zero in this loop by using _setForce instead - // of _addForce - - this._calculateGravitationalForces(); - this._calculateNodeForces(); + exports.handleChains = function() { + // after clustering we check how many chains there are + var chainPercentage = this._getChainFraction(); + if (chainPercentage > this.constants.clustering.chainThreshold) { + this._reduceAmountOfChains(1 - this.constants.clustering.chainThreshold / chainPercentage) - if (this.constants.physics.springConstant > 0) { - if (this.constants.smoothCurves.enabled == true && this.constants.smoothCurves.dynamic == true) { - this._calculateSpringForcesWithSupport(); - } - else { - if (this.constants.physics.hierarchicalRepulsion.enabled == true) { - this._calculateHierarchicalSpringForces(); - } - else { - this._calculateSpringForces(); - } - } } }; - /** - * Smooth curves are created by adding invisible nodes in the center of the edges. These nodes are also - * handled in the calculateForces function. We then use a quadratic curve with the center node as control. - * This function joins the datanodes and invisible (called support) nodes into one object. - * We do this so we do not contaminate this.nodes with the support nodes. + * this functions starts clustering by hubs + * The minimum hub threshold is set globally * * @private */ - exports._updateCalculationNodes = function () { - if (this.constants.smoothCurves.enabled == true && this.constants.smoothCurves.dynamic == true) { - this.calculationNodes = {}; - this.calculationNodeIndices = []; - - for (var nodeId in this.nodes) { - if (this.nodes.hasOwnProperty(nodeId)) { - this.calculationNodes[nodeId] = this.nodes[nodeId]; - } - } - var supportNodes = this.sectors['support']['nodes']; - for (var supportNodeId in supportNodes) { - if (supportNodes.hasOwnProperty(supportNodeId)) { - if (this.edges.hasOwnProperty(supportNodes[supportNodeId].parentEdgeId)) { - this.calculationNodes[supportNodeId] = supportNodes[supportNodeId]; - } - else { - supportNodes[supportNodeId]._setForce(0, 0); - } - } - } - - for (var idx in this.calculationNodes) { - if (this.calculationNodes.hasOwnProperty(idx)) { - this.calculationNodeIndices.push(idx); - } - } - } - else { - this.calculationNodes = this.nodes; - this.calculationNodeIndices = this.nodeIndices; - } + exports._aggregateHubs = function(force) { + this._getHubSize(); + this._formClustersByHub(force,false); }; /** - * this function applies the central gravity effect to keep groups from floating off + * This function is fired by keypress. It forces hubs to form. * - * @private */ - exports._calculateGravitationalForces = function () { - var dx, dy, distance, node, i; - var nodes = this.calculationNodes; - var gravity = this.constants.physics.centralGravity; - var gravityForce = 0; + exports.forceAggregateHubs = function(doNotStart) { + var isMovingBeforeClustering = this.moving; + var amountOfNodes = this.nodeIndices.length; - for (i = 0; i < this.calculationNodeIndices.length; i++) { - node = nodes[this.calculationNodeIndices[i]]; - node.damping = this.constants.physics.damping; // possibly add function to alter damping properties of clusters. - // gravity does not apply when we are in a pocket sector - if (this._sector() == "default" && gravity != 0) { - dx = -node.x; - dy = -node.y; - distance = Math.sqrt(dx * dx + dy * dy); + this._aggregateHubs(true); - gravityForce = (distance == 0) ? 0 : (gravity / distance); - node.fx = dx * gravityForce; - node.fy = dy * gravityForce; - } - else { - node.fx = 0; - node.fy = 0; + // update the index list, dynamic edges and labels + this._updateNodeIndexList(); + this._updateDynamicEdges(); + this.updateLabels(); + + // if a cluster was formed, we increase the clusterSession + if (this.nodeIndices.length != amountOfNodes) { + this.clusterSession += 1; + } + + if (doNotStart == false || doNotStart === undefined) { + // if the simulation was settled, we restart the simulation if a cluster has been formed or expanded + if (this.moving != isMovingBeforeClustering) { + this.start(); } } }; - - - /** - * this function calculates the effects of the springs in the case of unsmooth curves. + * If a cluster takes up more than a set percentage of the screen, open the cluster * * @private */ - exports._calculateSpringForces = function () { - var edgeLength, edge, edgeId; - var dx, dy, fx, fy, springForce, distance; - var edges = this.edges; - - // forces caused by the edges, modelled as springs - for (edgeId in edges) { - if (edges.hasOwnProperty(edgeId)) { - edge = edges[edgeId]; - if (edge.connected) { - // only calculate forces if nodes are in the same sector - if (this.nodes.hasOwnProperty(edge.toId) && this.nodes.hasOwnProperty(edge.fromId)) { - edgeLength = edge.physics.springLength; - // this implies that the edges between big clusters are longer - edgeLength += (edge.to.clusterSize + edge.from.clusterSize - 2) * this.constants.clustering.edgeGrowth; - - dx = (edge.from.x - edge.to.x); - dy = (edge.from.y - edge.to.y); - distance = Math.sqrt(dx * dx + dy * dy); - - if (distance == 0) { - distance = 0.01; - } - - // the 1/distance is so the fx and fy can be calculated without sine or cosine. - springForce = this.constants.physics.springConstant * (edgeLength - distance) / distance; - - fx = dx * springForce; - fy = dy * springForce; - - edge.from.fx += fx; - edge.from.fy += fy; - edge.to.fx -= fx; - edge.to.fy -= fy; + exports._openClustersBySize = function() { + for (var nodeId in this.nodes) { + if (this.nodes.hasOwnProperty(nodeId)) { + var node = this.nodes[nodeId]; + if (node.inView() == true) { + if ((node.width*this.scale > this.constants.clustering.screenSizeThreshold * this.frame.canvas.clientWidth) || + (node.height*this.scale > this.constants.clustering.screenSizeThreshold * this.frame.canvas.clientHeight)) { + this.openCluster(node); } } } @@ -26026,37 +26260,59 @@ return /******/ (function(modules) { // webpackBootstrap }; - - /** - * This function calculates the springforces on the nodes, accounting for the support nodes. + * This function loops over all nodes in the nodeIndices list. For each node it checks if it is a cluster and if it + * has to be opened based on the current zoom level. * * @private */ - exports._calculateSpringForcesWithSupport = function () { - var edgeLength, edge, edgeId, combinedClusterSize; - var edges = this.edges; - - // forces caused by the edges, modelled as springs - for (edgeId in edges) { - if (edges.hasOwnProperty(edgeId)) { - edge = edges[edgeId]; - if (edge.connected) { - // only calculate forces if nodes are in the same sector - if (this.nodes.hasOwnProperty(edge.toId) && this.nodes.hasOwnProperty(edge.fromId)) { - if (edge.via != null) { - var node1 = edge.to; - var node2 = edge.via; - var node3 = edge.from; + exports._openClusters = function(recursive,force) { + for (var i = 0; i < this.nodeIndices.length; i++) { + var node = this.nodes[this.nodeIndices[i]]; + this._expandClusterNode(node,recursive,force); + this._updateCalculationNodes(); + } + }; - edgeLength = edge.physics.springLength; + /** + * This function checks if a node has to be opened. This is done by checking the zoom level. + * If the node contains child nodes, this function is recursively called on the child nodes as well. + * This recursive behaviour is optional and can be set by the recursive argument. + * + * @param {Node} parentNode | to check for cluster and expand + * @param {Boolean} recursive | enabled or disable recursive calling + * @param {Boolean} force | enabled or disable forcing + * @param {Boolean} [openAll] | This will recursively force all nodes in the parent to be released + * @private + */ + exports._expandClusterNode = function(parentNode, recursive, force, openAll) { + // first check if node is a cluster + if (parentNode.clusterSize > 1) { + // this means that on a double tap event or a zoom event, the cluster fully unpacks if it is smaller than 20 + if (parentNode.clusterSize < this.constants.clustering.sectorThreshold) { + openAll = true; + } + recursive = openAll ? true : recursive; - combinedClusterSize = node1.clusterSize + node3.clusterSize - 2; + // if the last child has been added on a smaller scale than current scale decluster + if (parentNode.formationScale < this.scale || force == true) { + // we will check if any of the contained child nodes should be removed from the cluster + for (var containedNodeId in parentNode.containedNodes) { + if (parentNode.containedNodes.hasOwnProperty(containedNodeId)) { + var childNode = parentNode.containedNodes[containedNodeId]; - // this implies that the edges between big clusters are longer - edgeLength += combinedClusterSize * this.constants.clustering.edgeGrowth; - this._calculateSpringForce(node1, node2, 0.5 * edgeLength); - this._calculateSpringForce(node2, node3, 0.5 * edgeLength); + // force expand will expand the largest cluster size clusters. Since we cluster from outside in, we assume that + // the largest cluster is the one that comes from outside + if (force == true) { + if (childNode.clusterSession == parentNode.clusterSessions[parentNode.clusterSessions.length-1] + || openAll) { + this._expelChildFromParent(parentNode,containedNodeId,recursive,force,openAll); + } + } + else { + if (this._nodeInActiveArea(parentNode)) { + this._expelChildFromParent(parentNode,containedNodeId,recursive,force,openAll); + } } } } @@ -26064,4056 +26320,3934 @@ return /******/ (function(modules) { // webpackBootstrap } }; - /** - * This is the code actually performing the calculation for the function above. It is split out to avoid repetition. + * ONLY CALLED FROM _expandClusterNode * - * @param node1 - * @param node2 - * @param edgeLength + * This function will expel a child_node from a parent_node. This is to de-cluster the node. This function will remove + * the child node from the parent contained_node object and put it back into the global nodes object. + * The same holds for the edge that was connected to the child node. It is moved back into the global edges object. + * + * @param {Node} parentNode | the parent node + * @param {String} containedNodeId | child_node id as it is contained in the containedNodes object of the parent node + * @param {Boolean} recursive | This will also check if the child needs to be expanded. + * With force and recursive both true, the entire cluster is unpacked + * @param {Boolean} force | This will disregard the zoom level and will expel this child from the parent + * @param {Boolean} openAll | This will recursively force all nodes in the parent to be released * @private */ - exports._calculateSpringForce = function (node1, node2, edgeLength) { - var dx, dy, fx, fy, springForce, distance; - - dx = (node1.x - node2.x); - dy = (node1.y - node2.y); - distance = Math.sqrt(dx * dx + dy * dy); - - if (distance == 0) { - distance = 0.01; - } - - // the 1/distance is so the fx and fy can be calculated without sine or cosine. - springForce = this.constants.physics.springConstant * (edgeLength - distance) / distance; - - fx = dx * springForce; - fy = dy * springForce; - - node1.fx += fx; - node1.fy += fy; - node2.fx -= fx; - node2.fy -= fy; - }; + exports._expelChildFromParent = function(parentNode, containedNodeId, recursive, force, openAll) { + var childNode = parentNode.containedNodes[containedNodeId]; + // if child node has been added on smaller scale than current, kick out + if (childNode.formationScale < this.scale || force == true) { + // unselect all selected items + this._unselectAll(); - /** - * Load the HTML for the physics config and bind it - * @private - */ - exports._loadPhysicsConfiguration = function () { - if (this.physicsConfiguration === undefined) { - this.backupConstants = {}; - util.deepExtend(this.backupConstants,this.constants); + // put the child node back in the global nodes object + this.nodes[containedNodeId] = childNode; - var hierarchicalLayoutDirections = ["LR", "RL", "UD", "DU"]; - this.physicsConfiguration = document.createElement('div'); - this.physicsConfiguration.className = "PhysicsConfiguration"; - this.physicsConfiguration.innerHTML = '' + - '' + - '' + - '' + - '' + - '' + - '' + - '
Simulation Mode:
Barnes HutRepulsionHierarchical
' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '
Options:
' - this.containerElement.parentElement.insertBefore(this.physicsConfiguration, this.containerElement); - this.optionsDiv = document.createElement("div"); - this.optionsDiv.style.fontSize = "14px"; - this.optionsDiv.style.fontFamily = "verdana"; - this.containerElement.parentElement.insertBefore(this.optionsDiv, this.containerElement); + // release the contained edges from this childNode back into the global edges + this._releaseContainedEdges(parentNode,childNode); - var rangeElement; - rangeElement = document.getElementById('graph_BH_gc'); - rangeElement.onchange = showValueOfRange.bind(this, 'graph_BH_gc', -1, "physics_barnesHut_gravitationalConstant"); - rangeElement = document.getElementById('graph_BH_cg'); - rangeElement.onchange = showValueOfRange.bind(this, 'graph_BH_cg', 1, "physics_centralGravity"); - rangeElement = document.getElementById('graph_BH_sc'); - rangeElement.onchange = showValueOfRange.bind(this, 'graph_BH_sc', 1, "physics_springConstant"); - rangeElement = document.getElementById('graph_BH_sl'); - rangeElement.onchange = showValueOfRange.bind(this, 'graph_BH_sl', 1, "physics_springLength"); - rangeElement = document.getElementById('graph_BH_damp'); - rangeElement.onchange = showValueOfRange.bind(this, 'graph_BH_damp', 1, "physics_damping"); + // reconnect rerouted edges to the childNode + this._connectEdgeBackToChild(parentNode,childNode); - rangeElement = document.getElementById('graph_R_nd'); - rangeElement.onchange = showValueOfRange.bind(this, 'graph_R_nd', 1, "physics_repulsion_nodeDistance"); - rangeElement = document.getElementById('graph_R_cg'); - rangeElement.onchange = showValueOfRange.bind(this, 'graph_R_cg', 1, "physics_centralGravity"); - rangeElement = document.getElementById('graph_R_sc'); - rangeElement.onchange = showValueOfRange.bind(this, 'graph_R_sc', 1, "physics_springConstant"); - rangeElement = document.getElementById('graph_R_sl'); - rangeElement.onchange = showValueOfRange.bind(this, 'graph_R_sl', 1, "physics_springLength"); - rangeElement = document.getElementById('graph_R_damp'); - rangeElement.onchange = showValueOfRange.bind(this, 'graph_R_damp', 1, "physics_damping"); + // validate all edges in dynamicEdges + this._validateEdges(parentNode); - rangeElement = document.getElementById('graph_H_nd'); - rangeElement.onchange = showValueOfRange.bind(this, 'graph_H_nd', 1, "physics_hierarchicalRepulsion_nodeDistance"); - rangeElement = document.getElementById('graph_H_cg'); - rangeElement.onchange = showValueOfRange.bind(this, 'graph_H_cg', 1, "physics_centralGravity"); - rangeElement = document.getElementById('graph_H_sc'); - rangeElement.onchange = showValueOfRange.bind(this, 'graph_H_sc', 1, "physics_springConstant"); - rangeElement = document.getElementById('graph_H_sl'); - rangeElement.onchange = showValueOfRange.bind(this, 'graph_H_sl', 1, "physics_springLength"); - rangeElement = document.getElementById('graph_H_damp'); - rangeElement.onchange = showValueOfRange.bind(this, 'graph_H_damp', 1, "physics_damping"); - rangeElement = document.getElementById('graph_H_direction'); - rangeElement.onchange = showValueOfRange.bind(this, 'graph_H_direction', hierarchicalLayoutDirections, "hierarchicalLayout_direction"); - rangeElement = document.getElementById('graph_H_levsep'); - rangeElement.onchange = showValueOfRange.bind(this, 'graph_H_levsep', 1, "hierarchicalLayout_levelSeparation"); - rangeElement = document.getElementById('graph_H_nspac'); - rangeElement.onchange = showValueOfRange.bind(this, 'graph_H_nspac', 1, "hierarchicalLayout_nodeSpacing"); + // undo the changes from the clustering operation on the parent node + parentNode.options.mass -= childNode.options.mass; + parentNode.clusterSize -= childNode.clusterSize; + parentNode.options.fontSize = Math.min(this.constants.clustering.maxFontSize, this.constants.nodes.fontSize + this.constants.clustering.fontSizeMultiplier*parentNode.clusterSize); + parentNode.dynamicEdgesLength = parentNode.dynamicEdges.length; - var radioButton1 = document.getElementById("graph_physicsMethod1"); - var radioButton2 = document.getElementById("graph_physicsMethod2"); - var radioButton3 = document.getElementById("graph_physicsMethod3"); - radioButton2.checked = true; - if (this.constants.physics.barnesHut.enabled) { - radioButton1.checked = true; - } - if (this.constants.hierarchicalLayout.enabled) { - radioButton3.checked = true; - } + // place the child node near the parent, not at the exact same location to avoid chaos in the system + childNode.x = parentNode.x + parentNode.growthIndicator * (0.5 - Math.random()); + childNode.y = parentNode.y + parentNode.growthIndicator * (0.5 - Math.random()); - var graph_toggleSmooth = document.getElementById("graph_toggleSmooth"); - var graph_repositionNodes = document.getElementById("graph_repositionNodes"); - var graph_generateOptions = document.getElementById("graph_generateOptions"); + // remove node from the list + delete parentNode.containedNodes[containedNodeId]; - graph_toggleSmooth.onclick = graphToggleSmoothCurves.bind(this); - graph_repositionNodes.onclick = graphRepositionNodes.bind(this); - graph_generateOptions.onclick = graphGenerateOptions.bind(this); - if (this.constants.smoothCurves == true && this.constants.dynamicSmoothCurves == false) { - graph_toggleSmooth.style.background = "#A4FF56"; - } - else { - graph_toggleSmooth.style.background = "#FF8532"; + // check if there are other childs with this clusterSession in the parent. + var othersPresent = false; + for (var childNodeId in parentNode.containedNodes) { + if (parentNode.containedNodes.hasOwnProperty(childNodeId)) { + if (parentNode.containedNodes[childNodeId].clusterSession == childNode.clusterSession) { + othersPresent = true; + break; + } + } + } + // if there are no others, remove the cluster session from the list + if (othersPresent == false) { + parentNode.clusterSessions.pop(); } + this._repositionBezierNodes(childNode); + // this._repositionBezierNodes(parentNode); - switchConfigurations.apply(this); + // remove the clusterSession from the child node + childNode.clusterSession = 0; - radioButton1.onchange = switchConfigurations.bind(this); - radioButton2.onchange = switchConfigurations.bind(this); - radioButton3.onchange = switchConfigurations.bind(this); + // recalculate the size of the node on the next time the node is rendered + parentNode.clearSizeCache(); + + // restart the simulation to reorganise all nodes + this.moving = true; + } + + // check if a further expansion step is possible if recursivity is enabled + if (recursive == true) { + this._expandClusterNode(childNode,recursive,force,openAll); } }; + /** - * This overwrites the this.constants. + * position the bezier nodes at the center of the edges * - * @param constantsVariableName - * @param value + * @param node * @private */ - exports._overWriteGraphConstants = function (constantsVariableName, value) { - var nameArray = constantsVariableName.split("_"); - if (nameArray.length == 1) { - this.constants[nameArray[0]] = value; - } - else if (nameArray.length == 2) { - this.constants[nameArray[0]][nameArray[1]] = value; - } - else if (nameArray.length == 3) { - this.constants[nameArray[0]][nameArray[1]][nameArray[2]] = value; + exports._repositionBezierNodes = function(node) { + for (var i = 0; i < node.dynamicEdges.length; i++) { + node.dynamicEdges[i].positionBezierNode(); } }; /** - * this function is bound to the toggle smooth curves button. That is also why it is not in the prototype. - */ - function graphToggleSmoothCurves () { - this.constants.smoothCurves.enabled = !this.constants.smoothCurves.enabled; - var graph_toggleSmooth = document.getElementById("graph_toggleSmooth"); - if (this.constants.smoothCurves.enabled == true) {graph_toggleSmooth.style.background = "#A4FF56";} - else {graph_toggleSmooth.style.background = "#FF8532";} - - this._configureSmoothCurves(false); - } - - /** - * this function is used to scramble the nodes + * This function checks if any nodes at the end of their trees have edges below a threshold length + * This function is called only from updateClusters() + * forceLevelCollapse ignores the length of the edge and collapses one level + * This means that a node with only one edge will be clustered with its connected node * + * @private + * @param {Boolean} force */ - function graphRepositionNodes () { - for (var nodeId in this.calculationNodes) { - if (this.calculationNodes.hasOwnProperty(nodeId)) { - this.calculationNodes[nodeId].vx = 0; this.calculationNodes[nodeId].vy = 0; - this.calculationNodes[nodeId].fx = 0; this.calculationNodes[nodeId].fy = 0; - } - } - if (this.constants.hierarchicalLayout.enabled == true) { - this._setupHierarchicalLayout(); - showValueOfRange.call(this, 'graph_H_nd', 1, "physics_hierarchicalRepulsion_nodeDistance"); - showValueOfRange.call(this, 'graph_H_cg', 1, "physics_centralGravity"); - showValueOfRange.call(this, 'graph_H_sc', 1, "physics_springConstant"); - showValueOfRange.call(this, 'graph_H_sl', 1, "physics_springLength"); - showValueOfRange.call(this, 'graph_H_damp', 1, "physics_damping"); + exports._formClusters = function(force) { + if (force == false) { + this._formClustersByZoom(); } else { - this.repositionNodes(); + this._forceClustersByZoom(); } - this.moving = true; - this.start(); - } + }; + /** - * this is used to generate an options file from the playing with physics system. + * This function handles the clustering by zooming out, this is based on a minimum edge distance + * + * @private */ - function graphGenerateOptions () { - var options = "No options are required, default values used."; - var optionsSpecific = []; - var radioButton1 = document.getElementById("graph_physicsMethod1"); - var radioButton2 = document.getElementById("graph_physicsMethod2"); - if (radioButton1.checked == true) { - if (this.constants.physics.barnesHut.gravitationalConstant != this.backupConstants.physics.barnesHut.gravitationalConstant) {optionsSpecific.push("gravitationalConstant: " + this.constants.physics.barnesHut.gravitationalConstant);} - if (this.constants.physics.centralGravity != this.backupConstants.physics.barnesHut.centralGravity) {optionsSpecific.push("centralGravity: " + this.constants.physics.centralGravity);} - if (this.constants.physics.springLength != this.backupConstants.physics.barnesHut.springLength) {optionsSpecific.push("springLength: " + this.constants.physics.springLength);} - if (this.constants.physics.springConstant != this.backupConstants.physics.barnesHut.springConstant) {optionsSpecific.push("springConstant: " + this.constants.physics.springConstant);} - if (this.constants.physics.damping != this.backupConstants.physics.barnesHut.damping) {optionsSpecific.push("damping: " + this.constants.physics.damping);} - if (optionsSpecific.length != 0) { - options = "var options = {"; - options += "physics: {barnesHut: {"; - for (var i = 0; i < optionsSpecific.length; i++) { - options += optionsSpecific[i]; - if (i < optionsSpecific.length - 1) { - options += ", " - } - } - options += '}}' - } - if (this.constants.smoothCurves.enabled != this.backupConstants.smoothCurves.enabled) { - if (optionsSpecific.length == 0) {options = "var options = {";} - else {options += ", "} - options += "smoothCurves: " + this.constants.smoothCurves.enabled; - } - if (options != "No options are required, default values used.") { - options += '};' - } - } - else if (radioButton2.checked == true) { - options = "var options = {"; - options += "physics: {barnesHut: {enabled: false}"; - if (this.constants.physics.repulsion.nodeDistance != this.backupConstants.physics.repulsion.nodeDistance) {optionsSpecific.push("nodeDistance: " + this.constants.physics.repulsion.nodeDistance);} - if (this.constants.physics.centralGravity != this.backupConstants.physics.repulsion.centralGravity) {optionsSpecific.push("centralGravity: " + this.constants.physics.centralGravity);} - if (this.constants.physics.springLength != this.backupConstants.physics.repulsion.springLength) {optionsSpecific.push("springLength: " + this.constants.physics.springLength);} - if (this.constants.physics.springConstant != this.backupConstants.physics.repulsion.springConstant) {optionsSpecific.push("springConstant: " + this.constants.physics.springConstant);} - if (this.constants.physics.damping != this.backupConstants.physics.repulsion.damping) {optionsSpecific.push("damping: " + this.constants.physics.damping);} - if (optionsSpecific.length != 0) { - options += ", repulsion: {"; - for (var i = 0; i < optionsSpecific.length; i++) { - options += optionsSpecific[i]; - if (i < optionsSpecific.length - 1) { - options += ", " - } - } - options += '}}' - } - if (optionsSpecific.length == 0) {options += "}"} - if (this.constants.smoothCurves != this.backupConstants.smoothCurves) { - options += ", smoothCurves: " + this.constants.smoothCurves; - } - options += '};' - } - else { - options = "var options = {"; - if (this.constants.physics.hierarchicalRepulsion.nodeDistance != this.backupConstants.physics.hierarchicalRepulsion.nodeDistance) {optionsSpecific.push("nodeDistance: " + this.constants.physics.hierarchicalRepulsion.nodeDistance);} - if (this.constants.physics.centralGravity != this.backupConstants.physics.hierarchicalRepulsion.centralGravity) {optionsSpecific.push("centralGravity: " + this.constants.physics.centralGravity);} - if (this.constants.physics.springLength != this.backupConstants.physics.hierarchicalRepulsion.springLength) {optionsSpecific.push("springLength: " + this.constants.physics.springLength);} - if (this.constants.physics.springConstant != this.backupConstants.physics.hierarchicalRepulsion.springConstant) {optionsSpecific.push("springConstant: " + this.constants.physics.springConstant);} - if (this.constants.physics.damping != this.backupConstants.physics.hierarchicalRepulsion.damping) {optionsSpecific.push("damping: " + this.constants.physics.damping);} - if (optionsSpecific.length != 0) { - options += "physics: {hierarchicalRepulsion: {"; - for (var i = 0; i < optionsSpecific.length; i++) { - options += optionsSpecific[i]; - if (i < optionsSpecific.length - 1) { - options += ", "; - } - } - options += '}},'; - } - options += 'hierarchicalLayout: {'; - optionsSpecific = []; - if (this.constants.hierarchicalLayout.direction != this.backupConstants.hierarchicalLayout.direction) {optionsSpecific.push("direction: " + this.constants.hierarchicalLayout.direction);} - if (Math.abs(this.constants.hierarchicalLayout.levelSeparation) != this.backupConstants.hierarchicalLayout.levelSeparation) {optionsSpecific.push("levelSeparation: " + this.constants.hierarchicalLayout.levelSeparation);} - if (this.constants.hierarchicalLayout.nodeSpacing != this.backupConstants.hierarchicalLayout.nodeSpacing) {optionsSpecific.push("nodeSpacing: " + this.constants.hierarchicalLayout.nodeSpacing);} - if (optionsSpecific.length != 0) { - for (var i = 0; i < optionsSpecific.length; i++) { - options += optionsSpecific[i]; - if (i < optionsSpecific.length - 1) { - options += ", " + exports._formClustersByZoom = function() { + var dx,dy,length, + minLength = this.constants.clustering.clusterEdgeThreshold/this.scale; + + // check if any edges are shorter than minLength and start the clustering + // the clustering favours the node with the larger mass + for (var edgeId in this.edges) { + if (this.edges.hasOwnProperty(edgeId)) { + var edge = this.edges[edgeId]; + if (edge.connected) { + if (edge.toId != edge.fromId) { + dx = (edge.to.x - edge.from.x); + dy = (edge.to.y - edge.from.y); + length = Math.sqrt(dx * dx + dy * dy); + + + if (length < minLength) { + // first check which node is larger + var parentNode = edge.from; + var childNode = edge.to; + if (edge.to.options.mass > edge.from.options.mass) { + parentNode = edge.to; + childNode = edge.from; + } + + if (childNode.dynamicEdgesLength == 1) { + this._addToCluster(parentNode,childNode,false); + } + else if (parentNode.dynamicEdgesLength == 1) { + this._addToCluster(childNode,parentNode,false); + } + } } } - options += '}' - } - else { - options += "enabled:true}"; } - options += '};' } - - - this.optionsDiv.innerHTML = options; - } + }; /** - * this is used to switch between barnesHut, repulsion and hierarchical. + * This function forces the network to cluster all nodes with only one connecting edge to their + * connected node. * + * @private */ - function switchConfigurations () { - var ids = ["graph_BH_table", "graph_R_table", "graph_H_table"]; - var radioButton = document.querySelector('input[name="graph_physicsMethod"]:checked').value; - var tableId = "graph_" + radioButton + "_table"; - var table = document.getElementById(tableId); - table.style.display = "block"; - for (var i = 0; i < ids.length; i++) { - if (ids[i] != tableId) { - table = document.getElementById(ids[i]); - table.style.display = "none"; - } - } - this._restoreNodes(); - if (radioButton == "R") { - this.constants.hierarchicalLayout.enabled = false; - this.constants.physics.hierarchicalRepulsion.enabled = false; - this.constants.physics.barnesHut.enabled = false; - } - else if (radioButton == "H") { - if (this.constants.hierarchicalLayout.enabled == false) { - this.constants.hierarchicalLayout.enabled = true; - this.constants.physics.hierarchicalRepulsion.enabled = true; - this.constants.physics.barnesHut.enabled = false; - this.constants.smoothCurves.enabled = false; - this._setupHierarchicalLayout(); + exports._forceClustersByZoom = function() { + for (var nodeId in this.nodes) { + // another node could have absorbed this child. + if (this.nodes.hasOwnProperty(nodeId)) { + var childNode = this.nodes[nodeId]; + + // the edges can be swallowed by another decrease + if (childNode.dynamicEdgesLength == 1 && childNode.dynamicEdges.length != 0) { + var edge = childNode.dynamicEdges[0]; + var parentNode = (edge.toId == childNode.id) ? this.nodes[edge.fromId] : this.nodes[edge.toId]; + + // group to the largest node + if (childNode.id != parentNode.id) { + if (parentNode.options.mass > childNode.options.mass) { + this._addToCluster(parentNode,childNode,true); + } + else { + this._addToCluster(childNode,parentNode,true); + } + } + } } } - else { - this.constants.hierarchicalLayout.enabled = false; - this.constants.physics.hierarchicalRepulsion.enabled = false; - this.constants.physics.barnesHut.enabled = true; - } - this._loadSelectedForceSolver(); - var graph_toggleSmooth = document.getElementById("graph_toggleSmooth"); - if (this.constants.smoothCurves.enabled == true) {graph_toggleSmooth.style.background = "#A4FF56";} - else {graph_toggleSmooth.style.background = "#FF8532";} - this.moving = true; - this.start(); - } + }; /** - * this generates the ranges depending on the iniital values. + * To keep the nodes of roughly equal size we normalize the cluster levels. + * This function clusters a node to its smallest connected neighbour. * - * @param id - * @param map - * @param constantsVariableName + * @param node + * @private */ - function showValueOfRange (id,map,constantsVariableName) { - var valueId = id + "_value"; - var rangeValue = document.getElementById(id).value; + exports._clusterToSmallestNeighbour = function(node) { + var smallestNeighbour = -1; + var smallestNeighbourNode = null; + for (var i = 0; i < node.dynamicEdges.length; i++) { + if (node.dynamicEdges[i] !== undefined) { + var neighbour = null; + if (node.dynamicEdges[i].fromId != node.id) { + neighbour = node.dynamicEdges[i].from; + } + else if (node.dynamicEdges[i].toId != node.id) { + neighbour = node.dynamicEdges[i].to; + } - if (map instanceof Array) { - document.getElementById(valueId).value = map[parseInt(rangeValue)]; - this._overWriteGraphConstants(constantsVariableName,map[parseInt(rangeValue)]); - } - else { - document.getElementById(valueId).value = parseInt(map) * parseFloat(rangeValue); - this._overWriteGraphConstants(constantsVariableName, parseInt(map) * parseFloat(rangeValue)); - } - if (constantsVariableName == "hierarchicalLayout_direction" || - constantsVariableName == "hierarchicalLayout_levelSeparation" || - constantsVariableName == "hierarchicalLayout_nodeSpacing") { - this._setupHierarchicalLayout(); + if (neighbour != null && smallestNeighbour > neighbour.clusterSessions.length) { + smallestNeighbour = neighbour.clusterSessions.length; + smallestNeighbourNode = neighbour; + } + } } - this.moving = true; - this.start(); - } + if (neighbour != null && this.nodes[neighbour.id] !== undefined) { + this._addToCluster(neighbour, node, true); + } + }; -/***/ }, -/* 52 */ -/***/ function(module, exports, __webpack_require__) { /** - * Calculate the forces the nodes apply on each other based on a repulsion field. - * This field is linearly approximated. + * This function forms clusters from hubs, it loops over all nodes * + * @param {Boolean} force | Disregard zoom level + * @param {Boolean} onlyEqual | This only clusters a hub with a specific number of edges * @private */ - exports._calculateNodeForces = function () { - var dx, dy, angle, distance, fx, fy, combinedClusterSize, - repulsingForce, node1, node2, i, j; - - var nodes = this.calculationNodes; - var nodeIndices = this.calculationNodeIndices; - - // approximation constants - var a_base = -2 / 3; - var b = 4 / 3; + exports._formClustersByHub = function(force, onlyEqual) { + // we loop over all nodes in the list + for (var nodeId in this.nodes) { + // we check if it is still available since it can be used by the clustering in this loop + if (this.nodes.hasOwnProperty(nodeId)) { + this._formClusterFromHub(this.nodes[nodeId],force,onlyEqual); + } + } + }; - // repulsing forces between nodes - var nodeDistance = this.constants.physics.repulsion.nodeDistance; - var minimumDistance = nodeDistance; + /** + * This function forms a cluster from a specific preselected hub node + * + * @param {Node} hubNode | the node we will cluster as a hub + * @param {Boolean} force | Disregard zoom level + * @param {Boolean} onlyEqual | This only clusters a hub with a specific number of edges + * @param {Number} [absorptionSizeOffset] | + * @private + */ + exports._formClusterFromHub = function(hubNode, force, onlyEqual, absorptionSizeOffset) { + if (absorptionSizeOffset === undefined) { + absorptionSizeOffset = 0; + } + // we decide if the node is a hub + if ((hubNode.dynamicEdgesLength >= this.hubThreshold && onlyEqual == false) || + (hubNode.dynamicEdgesLength == this.hubThreshold && onlyEqual == true)) { + // initialize variables + var dx,dy,length; + var minLength = this.constants.clustering.clusterEdgeThreshold/this.scale; + var allowCluster = false; - // we loop from i over all but the last entree in the array - // j loops from i+1 to the last. This way we do not double count any of the indices, nor i == j - for (i = 0; i < nodeIndices.length - 1; i++) { - node1 = nodes[nodeIndices[i]]; - for (j = i + 1; j < nodeIndices.length; j++) { - node2 = nodes[nodeIndices[j]]; - combinedClusterSize = node1.clusterSize + node2.clusterSize - 2; + // we create a list of edges because the dynamicEdges change over the course of this loop + var edgesIdarray = []; + var amountOfInitialEdges = hubNode.dynamicEdges.length; + for (var j = 0; j < amountOfInitialEdges; j++) { + edgesIdarray.push(hubNode.dynamicEdges[j].id); + } - dx = node2.x - node1.x; - dy = node2.y - node1.y; - distance = Math.sqrt(dx * dx + dy * dy); + // if the hub clustering is not forces, we check if one of the edges connected + // to a cluster is small enough based on the constants.clustering.clusterEdgeThreshold + if (force == false) { + allowCluster = false; + for (j = 0; j < amountOfInitialEdges; j++) { + var edge = this.edges[edgesIdarray[j]]; + if (edge !== undefined) { + if (edge.connected) { + if (edge.toId != edge.fromId) { + dx = (edge.to.x - edge.from.x); + dy = (edge.to.y - edge.from.y); + length = Math.sqrt(dx * dx + dy * dy); - minimumDistance = (combinedClusterSize == 0) ? nodeDistance : (nodeDistance * (1 + combinedClusterSize * this.constants.clustering.distanceAmplification)); - var a = a_base / minimumDistance; - if (distance < 2 * minimumDistance) { - if (distance < 0.5 * minimumDistance) { - repulsingForce = 1.0; - } - else { - repulsingForce = a * distance + b; // linear approx of 1 / (1 + Math.exp((distance / minimumDistance - 1) * steepness)) + if (length < minLength) { + allowCluster = true; + break; + } + } + } } + } + } - // amplify the repulsion for clusters. - repulsingForce *= (combinedClusterSize == 0) ? 1 : 1 + combinedClusterSize * this.constants.clustering.forceAmplification; - repulsingForce = repulsingForce / distance; - - fx = dx * repulsingForce; - fy = dy * repulsingForce; - - node1.fx -= fx; - node1.fy -= fy; - node2.fx += fx; - node2.fy += fy; + // start the clustering if allowed + if ((!force && allowCluster) || force) { + // we loop over all edges INITIALLY connected to this hub + for (j = 0; j < amountOfInitialEdges; j++) { + edge = this.edges[edgesIdarray[j]]; + // the edge can be clustered by this function in a previous loop + if (edge !== undefined) { + var childNode = this.nodes[(edge.fromId == hubNode.id) ? edge.toId : edge.fromId]; + // we do not want hubs to merge with other hubs nor do we want to cluster itself. + if ((childNode.dynamicEdges.length <= (this.hubThreshold + absorptionSizeOffset)) && + (childNode.id != hubNode.id)) { + this._addToCluster(hubNode,childNode,force); + } + } } } } }; -/***/ }, -/* 53 */ -/***/ function(module, exports, __webpack_require__) { /** - * Calculate the forces the nodes apply on eachother based on a repulsion field. - * This field is linearly approximated. + * This function adds the child node to the parent node, creating a cluster if it is not already. * + * @param {Node} parentNode | this is the node that will house the child node + * @param {Node} childNode | this node will be deleted from the global this.nodes and stored in the parent node + * @param {Boolean} force | true will only update the remainingEdges at the very end of the clustering, ensuring single level collapse * @private */ - exports._calculateNodeForces = function () { - var dx, dy, distance, fx, fy, - repulsingForce, node1, node2, i, j; - - var nodes = this.calculationNodes; - var nodeIndices = this.calculationNodeIndices; - - // repulsing forces between nodes - var nodeDistance = this.constants.physics.hierarchicalRepulsion.nodeDistance; - - // we loop from i over all but the last entree in the array - // j loops from i+1 to the last. This way we do not double count any of the indices, nor i == j - for (i = 0; i < nodeIndices.length - 1; i++) { - node1 = nodes[nodeIndices[i]]; - for (j = i + 1; j < nodeIndices.length; j++) { - node2 = nodes[nodeIndices[j]]; - - // nodes only affect nodes on their level - if (node1.level == node2.level) { - - dx = node2.x - node1.x; - dy = node2.y - node1.y; - distance = Math.sqrt(dx * dx + dy * dy); - - - var steepness = 0.05; - if (distance < nodeDistance) { - repulsingForce = -Math.pow(steepness*distance,2) + Math.pow(steepness*nodeDistance,2); - } - else { - repulsingForce = 0; - } - // normalize force with - if (distance == 0) { - distance = 0.01; - } - else { - repulsingForce = repulsingForce / distance; - } - fx = dx * repulsingForce; - fy = dy * repulsingForce; + exports._addToCluster = function(parentNode, childNode, force) { + // join child node in the parent node + parentNode.containedNodes[childNode.id] = childNode; - node1.fx -= fx; - node1.fy -= fy; - node2.fx += fx; - node2.fy += fy; - } + // manage all the edges connected to the child and parent nodes + for (var i = 0; i < childNode.dynamicEdges.length; i++) { + var edge = childNode.dynamicEdges[i]; + if (edge.toId == parentNode.id || edge.fromId == parentNode.id) { // edge connected to parentNode + this._addToContainedEdges(parentNode,childNode,edge); + } + else { + this._connectEdgeToCluster(parentNode,childNode,edge); } } - }; + // a contained node has no dynamic edges. + childNode.dynamicEdges = []; + // remove circular edges from clusters + this._containCircularEdgesFromNode(parentNode,childNode); - /** - * this function calculates the effects of the springs in the case of unsmooth curves. - * - * @private - */ - exports._calculateHierarchicalSpringForces = function () { - var edgeLength, edge, edgeId; - var dx, dy, fx, fy, springForce, distance; - var edges = this.edges; - var nodes = this.calculationNodes; - var nodeIndices = this.calculationNodeIndices; + // remove the childNode from the global nodes object + delete this.nodes[childNode.id]; + // update the properties of the child and parent + var massBefore = parentNode.options.mass; + childNode.clusterSession = this.clusterSession; + parentNode.options.mass += childNode.options.mass; + parentNode.clusterSize += childNode.clusterSize; + parentNode.options.fontSize = Math.min(this.constants.clustering.maxFontSize, this.constants.nodes.fontSize + this.constants.clustering.fontSizeMultiplier*parentNode.clusterSize); - for (var i = 0; i < nodeIndices.length; i++) { - var node1 = nodes[nodeIndices[i]]; - node1.springFx = 0; - node1.springFy = 0; + // keep track of the clustersessions so we can open the cluster up as it has been formed. + if (parentNode.clusterSessions[parentNode.clusterSessions.length - 1] != this.clusterSession) { + parentNode.clusterSessions.push(this.clusterSession); } + // forced clusters only open from screen size and double tap + if (force == true) { + // parentNode.formationScale = Math.pow(1 - (1.0/11.0),this.clusterSession+3); + parentNode.formationScale = 0; + } + else { + parentNode.formationScale = this.scale; // The latest child has been added on this scale + } - // forces caused by the edges, modelled as springs - for (edgeId in edges) { - if (edges.hasOwnProperty(edgeId)) { - edge = edges[edgeId]; - if (edge.connected) { - // only calculate forces if nodes are in the same sector - if (this.nodes.hasOwnProperty(edge.toId) && this.nodes.hasOwnProperty(edge.fromId)) { - edgeLength = edge.physics.springLength; - // this implies that the edges between big clusters are longer - edgeLength += (edge.to.clusterSize + edge.from.clusterSize - 2) * this.constants.clustering.edgeGrowth; + // recalculate the size of the node on the next time the node is rendered + parentNode.clearSizeCache(); - dx = (edge.from.x - edge.to.x); - dy = (edge.from.y - edge.to.y); - distance = Math.sqrt(dx * dx + dy * dy); + // set the pop-out scale for the childnode + parentNode.containedNodes[childNode.id].formationScale = parentNode.formationScale; - if (distance == 0) { - distance = 0.01; - } + // nullify the movement velocity of the child, this is to avoid hectic behaviour + childNode.clearVelocity(); - // the 1/distance is so the fx and fy can be calculated without sine or cosine. - springForce = this.constants.physics.springConstant * (edgeLength - distance) / distance; + // the mass has altered, preservation of energy dictates the velocity to be updated + parentNode.updateVelocity(massBefore); - fx = dx * springForce; - fy = dy * springForce; + // restart the simulation to reorganise all nodes + this.moving = true; + }; + /** + * This function will apply the changes made to the remainingEdges during the formation of the clusters. + * This is a seperate function to allow for level-wise collapsing of the node barnesHutTree. + * It has to be called if a level is collapsed. It is called by _formClusters(). + * @private + */ + exports._updateDynamicEdges = function() { + for (var i = 0; i < this.nodeIndices.length; i++) { + var node = this.nodes[this.nodeIndices[i]]; + node.dynamicEdgesLength = node.dynamicEdges.length; - if (edge.to.level != edge.from.level) { - edge.to.springFx -= fx; - edge.to.springFy -= fy; - edge.from.springFx += fx; - edge.from.springFy += fy; - } - else { - var factor = 0.5; - edge.to.fx -= factor*fx; - edge.to.fy -= factor*fy; - edge.from.fx += factor*fx; - edge.from.fy += factor*fy; + // this corrects for multiple edges pointing at the same other node + var correction = 0; + if (node.dynamicEdgesLength > 1) { + for (var j = 0; j < node.dynamicEdgesLength - 1; j++) { + var edgeToId = node.dynamicEdges[j].toId; + var edgeFromId = node.dynamicEdges[j].fromId; + for (var k = j+1; k < node.dynamicEdgesLength; k++) { + if ((node.dynamicEdges[k].toId == edgeToId && node.dynamicEdges[k].fromId == edgeFromId) || + (node.dynamicEdges[k].fromId == edgeToId && node.dynamicEdges[k].toId == edgeFromId)) { + correction += 1; } } } } + node.dynamicEdgesLength -= correction; } + }; - // normalize spring forces - var springForce = 1; - var springFx, springFy; - for (i = 0; i < nodeIndices.length; i++) { - var node = nodes[nodeIndices[i]]; - springFx = Math.min(springForce,Math.max(-springForce,node.springFx)); - springFy = Math.min(springForce,Math.max(-springForce,node.springFy)); - node.fx += springFx; - node.fy += springFy; + /** + * This adds an edge from the childNode to the contained edges of the parent node + * + * @param parentNode | Node object + * @param childNode | Node object + * @param edge | Edge object + * @private + */ + exports._addToContainedEdges = function(parentNode, childNode, edge) { + // create an array object if it does not yet exist for this childNode + if (!(parentNode.containedEdges.hasOwnProperty(childNode.id))) { + parentNode.containedEdges[childNode.id] = [] } + // add this edge to the list + parentNode.containedEdges[childNode.id].push(edge); - // retain energy balance - var totalFx = 0; - var totalFy = 0; - for (i = 0; i < nodeIndices.length; i++) { - var node = nodes[nodeIndices[i]]; - totalFx += node.fx; - totalFy += node.fy; - } - var correctionFx = totalFx / nodeIndices.length; - var correctionFy = totalFy / nodeIndices.length; + // remove the edge from the global edges object + delete this.edges[edge.id]; - for (i = 0; i < nodeIndices.length; i++) { - var node = nodes[nodeIndices[i]]; - node.fx -= correctionFx; - node.fy -= correctionFy; + // remove the edge from the parent object + for (var i = 0; i < parentNode.dynamicEdges.length; i++) { + if (parentNode.dynamicEdges[i].id == edge.id) { + parentNode.dynamicEdges.splice(i,1); + break; + } } - }; -/***/ }, -/* 54 */ -/***/ function(module, exports, __webpack_require__) { - /** - * This function calculates the forces the nodes apply on eachother based on a gravitational model. - * The Barnes Hut method is used to speed up this N-body simulation. + * This function connects an edge that was connected to a child node to the parent node. + * It keeps track of which nodes it has been connected to with the originalId array. * + * @param {Node} parentNode | Node object + * @param {Node} childNode | Node object + * @param {Edge} edge | Edge object * @private */ - exports._calculateNodeForces = function() { - if (this.constants.physics.barnesHut.gravitationalConstant != 0) { - var node; - var nodes = this.calculationNodes; - var nodeIndices = this.calculationNodeIndices; - var nodeCount = nodeIndices.length; - - this._formBarnesHutTree(nodes,nodeIndices); - - var barnesHutTree = this.barnesHutTree; + exports._connectEdgeToCluster = function(parentNode, childNode, edge) { + // handle circular edges + if (edge.toId == edge.fromId) { + this._addToContainedEdges(parentNode, childNode, edge); + } + else { + if (edge.toId == childNode.id) { // edge connected to other node on the "to" side + edge.originalToId.push(childNode.id); + edge.to = parentNode; + edge.toId = parentNode.id; + } + else { // edge connected to other node with the "from" side - // place the nodes one by one recursively - for (var i = 0; i < nodeCount; i++) { - node = nodes[nodeIndices[i]]; - if (node.options.mass > 0) { - // starting with root is irrelevant, it never passes the BarnesHut condition - this._getForceContribution(barnesHutTree.root.children.NW,node); - this._getForceContribution(barnesHutTree.root.children.NE,node); - this._getForceContribution(barnesHutTree.root.children.SW,node); - this._getForceContribution(barnesHutTree.root.children.SE,node); - } + edge.originalFromId.push(childNode.id); + edge.from = parentNode; + edge.fromId = parentNode.id; } + + this._addToReroutedEdges(parentNode,childNode,edge); } }; /** - * This function traverses the barnesHutTree. It checks when it can approximate distant nodes with their center of mass. - * If a region contains a single node, we check if it is not itself, then we apply the force. + * If a node is connected to itself, a circular edge is drawn. When clustering we want to contain + * these edges inside of the cluster. * - * @param parentBranch - * @param node + * @param parentNode + * @param childNode * @private */ - exports._getForceContribution = function(parentBranch,node) { - // we get no force contribution from an empty region - if (parentBranch.childrenCount > 0) { - var dx,dy,distance; - - // get the distance from the center of mass to the node. - dx = parentBranch.centerOfMass.x - node.x; - dy = parentBranch.centerOfMass.y - node.y; - distance = Math.sqrt(dx * dx + dy * dy); - - // BarnesHut condition - // original condition : s/d < theta = passed === d/s > 1/theta = passed - // calcSize = 1/s --> d * 1/s > 1/theta = passed - if (distance * parentBranch.calcSize > this.constants.physics.barnesHut.theta) { - // duplicate code to reduce function calls to speed up program - if (distance == 0) { - distance = 0.1*Math.random(); - dx = distance; - } - var gravityForce = this.constants.physics.barnesHut.gravitationalConstant * parentBranch.mass * node.options.mass / (distance * distance * distance); - var fx = dx * gravityForce; - var fy = dy * gravityForce; - node.fx += fx; - node.fy += fy; - } - else { - // Did not pass the condition, go into children if available - if (parentBranch.childrenCount == 4) { - this._getForceContribution(parentBranch.children.NW,node); - this._getForceContribution(parentBranch.children.NE,node); - this._getForceContribution(parentBranch.children.SW,node); - this._getForceContribution(parentBranch.children.SE,node); - } - else { // parentBranch must have only one node, if it was empty we wouldnt be here - if (parentBranch.children.data.id != node.id) { // if it is not self - // duplicate code to reduce function calls to speed up program - if (distance == 0) { - distance = 0.5*Math.random(); - dx = distance; - } - var gravityForce = this.constants.physics.barnesHut.gravitationalConstant * parentBranch.mass * node.options.mass / (distance * distance * distance); - var fx = dx * gravityForce; - var fy = dy * gravityForce; - node.fx += fx; - node.fy += fy; - } - } + exports._containCircularEdgesFromNode = function(parentNode, childNode) { + // manage all the edges connected to the child and parent nodes + for (var i = 0; i < parentNode.dynamicEdges.length; i++) { + var edge = parentNode.dynamicEdges[i]; + // handle circular edges + if (edge.toId == edge.fromId) { + this._addToContainedEdges(parentNode, childNode, edge); } } }; + /** - * This function constructs the barnesHut tree recursively. It creates the root, splits it and starts placing the nodes. + * This adds an edge from the childNode to the rerouted edges of the parent node * - * @param nodes - * @param nodeIndices + * @param parentNode | Node object + * @param childNode | Node object + * @param edge | Edge object * @private */ - exports._formBarnesHutTree = function(nodes,nodeIndices) { - var node; - var nodeCount = nodeIndices.length; + exports._addToReroutedEdges = function(parentNode, childNode, edge) { + // create an array object if it does not yet exist for this childNode + // we store the edge in the rerouted edges so we can restore it when the cluster pops open + if (!(parentNode.reroutedEdges.hasOwnProperty(childNode.id))) { + parentNode.reroutedEdges[childNode.id] = []; + } + parentNode.reroutedEdges[childNode.id].push(edge); - var minX = Number.MAX_VALUE, - minY = Number.MAX_VALUE, - maxX =-Number.MAX_VALUE, - maxY =-Number.MAX_VALUE; + // this edge becomes part of the dynamicEdges of the cluster node + parentNode.dynamicEdges.push(edge); + }; - // get the range of the nodes - for (var i = 0; i < nodeCount; i++) { - var x = nodes[nodeIndices[i]].x; - var y = nodes[nodeIndices[i]].y; - if (nodes[nodeIndices[i]].options.mass > 0) { - if (x < minX) { minX = x; } - if (x > maxX) { maxX = x; } - if (y < minY) { minY = y; } - if (y > maxY) { maxY = y; } - } - } - // make the range a square - var sizeDiff = Math.abs(maxX - minX) - Math.abs(maxY - minY); // difference between X and Y - if (sizeDiff > 0) {minY -= 0.5 * sizeDiff; maxY += 0.5 * sizeDiff;} // xSize > ySize - else {minX += 0.5 * sizeDiff; maxX -= 0.5 * sizeDiff;} // xSize < ySize - var minimumTreeSize = 1e-5; - var rootSize = Math.max(minimumTreeSize,Math.abs(maxX - minX)); - var halfRootSize = 0.5 * rootSize; - var centerX = 0.5 * (minX + maxX), centerY = 0.5 * (minY + maxY); + /** + * This function connects an edge that was connected to a cluster node back to the child node. + * + * @param parentNode | Node object + * @param childNode | Node object + * @private + */ + exports._connectEdgeBackToChild = function(parentNode, childNode) { + if (parentNode.reroutedEdges.hasOwnProperty(childNode.id)) { + for (var i = 0; i < parentNode.reroutedEdges[childNode.id].length; i++) { + var edge = parentNode.reroutedEdges[childNode.id][i]; + if (edge.originalFromId[edge.originalFromId.length-1] == childNode.id) { + edge.originalFromId.pop(); + edge.fromId = childNode.id; + edge.from = childNode; + } + else { + edge.originalToId.pop(); + edge.toId = childNode.id; + edge.to = childNode; + } - // construct the barnesHutTree - var barnesHutTree = { - root:{ - centerOfMass: {x:0, y:0}, - mass:0, - range: { - minX: centerX-halfRootSize,maxX:centerX+halfRootSize, - minY: centerY-halfRootSize,maxY:centerY+halfRootSize - }, - size: rootSize, - calcSize: 1 / rootSize, - children: { data:null}, - maxWidth: 0, - level: 0, - childrenCount: 4 - } - }; - this._splitBranch(barnesHutTree.root); + // append this edge to the list of edges connecting to the childnode + childNode.dynamicEdges.push(edge); - // place the nodes one by one recursively - for (i = 0; i < nodeCount; i++) { - node = nodes[nodeIndices[i]]; - if (node.options.mass > 0) { - this._placeInTree(barnesHutTree.root,node); + // remove the edge from the parent object + for (var j = 0; j < parentNode.dynamicEdges.length; j++) { + if (parentNode.dynamicEdges[j].id == edge.id) { + parentNode.dynamicEdges.splice(j,1); + break; + } + } } + // remove the entry from the rerouted edges + delete parentNode.reroutedEdges[childNode.id]; } - - // make global - this.barnesHutTree = barnesHutTree }; /** - * this updates the mass of a branch. this is increased by adding a node. + * When loops are clustered, an edge can be both in the rerouted array and the contained array. + * This function is called last to verify that all edges in dynamicEdges are in fact connected to the + * parentNode * - * @param parentBranch - * @param node + * @param parentNode | Node object * @private */ - exports._updateBranchMass = function(parentBranch, node) { - var totalMass = parentBranch.mass + node.options.mass; - var totalMassInv = 1/totalMass; - - parentBranch.centerOfMass.x = parentBranch.centerOfMass.x * parentBranch.mass + node.x * node.options.mass; - parentBranch.centerOfMass.x *= totalMassInv; - - parentBranch.centerOfMass.y = parentBranch.centerOfMass.y * parentBranch.mass + node.y * node.options.mass; - parentBranch.centerOfMass.y *= totalMassInv; - - parentBranch.mass = totalMass; - var biggestSize = Math.max(Math.max(node.height,node.radius),node.width); - parentBranch.maxWidth = (parentBranch.maxWidth < biggestSize) ? biggestSize : parentBranch.maxWidth; - + exports._validateEdges = function(parentNode) { + for (var i = 0; i < parentNode.dynamicEdges.length; i++) { + var edge = parentNode.dynamicEdges[i]; + if (parentNode.id != edge.toId && parentNode.id != edge.fromId) { + parentNode.dynamicEdges.splice(i,1); + } + } }; /** - * determine in which branch the node will be placed. + * This function released the contained edges back into the global domain and puts them back into the + * dynamic edges of both parent and child. * - * @param parentBranch - * @param node - * @param skipMassUpdate + * @param {Node} parentNode | + * @param {Node} childNode | * @private */ - exports._placeInTree = function(parentBranch,node,skipMassUpdate) { - if (skipMassUpdate != true || skipMassUpdate === undefined) { - // update the mass of the branch. - this._updateBranchMass(parentBranch,node); - } + exports._releaseContainedEdges = function(parentNode, childNode) { + for (var i = 0; i < parentNode.containedEdges[childNode.id].length; i++) { + var edge = parentNode.containedEdges[childNode.id][i]; - if (parentBranch.children.NW.range.maxX > node.x) { // in NW or SW - if (parentBranch.children.NW.range.maxY > node.y) { // in NW - this._placeInRegion(parentBranch,node,"NW"); - } - else { // in SW - this._placeInRegion(parentBranch,node,"SW"); - } - } - else { // in NE or SE - if (parentBranch.children.NW.range.maxY > node.y) { // in NE - this._placeInRegion(parentBranch,node,"NE"); - } - else { // in SE - this._placeInRegion(parentBranch,node,"SE"); - } + // put the edge back in the global edges object + this.edges[edge.id] = edge; + + // put the edge back in the dynamic edges of the child and parent + childNode.dynamicEdges.push(edge); + parentNode.dynamicEdges.push(edge); } + // remove the entry from the contained edges + delete parentNode.containedEdges[childNode.id]; + }; + + + // ------------------- UTILITY FUNCTIONS ---------------------------- // + + /** - * actually place the node in a region (or branch) - * - * @param parentBranch - * @param node - * @param region - * @private + * This updates the node labels for all nodes (for debugging purposes) */ - exports._placeInRegion = function(parentBranch,node,region) { - switch (parentBranch.children[region].childrenCount) { - case 0: // place node here - parentBranch.children[region].children.data = node; - parentBranch.children[region].childrenCount = 1; - this._updateBranchMass(parentBranch.children[region],node); - break; - case 1: // convert into children - // if there are two nodes exactly overlapping (on init, on opening of cluster etc.) - // we move one node a pixel and we do not put it in the tree. - if (parentBranch.children[region].children.data.x == node.x && - parentBranch.children[region].children.data.y == node.y) { - node.x += Math.random(); - node.y += Math.random(); + exports.updateLabels = function() { + var nodeId; + // update node labels + for (nodeId in this.nodes) { + if (this.nodes.hasOwnProperty(nodeId)) { + var node = this.nodes[nodeId]; + if (node.clusterSize > 1) { + node.label = "[".concat(String(node.clusterSize),"]"); } - else { - this._splitBranch(parentBranch.children[region]); - this._placeInTree(parentBranch.children[region],node); + } + } + + // update node labels + for (nodeId in this.nodes) { + if (this.nodes.hasOwnProperty(nodeId)) { + node = this.nodes[nodeId]; + if (node.clusterSize == 1) { + if (node.originalLabel !== undefined) { + node.label = node.originalLabel; + } + else { + node.label = String(node.id); + } } - break; - case 4: // place in branch - this._placeInTree(parentBranch.children[region],node); - break; + } } + + // /* Debug Override */ + // for (nodeId in this.nodes) { + // if (this.nodes.hasOwnProperty(nodeId)) { + // node = this.nodes[nodeId]; + // node.label = String(node.level); + // } + // } + }; /** - * this function splits a branch into 4 sub branches. If the branch contained a node, we place it in the subbranch - * after the split is complete. - * - * @param parentBranch - * @private + * We want to keep the cluster level distribution rather small. This means we do not want unclustered nodes + * if the rest of the nodes are already a few cluster levels in. + * To fix this we use this function. It determines the min and max cluster level and sends nodes that have not + * clustered enough to the clusterToSmallestNeighbours function. */ - exports._splitBranch = function(parentBranch) { - // if the branch is shaded with a node, replace the node in the new subset. - var containedNode = null; - if (parentBranch.childrenCount == 1) { - containedNode = parentBranch.children.data; - parentBranch.mass = 0; parentBranch.centerOfMass.x = 0; parentBranch.centerOfMass.y = 0; + exports.normalizeClusterLevels = function() { + var maxLevel = 0; + var minLevel = 1e9; + var clusterLevel = 0; + var nodeId; + + // we loop over all nodes in the list + for (nodeId in this.nodes) { + if (this.nodes.hasOwnProperty(nodeId)) { + clusterLevel = this.nodes[nodeId].clusterSessions.length; + if (maxLevel < clusterLevel) {maxLevel = clusterLevel;} + if (minLevel > clusterLevel) {minLevel = clusterLevel;} + } } - parentBranch.childrenCount = 4; - parentBranch.children.data = null; - this._insertRegion(parentBranch,"NW"); - this._insertRegion(parentBranch,"NE"); - this._insertRegion(parentBranch,"SW"); - this._insertRegion(parentBranch,"SE"); - if (containedNode != null) { - this._placeInTree(parentBranch,containedNode); + if (maxLevel - minLevel > this.constants.clustering.clusterLevelDifference) { + var amountOfNodes = this.nodeIndices.length; + var targetLevel = maxLevel - this.constants.clustering.clusterLevelDifference; + // we loop over all nodes in the list + for (nodeId in this.nodes) { + if (this.nodes.hasOwnProperty(nodeId)) { + if (this.nodes[nodeId].clusterSessions.length < targetLevel) { + this._clusterToSmallestNeighbour(this.nodes[nodeId]); + } + } + } + this._updateNodeIndexList(); + this._updateDynamicEdges(); + // if a cluster was formed, we increase the clusterSession + if (this.nodeIndices.length != amountOfNodes) { + this.clusterSession += 1; + } } }; + /** - * This function subdivides the region into four new segments. - * Specifically, this inserts a single new segment. - * It fills the children section of the parentBranch + * This function determines if the cluster we want to decluster is in the active area + * this means around the zoom center * - * @param parentBranch - * @param region - * @param parentRange + * @param {Node} node + * @returns {boolean} * @private */ - exports._insertRegion = function(parentBranch, region) { - var minX,maxX,minY,maxY; - var childSize = 0.5 * parentBranch.size; - switch (region) { - case "NW": - minX = parentBranch.range.minX; - maxX = parentBranch.range.minX + childSize; - minY = parentBranch.range.minY; - maxY = parentBranch.range.minY + childSize; - break; - case "NE": - minX = parentBranch.range.minX + childSize; - maxX = parentBranch.range.maxX; - minY = parentBranch.range.minY; - maxY = parentBranch.range.minY + childSize; - break; - case "SW": - minX = parentBranch.range.minX; - maxX = parentBranch.range.minX + childSize; - minY = parentBranch.range.minY + childSize; - maxY = parentBranch.range.maxY; - break; - case "SE": - minX = parentBranch.range.minX + childSize; - maxX = parentBranch.range.maxX; - minY = parentBranch.range.minY + childSize; - maxY = parentBranch.range.maxY; - break; - } - - - parentBranch.children[region] = { - centerOfMass:{x:0,y:0}, - mass:0, - range:{minX:minX,maxX:maxX,minY:minY,maxY:maxY}, - size: 0.5 * parentBranch.size, - calcSize: 2 * parentBranch.calcSize, - children: {data:null}, - maxWidth: 0, - level: parentBranch.level+1, - childrenCount: 0 - }; + exports._nodeInActiveArea = function(node) { + return ( + Math.abs(node.x - this.areaCenter.x) <= this.constants.clustering.activeAreaBoxSize/this.scale + && + Math.abs(node.y - this.areaCenter.y) <= this.constants.clustering.activeAreaBoxSize/this.scale + ) }; /** - * This function is for debugging purposed, it draws the tree. + * This is an adaptation of the original repositioning function. This is called if the system is clustered initially + * It puts large clusters away from the center and randomizes the order. * - * @param ctx - * @param color - * @private */ - exports._drawTree = function(ctx,color) { - if (this.barnesHutTree !== undefined) { - - ctx.lineWidth = 1; - - this._drawBranch(this.barnesHutTree.root,ctx,color); + exports.repositionNodes = function() { + for (var i = 0; i < this.nodeIndices.length; i++) { + var node = this.nodes[this.nodeIndices[i]]; + if ((node.xFixed == false || node.yFixed == false)) { + var radius = 10 * 0.1*this.nodeIndices.length * Math.min(100,node.options.mass); + var angle = 2 * Math.PI * Math.random(); + if (node.xFixed == false) {node.x = radius * Math.cos(angle);} + if (node.yFixed == false) {node.y = radius * Math.sin(angle);} + this._repositionBezierNodes(node); + } } }; /** - * This function is for debugging purposes. It draws the branches recursively. + * We determine how many connections denote an important hub. + * We take the mean + 2*std as the important hub size. (Assuming a normal distribution of data, ~2.2%) * - * @param branch - * @param ctx - * @param color * @private */ - exports._drawBranch = function(branch,ctx,color) { - if (color === undefined) { - color = "#FF0000"; - } + exports._getHubSize = function() { + var average = 0; + var averageSquared = 0; + var hubCounter = 0; + var largestHub = 0; - if (branch.childrenCount == 4) { - this._drawBranch(branch.children.NW,ctx); - this._drawBranch(branch.children.NE,ctx); - this._drawBranch(branch.children.SE,ctx); - this._drawBranch(branch.children.SW,ctx); + for (var i = 0; i < this.nodeIndices.length; i++) { + + var node = this.nodes[this.nodeIndices[i]]; + if (node.dynamicEdgesLength > largestHub) { + largestHub = node.dynamicEdgesLength; + } + average += node.dynamicEdgesLength; + averageSquared += Math.pow(node.dynamicEdgesLength,2); + hubCounter += 1; } - ctx.strokeStyle = color; - ctx.beginPath(); - ctx.moveTo(branch.range.minX,branch.range.minY); - ctx.lineTo(branch.range.maxX,branch.range.minY); - ctx.stroke(); + average = average / hubCounter; + averageSquared = averageSquared / hubCounter; - ctx.beginPath(); - ctx.moveTo(branch.range.maxX,branch.range.minY); - ctx.lineTo(branch.range.maxX,branch.range.maxY); - ctx.stroke(); + var variance = averageSquared - Math.pow(average,2); - ctx.beginPath(); - ctx.moveTo(branch.range.maxX,branch.range.maxY); - ctx.lineTo(branch.range.minX,branch.range.maxY); - ctx.stroke(); + var standardDeviation = Math.sqrt(variance); - ctx.beginPath(); - ctx.moveTo(branch.range.minX,branch.range.maxY); - ctx.lineTo(branch.range.minX,branch.range.minY); - ctx.stroke(); + this.hubThreshold = Math.floor(average + 2*standardDeviation); - /* - if (branch.mass > 0) { - ctx.circle(branch.centerOfMass.x, branch.centerOfMass.y, 3*branch.mass); - ctx.stroke(); - } - */ - }; + // always have at least one to cluster + if (this.hubThreshold > largestHub) { + this.hubThreshold = largestHub; + } + // console.log("average",average,"averageSQ",averageSquared,"var",variance,"std",standardDeviation); + // console.log("hubThreshold:",this.hubThreshold); + }; -/***/ }, -/* 55 */ -/***/ function(module, exports, __webpack_require__) { /** - * Creation of the ClusterMixin var. + * We reduce the amount of "extension nodes" or chains. These are not quickly clustered with the outliers and hubs methods + * with this amount we can cluster specifically on these chains. * - * This contains all the functions the Network object can use to employ clustering + * @param {Number} fraction | between 0 and 1, the percentage of chains to reduce + * @private */ - - /** - * This is only called in the constructor of the network object - * - */ - exports.startWithClustering = function() { - // cluster if the data set is big - this.clusterToFit(this.constants.clustering.initialMaxNodes, true); - - // updates the lables after clustering - this.updateLabels(); - - // this is called here because if clusterin is disabled, the start and stabilize are called in - // the setData function. - if (this.stabilize) { - this._stabilize(); - } - this.start(); + exports._reduceAmountOfChains = function(fraction) { + this.hubThreshold = 2; + var reduceAmount = Math.floor(this.nodeIndices.length * fraction); + for (var nodeId in this.nodes) { + if (this.nodes.hasOwnProperty(nodeId)) { + if (this.nodes[nodeId].dynamicEdgesLength == 2 && this.nodes[nodeId].dynamicEdges.length >= 2) { + if (reduceAmount > 0) { + this._formClusterFromHub(this.nodes[nodeId],true,true,1); + reduceAmount -= 1; + } + } + } + } }; /** - * This function clusters until the initialMaxNodes has been reached + * We get the amount of "extension nodes" or chains. These are not quickly clustered with the outliers and hubs methods + * with this amount we can cluster specifically on these chains. * - * @param {Number} maxNumberOfNodes - * @param {Boolean} reposition + * @private */ - exports.clusterToFit = function(maxNumberOfNodes, reposition) { - var numberOfNodes = this.nodeIndices.length; + exports._getChainFraction = function() { + var chains = 0; + var total = 0; + for (var nodeId in this.nodes) { + if (this.nodes.hasOwnProperty(nodeId)) { + if (this.nodes[nodeId].dynamicEdgesLength == 2 && this.nodes[nodeId].dynamicEdges.length >= 2) { + chains += 1; + } + total += 1; + } + } + return chains/total; + }; - var maxLevels = 50; - var level = 0; - // we first cluster the hubs, then we pull in the outliers, repeat - while (numberOfNodes > maxNumberOfNodes && level < maxLevels) { - if (level % 3 == 0) { - this.forceAggregateHubs(true); - this.normalizeClusterLevels(); - } - else { - this.increaseClusterLevel(); // this also includes a cluster normalization - } +/***/ }, +/* 51 */ +/***/ function(module, exports, __webpack_require__) { - numberOfNodes = this.nodeIndices.length; - level += 1; - } + var util = __webpack_require__(1); - // after the clustering we reposition the nodes to reduce the initial chaos - if (level > 0 && reposition == true) { - this.repositionNodes(); - } - this._updateCalculationNodes(); - }; + /** + * Creation of the SectorMixin var. + * + * This contains all the functions the Network object can use to employ the sector system. + * The sector system is always used by Network, though the benefits only apply to the use of clustering. + * If clustering is not used, there is no overhead except for a duplicate object with references to nodes and edges. + */ /** - * This function can be called to open up a specific cluster. It is only called by - * It will unpack the cluster back one level. + * This function is only called by the setData function of the Network object. + * This loads the global references into the active sector. This initializes the sector. * - * @param node | Node object: cluster to open. + * @private */ - exports.openCluster = function(node) { - var isMovingBeforeClustering = this.moving; - if (node.clusterSize > this.constants.clustering.sectorThreshold && this._nodeInActiveArea(node) && - !(this._sector() == "default" && this.nodeIndices.length == 1)) { - // this loads a new sector, loads the nodes and edges and nodeIndices of it. - this._addSector(node); - var level = 0; + exports._putDataInSector = function() { + this.sectors["active"][this._sector()].nodes = this.nodes; + this.sectors["active"][this._sector()].edges = this.edges; + this.sectors["active"][this._sector()].nodeIndices = this.nodeIndices; + }; - // we decluster until we reach a decent number of nodes - while ((this.nodeIndices.length < this.constants.clustering.initialMaxNodes) && (level < 10)) { - this.decreaseClusterLevel(); - level += 1; - } + /** + * /** + * This function sets the global references to nodes, edges and nodeIndices back to + * those of the supplied (active) sector. If a type is defined, do the specific type + * + * @param {String} sectorId + * @param {String} [sectorType] | "active" or "frozen" + * @private + */ + exports._switchToSector = function(sectorId, sectorType) { + if (sectorType === undefined || sectorType == "active") { + this._switchToActiveSector(sectorId); } else { - this._expandClusterNode(node,false,true); - - // update the index list, dynamic edges and labels - this._updateNodeIndexList(); - this._updateDynamicEdges(); - this._updateCalculationNodes(); - this.updateLabels(); - } - - // if the simulation was settled, we restart the simulation if a cluster has been formed or expanded - if (this.moving != isMovingBeforeClustering) { - this.start(); + this._switchToFrozenSector(sectorId); } }; /** - * This calls the updateClustes with default arguments + * This function sets the global references to nodes, edges and nodeIndices back to + * those of the supplied active sector. + * + * @param sectorId + * @private */ - exports.updateClustersDefault = function() { - if (this.constants.clustering.enabled == true) { - this.updateClusters(0,false,false); - } + exports._switchToActiveSector = function(sectorId) { + this.nodeIndices = this.sectors["active"][sectorId]["nodeIndices"]; + this.nodes = this.sectors["active"][sectorId]["nodes"]; + this.edges = this.sectors["active"][sectorId]["edges"]; }; /** - * This function can be called to increase the cluster level. This means that the nodes with only one edge connection will - * be clustered with their connected node. This can be repeated as many times as needed. - * This can be called externally (by a keybind for instance) to reduce the complexity of big datasets. + * This function sets the global references to nodes, edges and nodeIndices back to + * those of the supplied active sector. + * + * @private */ - exports.increaseClusterLevel = function() { - this.updateClusters(-1,false,true); + exports._switchToSupportSector = function() { + this.nodeIndices = this.sectors["support"]["nodeIndices"]; + this.nodes = this.sectors["support"]["nodes"]; + this.edges = this.sectors["support"]["edges"]; }; /** - * This function can be called to decrease the cluster level. This means that the nodes with only one edge connection will - * be unpacked if they are a cluster. This can be repeated as many times as needed. - * This can be called externally (by a key-bind for instance) to look into clusters without zooming. + * This function sets the global references to nodes, edges and nodeIndices back to + * those of the supplied frozen sector. + * + * @param sectorId + * @private */ - exports.decreaseClusterLevel = function() { - this.updateClusters(1,false,true); + exports._switchToFrozenSector = function(sectorId) { + this.nodeIndices = this.sectors["frozen"][sectorId]["nodeIndices"]; + this.nodes = this.sectors["frozen"][sectorId]["nodes"]; + this.edges = this.sectors["frozen"][sectorId]["edges"]; }; /** - * This is the main clustering function. It clusters and declusters on zoom or forced - * This function clusters on zoom, it can be called with a predefined zoom direction - * If out, check if we can form clusters, if in, check if we can open clusters. - * This function is only called from _zoom() - * - * @param {Number} zoomDirection | -1 / 0 / +1 for zoomOut / determineByZoom / zoomIn - * @param {Boolean} recursive | enabled or disable recursive calling of the opening of clusters - * @param {Boolean} force | enabled or disable forcing - * @param {Boolean} doNotStart | if true do not call start + * This function sets the global references to nodes, edges and nodeIndices back to + * those of the currently active sector. * + * @private */ - exports.updateClusters = function(zoomDirection,recursive,force,doNotStart) { - var isMovingBeforeClustering = this.moving; - var amountOfNodes = this.nodeIndices.length; - - // on zoom out collapse the sector if the scale is at the level the sector was made - if (this.previousScale > this.scale && zoomDirection == 0) { - this._collapseSector(); - } - - // check if we zoom in or out - if (this.previousScale > this.scale || zoomDirection == -1) { // zoom out - // forming clusters when forced pulls outliers in. When not forced, the edge length of the - // outer nodes determines if it is being clustered - this._formClusters(force); - } - else if (this.previousScale < this.scale || zoomDirection == 1) { // zoom in - if (force == true) { - // _openClusters checks for each node if the formationScale of the cluster is smaller than - // the current scale and if so, declusters. When forced, all clusters are reduced by one step - this._openClusters(recursive,force); - } - else { - // if a cluster takes up a set percentage of the active window - this._openClustersBySize(); - } - } - this._updateNodeIndexList(); - - // if a cluster was NOT formed and the user zoomed out, we try clustering by hubs - if (this.nodeIndices.length == amountOfNodes && (this.previousScale > this.scale || zoomDirection == -1)) { - this._aggregateHubs(force); - this._updateNodeIndexList(); - } + exports._loadLatestSector = function() { + this._switchToSector(this._sector()); + }; - // we now reduce chains. - if (this.previousScale > this.scale || zoomDirection == -1) { // zoom out - this.handleChains(); - this._updateNodeIndexList(); - } - this.previousScale = this.scale; + /** + * This function returns the currently active sector Id + * + * @returns {String} + * @private + */ + exports._sector = function() { + return this.activeSector[this.activeSector.length-1]; + }; - // rest of the update the index list, dynamic edges and labels - this._updateDynamicEdges(); - this.updateLabels(); - // if a cluster was formed, we increase the clusterSession - if (this.nodeIndices.length < amountOfNodes) { // this means a clustering operation has taken place - this.clusterSession += 1; - // if clusters have been made, we normalize the cluster level - this.normalizeClusterLevels(); + /** + * This function returns the previously active sector Id + * + * @returns {String} + * @private + */ + exports._previousSector = function() { + if (this.activeSector.length > 1) { + return this.activeSector[this.activeSector.length-2]; } - - if (doNotStart == false || doNotStart === undefined) { - // if the simulation was settled, we restart the simulation if a cluster has been formed or expanded - if (this.moving != isMovingBeforeClustering) { - this.start(); - } + else { + throw new TypeError('there are not enough sectors in the this.activeSector array.'); } - - this._updateCalculationNodes(); }; + /** - * This function handles the chains. It is called on every updateClusters(). + * We add the active sector at the end of the this.activeSector array + * This ensures it is the currently active sector returned by _sector() and it reaches the top + * of the activeSector stack. When we reverse our steps we move from the end to the beginning of this stack. + * + * @param newId + * @private */ - exports.handleChains = function() { - // after clustering we check how many chains there are - var chainPercentage = this._getChainFraction(); - if (chainPercentage > this.constants.clustering.chainThreshold) { - this._reduceAmountOfChains(1 - this.constants.clustering.chainThreshold / chainPercentage) - - } + exports._setActiveSector = function(newId) { + this.activeSector.push(newId); }; + /** - * this functions starts clustering by hubs - * The minimum hub threshold is set globally + * We remove the currently active sector id from the active sector stack. This happens when + * we reactivate the previously active sector * * @private */ - exports._aggregateHubs = function(force) { - this._getHubSize(); - this._formClustersByHub(force,false); + exports._forgetLastSector = function() { + this.activeSector.pop(); }; /** - * This function is fired by keypress. It forces hubs to form. + * This function creates a new active sector with the supplied newId. This newId + * is the expanding node id. * + * @param {String} newId | Id of the new active sector + * @private */ - exports.forceAggregateHubs = function(doNotStart) { - var isMovingBeforeClustering = this.moving; - var amountOfNodes = this.nodeIndices.length; - - this._aggregateHubs(true); - - // update the index list, dynamic edges and labels - this._updateNodeIndexList(); - this._updateDynamicEdges(); - this.updateLabels(); - - // if a cluster was formed, we increase the clusterSession - if (this.nodeIndices.length != amountOfNodes) { - this.clusterSession += 1; - } + exports._createNewSector = function(newId) { + // create the new sector + this.sectors["active"][newId] = {"nodes":{}, + "edges":{}, + "nodeIndices":[], + "formationScale": this.scale, + "drawingNode": undefined}; - if (doNotStart == false || doNotStart === undefined) { - // if the simulation was settled, we restart the simulation if a cluster has been formed or expanded - if (this.moving != isMovingBeforeClustering) { - this.start(); - } - } + // create the new sector render node. This gives visual feedback that you are in a new sector. + this.sectors["active"][newId]['drawingNode'] = new Node( + {id:newId, + color: { + background: "#eaefef", + border: "495c5e" + } + },{},{},this.constants); + this.sectors["active"][newId]['drawingNode'].clusterSize = 2; }; + /** - * If a cluster takes up more than a set percentage of the screen, open the cluster + * This function removes the currently active sector. This is called when we create a new + * active sector. * + * @param {String} sectorId | Id of the active sector that will be removed * @private */ - exports._openClustersBySize = function() { - for (var nodeId in this.nodes) { - if (this.nodes.hasOwnProperty(nodeId)) { - var node = this.nodes[nodeId]; - if (node.inView() == true) { - if ((node.width*this.scale > this.constants.clustering.screenSizeThreshold * this.frame.canvas.clientWidth) || - (node.height*this.scale > this.constants.clustering.screenSizeThreshold * this.frame.canvas.clientHeight)) { - this.openCluster(node); - } - } - } - } + exports._deleteActiveSector = function(sectorId) { + delete this.sectors["active"][sectorId]; }; /** - * This function loops over all nodes in the nodeIndices list. For each node it checks if it is a cluster and if it - * has to be opened based on the current zoom level. + * This function removes the currently active sector. This is called when we reactivate + * the previously active sector. * + * @param {String} sectorId | Id of the active sector that will be removed * @private */ - exports._openClusters = function(recursive,force) { - for (var i = 0; i < this.nodeIndices.length; i++) { - var node = this.nodes[this.nodeIndices[i]]; - this._expandClusterNode(node,recursive,force); - this._updateCalculationNodes(); - } + exports._deleteFrozenSector = function(sectorId) { + delete this.sectors["frozen"][sectorId]; }; + /** - * This function checks if a node has to be opened. This is done by checking the zoom level. - * If the node contains child nodes, this function is recursively called on the child nodes as well. - * This recursive behaviour is optional and can be set by the recursive argument. + * Freezing an active sector means moving it from the "active" object to the "frozen" object. + * We copy the references, then delete the active entree. * - * @param {Node} parentNode | to check for cluster and expand - * @param {Boolean} recursive | enabled or disable recursive calling - * @param {Boolean} force | enabled or disable forcing - * @param {Boolean} [openAll] | This will recursively force all nodes in the parent to be released + * @param sectorId * @private */ - exports._expandClusterNode = function(parentNode, recursive, force, openAll) { - // first check if node is a cluster - if (parentNode.clusterSize > 1) { - // this means that on a double tap event or a zoom event, the cluster fully unpacks if it is smaller than 20 - if (parentNode.clusterSize < this.constants.clustering.sectorThreshold) { - openAll = true; - } - recursive = openAll ? true : recursive; - - // if the last child has been added on a smaller scale than current scale decluster - if (parentNode.formationScale < this.scale || force == true) { - // we will check if any of the contained child nodes should be removed from the cluster - for (var containedNodeId in parentNode.containedNodes) { - if (parentNode.containedNodes.hasOwnProperty(containedNodeId)) { - var childNode = parentNode.containedNodes[containedNodeId]; + exports._freezeSector = function(sectorId) { + // we move the set references from the active to the frozen stack. + this.sectors["frozen"][sectorId] = this.sectors["active"][sectorId]; - // force expand will expand the largest cluster size clusters. Since we cluster from outside in, we assume that - // the largest cluster is the one that comes from outside - if (force == true) { - if (childNode.clusterSession == parentNode.clusterSessions[parentNode.clusterSessions.length-1] - || openAll) { - this._expelChildFromParent(parentNode,containedNodeId,recursive,force,openAll); - } - } - else { - if (this._nodeInActiveArea(parentNode)) { - this._expelChildFromParent(parentNode,containedNodeId,recursive,force,openAll); - } - } - } - } - } - } + // we have moved the sector data into the frozen set, we now remove it from the active set + this._deleteActiveSector(sectorId); }; + /** - * ONLY CALLED FROM _expandClusterNode - * - * This function will expel a child_node from a parent_node. This is to de-cluster the node. This function will remove - * the child node from the parent contained_node object and put it back into the global nodes object. - * The same holds for the edge that was connected to the child node. It is moved back into the global edges object. + * This is the reverse operation of _freezeSector. Activating means moving the sector from the "frozen" + * object to the "active" object. * - * @param {Node} parentNode | the parent node - * @param {String} containedNodeId | child_node id as it is contained in the containedNodes object of the parent node - * @param {Boolean} recursive | This will also check if the child needs to be expanded. - * With force and recursive both true, the entire cluster is unpacked - * @param {Boolean} force | This will disregard the zoom level and will expel this child from the parent - * @param {Boolean} openAll | This will recursively force all nodes in the parent to be released + * @param sectorId * @private */ - exports._expelChildFromParent = function(parentNode, containedNodeId, recursive, force, openAll) { - var childNode = parentNode.containedNodes[containedNodeId]; - - // if child node has been added on smaller scale than current, kick out - if (childNode.formationScale < this.scale || force == true) { - // unselect all selected items - this._unselectAll(); - - // put the child node back in the global nodes object - this.nodes[containedNodeId] = childNode; - - // release the contained edges from this childNode back into the global edges - this._releaseContainedEdges(parentNode,childNode); - - // reconnect rerouted edges to the childNode - this._connectEdgeBackToChild(parentNode,childNode); - - // validate all edges in dynamicEdges - this._validateEdges(parentNode); - - // undo the changes from the clustering operation on the parent node - parentNode.options.mass -= childNode.options.mass; - parentNode.clusterSize -= childNode.clusterSize; - parentNode.options.fontSize = Math.min(this.constants.clustering.maxFontSize, this.constants.nodes.fontSize + this.constants.clustering.fontSizeMultiplier*parentNode.clusterSize); - parentNode.dynamicEdgesLength = parentNode.dynamicEdges.length; + exports._activateSector = function(sectorId) { + // we move the set references from the frozen to the active stack. + this.sectors["active"][sectorId] = this.sectors["frozen"][sectorId]; - // place the child node near the parent, not at the exact same location to avoid chaos in the system - childNode.x = parentNode.x + parentNode.growthIndicator * (0.5 - Math.random()); - childNode.y = parentNode.y + parentNode.growthIndicator * (0.5 - Math.random()); + // we have moved the sector data into the active set, we now remove it from the frozen stack + this._deleteFrozenSector(sectorId); + }; - // remove node from the list - delete parentNode.containedNodes[containedNodeId]; - // check if there are other childs with this clusterSession in the parent. - var othersPresent = false; - for (var childNodeId in parentNode.containedNodes) { - if (parentNode.containedNodes.hasOwnProperty(childNodeId)) { - if (parentNode.containedNodes[childNodeId].clusterSession == childNode.clusterSession) { - othersPresent = true; - break; - } - } - } - // if there are no others, remove the cluster session from the list - if (othersPresent == false) { - parentNode.clusterSessions.pop(); + /** + * This function merges the data from the currently active sector with a frozen sector. This is used + * in the process of reverting back to the previously active sector. + * The data that is placed in the frozen (the previously active) sector is the node that has been removed from it + * upon the creation of a new active sector. + * + * @param sectorId + * @private + */ + exports._mergeThisWithFrozen = function(sectorId) { + // copy all nodes + for (var nodeId in this.nodes) { + if (this.nodes.hasOwnProperty(nodeId)) { + this.sectors["frozen"][sectorId]["nodes"][nodeId] = this.nodes[nodeId]; } + } - this._repositionBezierNodes(childNode); - // this._repositionBezierNodes(parentNode); - - // remove the clusterSession from the child node - childNode.clusterSession = 0; - - // recalculate the size of the node on the next time the node is rendered - parentNode.clearSizeCache(); - - // restart the simulation to reorganise all nodes - this.moving = true; + // copy all edges (if not fully clustered, else there are no edges) + for (var edgeId in this.edges) { + if (this.edges.hasOwnProperty(edgeId)) { + this.sectors["frozen"][sectorId]["edges"][edgeId] = this.edges[edgeId]; + } } - // check if a further expansion step is possible if recursivity is enabled - if (recursive == true) { - this._expandClusterNode(childNode,recursive,force,openAll); + // merge the nodeIndices + for (var i = 0; i < this.nodeIndices.length; i++) { + this.sectors["frozen"][sectorId]["nodeIndices"].push(this.nodeIndices[i]); } }; /** - * position the bezier nodes at the center of the edges + * This clusters the sector to one cluster. It was a single cluster before this process started so + * we revert to that state. The clusterToFit function with a maximum size of 1 node does this. * - * @param node * @private */ - exports._repositionBezierNodes = function(node) { - for (var i = 0; i < node.dynamicEdges.length; i++) { - node.dynamicEdges[i].positionBezierNode(); - } + exports._collapseThisToSingleCluster = function() { + this.clusterToFit(1,false); }; /** - * This function checks if any nodes at the end of their trees have edges below a threshold length - * This function is called only from updateClusters() - * forceLevelCollapse ignores the length of the edge and collapses one level - * This means that a node with only one edge will be clustered with its connected node + * We create a new active sector from the node that we want to open. * + * @param node * @private - * @param {Boolean} force */ - exports._formClusters = function(force) { - if (force == false) { - this._formClustersByZoom(); - } - else { - this._forceClustersByZoom(); - } - }; + exports._addSector = function(node) { + // this is the currently active sector + var sector = this._sector(); + // // this should allow me to select nodes from a frozen set. + // if (this.sectors['active'][sector]["nodes"].hasOwnProperty(node.id)) { + // console.log("the node is part of the active sector"); + // } + // else { + // console.log("I dont know what the fuck happened!!"); + // } - /** - * This function handles the clustering by zooming out, this is based on a minimum edge distance - * - * @private - */ - exports._formClustersByZoom = function() { - var dx,dy,length, - minLength = this.constants.clustering.clusterEdgeThreshold/this.scale; + // when we switch to a new sector, we remove the node that will be expanded from the current nodes list. + delete this.nodes[node.id]; - // check if any edges are shorter than minLength and start the clustering - // the clustering favours the node with the larger mass - for (var edgeId in this.edges) { - if (this.edges.hasOwnProperty(edgeId)) { - var edge = this.edges[edgeId]; - if (edge.connected) { - if (edge.toId != edge.fromId) { - dx = (edge.to.x - edge.from.x); - dy = (edge.to.y - edge.from.y); - length = Math.sqrt(dx * dx + dy * dy); + var unqiueIdentifier = util.randomUUID(); + // we fully freeze the currently active sector + this._freezeSector(sector); - if (length < minLength) { - // first check which node is larger - var parentNode = edge.from; - var childNode = edge.to; - if (edge.to.options.mass > edge.from.options.mass) { - parentNode = edge.to; - childNode = edge.from; - } + // we create a new active sector. This sector has the Id of the node to ensure uniqueness + this._createNewSector(unqiueIdentifier); + + // we add the active sector to the sectors array to be able to revert these steps later on + this._setActiveSector(unqiueIdentifier); - if (childNode.dynamicEdgesLength == 1) { - this._addToCluster(parentNode,childNode,false); - } - else if (parentNode.dynamicEdgesLength == 1) { - this._addToCluster(childNode,parentNode,false); - } - } - } - } - } - } + // we redirect the global references to the new sector's references. this._sector() now returns unqiueIdentifier + this._switchToSector(this._sector()); + + // finally we add the node we removed from our previous active sector to the new active sector + this.nodes[node.id] = node; }; + /** - * This function forces the network to cluster all nodes with only one connecting edge to their - * connected node. + * We close the sector that is currently open and revert back to the one before. + * If the active sector is the "default" sector, nothing happens. * * @private */ - exports._forceClustersByZoom = function() { - for (var nodeId in this.nodes) { - // another node could have absorbed this child. - if (this.nodes.hasOwnProperty(nodeId)) { - var childNode = this.nodes[nodeId]; + exports._collapseSector = function() { + // the currently active sector + var sector = this._sector(); - // the edges can be swallowed by another decrease - if (childNode.dynamicEdgesLength == 1 && childNode.dynamicEdges.length != 0) { - var edge = childNode.dynamicEdges[0]; - var parentNode = (edge.toId == childNode.id) ? this.nodes[edge.fromId] : this.nodes[edge.toId]; + // we cannot collapse the default sector + if (sector != "default") { + if ((this.nodeIndices.length == 1) || + (this.sectors["active"][sector]["drawingNode"].width*this.scale < this.constants.clustering.screenSizeThreshold * this.frame.canvas.clientWidth) || + (this.sectors["active"][sector]["drawingNode"].height*this.scale < this.constants.clustering.screenSizeThreshold * this.frame.canvas.clientHeight)) { + var previousSector = this._previousSector(); - // group to the largest node - if (childNode.id != parentNode.id) { - if (parentNode.options.mass > childNode.options.mass) { - this._addToCluster(parentNode,childNode,true); - } - else { - this._addToCluster(childNode,parentNode,true); - } - } - } - } - } - }; + // we collapse the sector back to a single cluster + this._collapseThisToSingleCluster(); + // we move the remaining nodes, edges and nodeIndices to the previous sector. + // This previous sector is the one we will reactivate + this._mergeThisWithFrozen(previousSector); - /** - * To keep the nodes of roughly equal size we normalize the cluster levels. - * This function clusters a node to its smallest connected neighbour. - * - * @param node - * @private - */ - exports._clusterToSmallestNeighbour = function(node) { - var smallestNeighbour = -1; - var smallestNeighbourNode = null; - for (var i = 0; i < node.dynamicEdges.length; i++) { - if (node.dynamicEdges[i] !== undefined) { - var neighbour = null; - if (node.dynamicEdges[i].fromId != node.id) { - neighbour = node.dynamicEdges[i].from; - } - else if (node.dynamicEdges[i].toId != node.id) { - neighbour = node.dynamicEdges[i].to; - } + // the previously active (frozen) sector now has all the data from the currently active sector. + // we can now delete the active sector. + this._deleteActiveSector(sector); + // we activate the previously active (and currently frozen) sector. + this._activateSector(previousSector); - if (neighbour != null && smallestNeighbour > neighbour.clusterSessions.length) { - smallestNeighbour = neighbour.clusterSessions.length; - smallestNeighbourNode = neighbour; - } - } - } + // we load the references from the newly active sector into the global references + this._switchToSector(previousSector); - if (neighbour != null && this.nodes[neighbour.id] !== undefined) { - this._addToCluster(neighbour, node, true); + // we forget the previously active sector because we reverted to the one before + this._forgetLastSector(); + + // finally, we update the node index list. + this._updateNodeIndexList(); + + // we refresh the list with calulation nodes and calculation node indices. + this._updateCalculationNodes(); + } } }; /** - * This function forms clusters from hubs, it loops over all nodes + * This runs a function in all active sectors. This is used in _redraw() and the _initializeForceCalculation(). * - * @param {Boolean} force | Disregard zoom level - * @param {Boolean} onlyEqual | This only clusters a hub with a specific number of edges + * @param {String} runFunction | This is the NAME of a function we want to call in all active sectors + * | we dont pass the function itself because then the "this" is the window object + * | instead of the Network object + * @param {*} [argument] | Optional: arguments to pass to the runFunction * @private */ - exports._formClustersByHub = function(force, onlyEqual) { - // we loop over all nodes in the list - for (var nodeId in this.nodes) { - // we check if it is still available since it can be used by the clustering in this loop - if (this.nodes.hasOwnProperty(nodeId)) { - this._formClusterFromHub(this.nodes[nodeId],force,onlyEqual); + exports._doInAllActiveSectors = function(runFunction,argument) { + if (argument === undefined) { + for (var sector in this.sectors["active"]) { + if (this.sectors["active"].hasOwnProperty(sector)) { + // switch the global references to those of this sector + this._switchToActiveSector(sector); + this[runFunction](); + } + } + } + else { + for (var sector in this.sectors["active"]) { + if (this.sectors["active"].hasOwnProperty(sector)) { + // switch the global references to those of this sector + this._switchToActiveSector(sector); + var args = Array.prototype.splice.call(arguments, 1); + if (args.length > 1) { + this[runFunction](args[0],args[1]); + } + else { + this[runFunction](argument); + } + } } } + // we revert the global references back to our active sector + this._loadLatestSector(); }; + /** - * This function forms a cluster from a specific preselected hub node + * This runs a function in all active sectors. This is used in _redraw() and the _initializeForceCalculation(). * - * @param {Node} hubNode | the node we will cluster as a hub - * @param {Boolean} force | Disregard zoom level - * @param {Boolean} onlyEqual | This only clusters a hub with a specific number of edges - * @param {Number} [absorptionSizeOffset] | + * @param {String} runFunction | This is the NAME of a function we want to call in all active sectors + * | we dont pass the function itself because then the "this" is the window object + * | instead of the Network object + * @param {*} [argument] | Optional: arguments to pass to the runFunction * @private */ - exports._formClusterFromHub = function(hubNode, force, onlyEqual, absorptionSizeOffset) { - if (absorptionSizeOffset === undefined) { - absorptionSizeOffset = 0; + exports._doInSupportSector = function(runFunction,argument) { + if (argument === undefined) { + this._switchToSupportSector(); + this[runFunction](); } - // we decide if the node is a hub - if ((hubNode.dynamicEdgesLength >= this.hubThreshold && onlyEqual == false) || - (hubNode.dynamicEdgesLength == this.hubThreshold && onlyEqual == true)) { - // initialize variables - var dx,dy,length; - var minLength = this.constants.clustering.clusterEdgeThreshold/this.scale; - var allowCluster = false; - - // we create a list of edges because the dynamicEdges change over the course of this loop - var edgesIdarray = []; - var amountOfInitialEdges = hubNode.dynamicEdges.length; - for (var j = 0; j < amountOfInitialEdges; j++) { - edgesIdarray.push(hubNode.dynamicEdges[j].id); - } - - // if the hub clustering is not forces, we check if one of the edges connected - // to a cluster is small enough based on the constants.clustering.clusterEdgeThreshold - if (force == false) { - allowCluster = false; - for (j = 0; j < amountOfInitialEdges; j++) { - var edge = this.edges[edgesIdarray[j]]; - if (edge !== undefined) { - if (edge.connected) { - if (edge.toId != edge.fromId) { - dx = (edge.to.x - edge.from.x); - dy = (edge.to.y - edge.from.y); - length = Math.sqrt(dx * dx + dy * dy); - - if (length < minLength) { - allowCluster = true; - break; - } - } - } - } - } + else { + this._switchToSupportSector(); + var args = Array.prototype.splice.call(arguments, 1); + if (args.length > 1) { + this[runFunction](args[0],args[1]); } - - // start the clustering if allowed - if ((!force && allowCluster) || force) { - // we loop over all edges INITIALLY connected to this hub - for (j = 0; j < amountOfInitialEdges; j++) { - edge = this.edges[edgesIdarray[j]]; - // the edge can be clustered by this function in a previous loop - if (edge !== undefined) { - var childNode = this.nodes[(edge.fromId == hubNode.id) ? edge.toId : edge.fromId]; - // we do not want hubs to merge with other hubs nor do we want to cluster itself. - if ((childNode.dynamicEdges.length <= (this.hubThreshold + absorptionSizeOffset)) && - (childNode.id != hubNode.id)) { - this._addToCluster(hubNode,childNode,force); - } - } - } + else { + this[runFunction](argument); } } + // we revert the global references back to our active sector + this._loadLatestSector(); }; - /** - * This function adds the child node to the parent node, creating a cluster if it is not already. + * This runs a function in all frozen sectors. This is used in the _redraw(). * - * @param {Node} parentNode | this is the node that will house the child node - * @param {Node} childNode | this node will be deleted from the global this.nodes and stored in the parent node - * @param {Boolean} force | true will only update the remainingEdges at the very end of the clustering, ensuring single level collapse + * @param {String} runFunction | This is the NAME of a function we want to call in all active sectors + * | we don't pass the function itself because then the "this" is the window object + * | instead of the Network object + * @param {*} [argument] | Optional: arguments to pass to the runFunction * @private */ - exports._addToCluster = function(parentNode, childNode, force) { - // join child node in the parent node - parentNode.containedNodes[childNode.id] = childNode; - - // manage all the edges connected to the child and parent nodes - for (var i = 0; i < childNode.dynamicEdges.length; i++) { - var edge = childNode.dynamicEdges[i]; - if (edge.toId == parentNode.id || edge.fromId == parentNode.id) { // edge connected to parentNode - this._addToContainedEdges(parentNode,childNode,edge); + exports._doInAllFrozenSectors = function(runFunction,argument) { + if (argument === undefined) { + for (var sector in this.sectors["frozen"]) { + if (this.sectors["frozen"].hasOwnProperty(sector)) { + // switch the global references to those of this sector + this._switchToFrozenSector(sector); + this[runFunction](); + } } - else { - this._connectEdgeToCluster(parentNode,childNode,edge); + } + else { + for (var sector in this.sectors["frozen"]) { + if (this.sectors["frozen"].hasOwnProperty(sector)) { + // switch the global references to those of this sector + this._switchToFrozenSector(sector); + var args = Array.prototype.splice.call(arguments, 1); + if (args.length > 1) { + this[runFunction](args[0],args[1]); + } + else { + this[runFunction](argument); + } + } } } - // a contained node has no dynamic edges. - childNode.dynamicEdges = []; - - // remove circular edges from clusters - this._containCircularEdgesFromNode(parentNode,childNode); - - - // remove the childNode from the global nodes object - delete this.nodes[childNode.id]; - - // update the properties of the child and parent - var massBefore = parentNode.options.mass; - childNode.clusterSession = this.clusterSession; - parentNode.options.mass += childNode.options.mass; - parentNode.clusterSize += childNode.clusterSize; - parentNode.options.fontSize = Math.min(this.constants.clustering.maxFontSize, this.constants.nodes.fontSize + this.constants.clustering.fontSizeMultiplier*parentNode.clusterSize); + this._loadLatestSector(); + }; - // keep track of the clustersessions so we can open the cluster up as it has been formed. - if (parentNode.clusterSessions[parentNode.clusterSessions.length - 1] != this.clusterSession) { - parentNode.clusterSessions.push(this.clusterSession); - } - // forced clusters only open from screen size and double tap - if (force == true) { - // parentNode.formationScale = Math.pow(1 - (1.0/11.0),this.clusterSession+3); - parentNode.formationScale = 0; + /** + * This runs a function in all sectors. This is used in the _redraw(). + * + * @param {String} runFunction | This is the NAME of a function we want to call in all active sectors + * | we don't pass the function itself because then the "this" is the window object + * | instead of the Network object + * @param {*} [argument] | Optional: arguments to pass to the runFunction + * @private + */ + exports._doInAllSectors = function(runFunction,argument) { + var args = Array.prototype.splice.call(arguments, 1); + if (argument === undefined) { + this._doInAllActiveSectors(runFunction); + this._doInAllFrozenSectors(runFunction); } else { - parentNode.formationScale = this.scale; // The latest child has been added on this scale + if (args.length > 1) { + this._doInAllActiveSectors(runFunction,args[0],args[1]); + this._doInAllFrozenSectors(runFunction,args[0],args[1]); + } + else { + this._doInAllActiveSectors(runFunction,argument); + this._doInAllFrozenSectors(runFunction,argument); + } } + }; - // recalculate the size of the node on the next time the node is rendered - parentNode.clearSizeCache(); - - // set the pop-out scale for the childnode - parentNode.containedNodes[childNode.id].formationScale = parentNode.formationScale; - - // nullify the movement velocity of the child, this is to avoid hectic behaviour - childNode.clearVelocity(); - - // the mass has altered, preservation of energy dictates the velocity to be updated - parentNode.updateVelocity(massBefore); - // restart the simulation to reorganise all nodes - this.moving = true; + /** + * This clears the nodeIndices list. We cannot use this.nodeIndices = [] because we would break the link with the + * active sector. Thus we clear the nodeIndices in the active sector, then reconnect the this.nodeIndices to it. + * + * @private + */ + exports._clearNodeIndexList = function() { + var sector = this._sector(); + this.sectors["active"][sector]["nodeIndices"] = []; + this.nodeIndices = this.sectors["active"][sector]["nodeIndices"]; }; /** - * This function will apply the changes made to the remainingEdges during the formation of the clusters. - * This is a seperate function to allow for level-wise collapsing of the node barnesHutTree. - * It has to be called if a level is collapsed. It is called by _formClusters(). + * Draw the encompassing sector node + * + * @param ctx + * @param sectorType * @private */ - exports._updateDynamicEdges = function() { - for (var i = 0; i < this.nodeIndices.length; i++) { - var node = this.nodes[this.nodeIndices[i]]; - node.dynamicEdgesLength = node.dynamicEdges.length; + exports._drawSectorNodes = function(ctx,sectorType) { + var minY = 1e9, maxY = -1e9, minX = 1e9, maxX = -1e9, node; + for (var sector in this.sectors[sectorType]) { + if (this.sectors[sectorType].hasOwnProperty(sector)) { + if (this.sectors[sectorType][sector]["drawingNode"] !== undefined) { - // this corrects for multiple edges pointing at the same other node - var correction = 0; - if (node.dynamicEdgesLength > 1) { - for (var j = 0; j < node.dynamicEdgesLength - 1; j++) { - var edgeToId = node.dynamicEdges[j].toId; - var edgeFromId = node.dynamicEdges[j].fromId; - for (var k = j+1; k < node.dynamicEdgesLength; k++) { - if ((node.dynamicEdges[k].toId == edgeToId && node.dynamicEdges[k].fromId == edgeFromId) || - (node.dynamicEdges[k].fromId == edgeToId && node.dynamicEdges[k].toId == edgeFromId)) { - correction += 1; + this._switchToSector(sector,sectorType); + + minY = 1e9; maxY = -1e9; minX = 1e9; maxX = -1e9; + for (var nodeId in this.nodes) { + if (this.nodes.hasOwnProperty(nodeId)) { + node = this.nodes[nodeId]; + node.resize(ctx); + if (minX > node.x - 0.5 * node.width) {minX = node.x - 0.5 * node.width;} + if (maxX < node.x + 0.5 * node.width) {maxX = node.x + 0.5 * node.width;} + if (minY > node.y - 0.5 * node.height) {minY = node.y - 0.5 * node.height;} + if (maxY < node.y + 0.5 * node.height) {maxY = node.y + 0.5 * node.height;} } } + node = this.sectors[sectorType][sector]["drawingNode"]; + node.x = 0.5 * (maxX + minX); + node.y = 0.5 * (maxY + minY); + node.width = 2 * (node.x - minX); + node.height = 2 * (node.y - minY); + node.radius = Math.sqrt(Math.pow(0.5*node.width,2) + Math.pow(0.5*node.height,2)); + node.setScale(this.scale); + node._drawCircle(ctx); } } - node.dynamicEdgesLength -= correction; } }; + exports._drawAllSectorNodes = function(ctx) { + this._drawSectorNodes(ctx,"frozen"); + this._drawSectorNodes(ctx,"active"); + this._loadLatestSector(); + }; + + +/***/ }, +/* 52 */ +/***/ function(module, exports, __webpack_require__) { + + var Node = __webpack_require__(36); /** - * This adds an edge from the childNode to the contained edges of the parent node + * This function can be called from the _doInAllSectors function * - * @param parentNode | Node object - * @param childNode | Node object - * @param edge | Edge object + * @param object + * @param overlappingNodes * @private */ - exports._addToContainedEdges = function(parentNode, childNode, edge) { - // create an array object if it does not yet exist for this childNode - if (!(parentNode.containedEdges.hasOwnProperty(childNode.id))) { - parentNode.containedEdges[childNode.id] = [] - } - // add this edge to the list - parentNode.containedEdges[childNode.id].push(edge); - - // remove the edge from the global edges object - delete this.edges[edge.id]; - - // remove the edge from the parent object - for (var i = 0; i < parentNode.dynamicEdges.length; i++) { - if (parentNode.dynamicEdges[i].id == edge.id) { - parentNode.dynamicEdges.splice(i,1); - break; + exports._getNodesOverlappingWith = function(object, overlappingNodes) { + var nodes = this.nodes; + for (var nodeId in nodes) { + if (nodes.hasOwnProperty(nodeId)) { + if (nodes[nodeId].isOverlappingWith(object)) { + overlappingNodes.push(nodeId); + } } } }; /** - * This function connects an edge that was connected to a child node to the parent node. - * It keeps track of which nodes it has been connected to with the originalId array. - * - * @param {Node} parentNode | Node object - * @param {Node} childNode | Node object - * @param {Edge} edge | Edge object + * retrieve all nodes overlapping with given object + * @param {Object} object An object with parameters left, top, right, bottom + * @return {Number[]} An array with id's of the overlapping nodes * @private */ - exports._connectEdgeToCluster = function(parentNode, childNode, edge) { - // handle circular edges - if (edge.toId == edge.fromId) { - this._addToContainedEdges(parentNode, childNode, edge); - } - else { - if (edge.toId == childNode.id) { // edge connected to other node on the "to" side - edge.originalToId.push(childNode.id); - edge.to = parentNode; - edge.toId = parentNode.id; - } - else { // edge connected to other node with the "from" side - - edge.originalFromId.push(childNode.id); - edge.from = parentNode; - edge.fromId = parentNode.id; - } - - this._addToReroutedEdges(parentNode,childNode,edge); - } + exports._getAllNodesOverlappingWith = function (object) { + var overlappingNodes = []; + this._doInAllActiveSectors("_getNodesOverlappingWith",object,overlappingNodes); + return overlappingNodes; }; /** - * If a node is connected to itself, a circular edge is drawn. When clustering we want to contain - * these edges inside of the cluster. + * Return a position object in canvasspace from a single point in screenspace * - * @param parentNode - * @param childNode + * @param pointer + * @returns {{left: number, top: number, right: number, bottom: number}} * @private */ - exports._containCircularEdgesFromNode = function(parentNode, childNode) { - // manage all the edges connected to the child and parent nodes - for (var i = 0; i < parentNode.dynamicEdges.length; i++) { - var edge = parentNode.dynamicEdges[i]; - // handle circular edges - if (edge.toId == edge.fromId) { - this._addToContainedEdges(parentNode, childNode, edge); - } - } + exports._pointerToPositionObject = function(pointer) { + var x = this._XconvertDOMtoCanvas(pointer.x); + var y = this._YconvertDOMtoCanvas(pointer.y); + + return { + left: x, + top: y, + right: x, + bottom: y + }; }; /** - * This adds an edge from the childNode to the rerouted edges of the parent node + * Get the top node at the a specific point (like a click) * - * @param parentNode | Node object - * @param childNode | Node object - * @param edge | Edge object + * @param {{x: Number, y: Number}} pointer + * @return {Node | null} node * @private */ - exports._addToReroutedEdges = function(parentNode, childNode, edge) { - // create an array object if it does not yet exist for this childNode - // we store the edge in the rerouted edges so we can restore it when the cluster pops open - if (!(parentNode.reroutedEdges.hasOwnProperty(childNode.id))) { - parentNode.reroutedEdges[childNode.id] = []; - } - parentNode.reroutedEdges[childNode.id].push(edge); - - // this edge becomes part of the dynamicEdges of the cluster node - parentNode.dynamicEdges.push(edge); - }; + exports._getNodeAt = function (pointer) { + // we first check if this is an navigation controls element + var positionObject = this._pointerToPositionObject(pointer); + var overlappingNodes = this._getAllNodesOverlappingWith(positionObject); + // if there are overlapping nodes, select the last one, this is the + // one which is drawn on top of the others + if (overlappingNodes.length > 0) { + return this.nodes[overlappingNodes[overlappingNodes.length - 1]]; + } + else { + return null; + } + }; /** - * This function connects an edge that was connected to a cluster node back to the child node. - * - * @param parentNode | Node object - * @param childNode | Node object + * retrieve all edges overlapping with given object, selector is around center + * @param {Object} object An object with parameters left, top, right, bottom + * @return {Number[]} An array with id's of the overlapping nodes * @private */ - exports._connectEdgeBackToChild = function(parentNode, childNode) { - if (parentNode.reroutedEdges.hasOwnProperty(childNode.id)) { - for (var i = 0; i < parentNode.reroutedEdges[childNode.id].length; i++) { - var edge = parentNode.reroutedEdges[childNode.id][i]; - if (edge.originalFromId[edge.originalFromId.length-1] == childNode.id) { - edge.originalFromId.pop(); - edge.fromId = childNode.id; - edge.from = childNode; - } - else { - edge.originalToId.pop(); - edge.toId = childNode.id; - edge.to = childNode; - } - - // append this edge to the list of edges connecting to the childnode - childNode.dynamicEdges.push(edge); - - // remove the edge from the parent object - for (var j = 0; j < parentNode.dynamicEdges.length; j++) { - if (parentNode.dynamicEdges[j].id == edge.id) { - parentNode.dynamicEdges.splice(j,1); - break; - } + exports._getEdgesOverlappingWith = function (object, overlappingEdges) { + var edges = this.edges; + for (var edgeId in edges) { + if (edges.hasOwnProperty(edgeId)) { + if (edges[edgeId].isOverlappingWith(object)) { + overlappingEdges.push(edgeId); } } - // remove the entry from the rerouted edges - delete parentNode.reroutedEdges[childNode.id]; } }; /** - * When loops are clustered, an edge can be both in the rerouted array and the contained array. - * This function is called last to verify that all edges in dynamicEdges are in fact connected to the - * parentNode - * - * @param parentNode | Node object + * retrieve all nodes overlapping with given object + * @param {Object} object An object with parameters left, top, right, bottom + * @return {Number[]} An array with id's of the overlapping nodes * @private */ - exports._validateEdges = function(parentNode) { - for (var i = 0; i < parentNode.dynamicEdges.length; i++) { - var edge = parentNode.dynamicEdges[i]; - if (parentNode.id != edge.toId && parentNode.id != edge.fromId) { - parentNode.dynamicEdges.splice(i,1); - } - } + exports._getAllEdgesOverlappingWith = function (object) { + var overlappingEdges = []; + this._doInAllActiveSectors("_getEdgesOverlappingWith",object,overlappingEdges); + return overlappingEdges; }; - /** - * This function released the contained edges back into the global domain and puts them back into the - * dynamic edges of both parent and child. + * Place holder. To implement change the _getNodeAt to a _getObjectAt. Have the _getObjectAt call + * _getNodeAt and _getEdgesAt, then priortize the selection to user preferences. * - * @param {Node} parentNode | - * @param {Node} childNode | + * @param pointer + * @returns {null} * @private */ - exports._releaseContainedEdges = function(parentNode, childNode) { - for (var i = 0; i < parentNode.containedEdges[childNode.id].length; i++) { - var edge = parentNode.containedEdges[childNode.id][i]; - - // put the edge back in the global edges object - this.edges[edge.id] = edge; + exports._getEdgeAt = function(pointer) { + var positionObject = this._pointerToPositionObject(pointer); + var overlappingEdges = this._getAllEdgesOverlappingWith(positionObject); - // put the edge back in the dynamic edges of the child and parent - childNode.dynamicEdges.push(edge); - parentNode.dynamicEdges.push(edge); + if (overlappingEdges.length > 0) { + return this.edges[overlappingEdges[overlappingEdges.length - 1]]; + } + else { + return null; } - // remove the entry from the contained edges - delete parentNode.containedEdges[childNode.id]; - }; - - - // ------------------- UTILITY FUNCTIONS ---------------------------- // - - /** - * This updates the node labels for all nodes (for debugging purposes) + * Add object to the selection array. + * + * @param obj + * @private */ - exports.updateLabels = function() { - var nodeId; - // update node labels - for (nodeId in this.nodes) { - if (this.nodes.hasOwnProperty(nodeId)) { - var node = this.nodes[nodeId]; - if (node.clusterSize > 1) { - node.label = "[".concat(String(node.clusterSize),"]"); - } - } + exports._addToSelection = function(obj) { + if (obj instanceof Node) { + this.selectionObj.nodes[obj.id] = obj; } - - // update node labels - for (nodeId in this.nodes) { - if (this.nodes.hasOwnProperty(nodeId)) { - node = this.nodes[nodeId]; - if (node.clusterSize == 1) { - if (node.originalLabel !== undefined) { - node.label = node.originalLabel; - } - else { - node.label = String(node.id); - } - } - } + else { + this.selectionObj.edges[obj.id] = obj; } - - // /* Debug Override */ - // for (nodeId in this.nodes) { - // if (this.nodes.hasOwnProperty(nodeId)) { - // node = this.nodes[nodeId]; - // node.label = String(node.level); - // } - // } - }; - /** - * We want to keep the cluster level distribution rather small. This means we do not want unclustered nodes - * if the rest of the nodes are already a few cluster levels in. - * To fix this we use this function. It determines the min and max cluster level and sends nodes that have not - * clustered enough to the clusterToSmallestNeighbours function. + * Add object to the selection array. + * + * @param obj + * @private */ - exports.normalizeClusterLevels = function() { - var maxLevel = 0; - var minLevel = 1e9; - var clusterLevel = 0; - var nodeId; - - // we loop over all nodes in the list - for (nodeId in this.nodes) { - if (this.nodes.hasOwnProperty(nodeId)) { - clusterLevel = this.nodes[nodeId].clusterSessions.length; - if (maxLevel < clusterLevel) {maxLevel = clusterLevel;} - if (minLevel > clusterLevel) {minLevel = clusterLevel;} - } + exports._addToHover = function(obj) { + if (obj instanceof Node) { + this.hoverObj.nodes[obj.id] = obj; } - - if (maxLevel - minLevel > this.constants.clustering.clusterLevelDifference) { - var amountOfNodes = this.nodeIndices.length; - var targetLevel = maxLevel - this.constants.clustering.clusterLevelDifference; - // we loop over all nodes in the list - for (nodeId in this.nodes) { - if (this.nodes.hasOwnProperty(nodeId)) { - if (this.nodes[nodeId].clusterSessions.length < targetLevel) { - this._clusterToSmallestNeighbour(this.nodes[nodeId]); - } - } - } - this._updateNodeIndexList(); - this._updateDynamicEdges(); - // if a cluster was formed, we increase the clusterSession - if (this.nodeIndices.length != amountOfNodes) { - this.clusterSession += 1; - } + else { + this.hoverObj.edges[obj.id] = obj; } }; - /** - * This function determines if the cluster we want to decluster is in the active area - * this means around the zoom center + * Remove a single option from selection. * - * @param {Node} node - * @returns {boolean} + * @param {Object} obj * @private */ - exports._nodeInActiveArea = function(node) { - return ( - Math.abs(node.x - this.areaCenter.x) <= this.constants.clustering.activeAreaBoxSize/this.scale - && - Math.abs(node.y - this.areaCenter.y) <= this.constants.clustering.activeAreaBoxSize/this.scale - ) + exports._removeFromSelection = function(obj) { + if (obj instanceof Node) { + delete this.selectionObj.nodes[obj.id]; + } + else { + delete this.selectionObj.edges[obj.id]; + } }; - /** - * This is an adaptation of the original repositioning function. This is called if the system is clustered initially - * It puts large clusters away from the center and randomizes the order. + * Unselect all. The selectionObj is useful for this. * + * @param {Boolean} [doNotTrigger] | ignore trigger + * @private */ - exports.repositionNodes = function() { - for (var i = 0; i < this.nodeIndices.length; i++) { - var node = this.nodes[this.nodeIndices[i]]; - if ((node.xFixed == false || node.yFixed == false)) { - var radius = 10 * 0.1*this.nodeIndices.length * Math.min(100,node.options.mass); - var angle = 2 * Math.PI * Math.random(); - if (node.xFixed == false) {node.x = radius * Math.cos(angle);} - if (node.yFixed == false) {node.y = radius * Math.sin(angle);} - this._repositionBezierNodes(node); + exports._unselectAll = function(doNotTrigger) { + if (doNotTrigger === undefined) { + doNotTrigger = false; + } + for(var nodeId in this.selectionObj.nodes) { + if(this.selectionObj.nodes.hasOwnProperty(nodeId)) { + this.selectionObj.nodes[nodeId].unselect(); + } + } + for(var edgeId in this.selectionObj.edges) { + if(this.selectionObj.edges.hasOwnProperty(edgeId)) { + this.selectionObj.edges[edgeId].unselect(); } } - }; + this.selectionObj = {nodes:{},edges:{}}; + + if (doNotTrigger == false) { + this.emit('select', this.getSelection()); + } + }; /** - * We determine how many connections denote an important hub. - * We take the mean + 2*std as the important hub size. (Assuming a normal distribution of data, ~2.2%) + * Unselect all clusters. The selectionObj is useful for this. * + * @param {Boolean} [doNotTrigger] | ignore trigger * @private */ - exports._getHubSize = function() { - var average = 0; - var averageSquared = 0; - var hubCounter = 0; - var largestHub = 0; - - for (var i = 0; i < this.nodeIndices.length; i++) { + exports._unselectClusters = function(doNotTrigger) { + if (doNotTrigger === undefined) { + doNotTrigger = false; + } - var node = this.nodes[this.nodeIndices[i]]; - if (node.dynamicEdgesLength > largestHub) { - largestHub = node.dynamicEdgesLength; + for (var nodeId in this.selectionObj.nodes) { + if (this.selectionObj.nodes.hasOwnProperty(nodeId)) { + if (this.selectionObj.nodes[nodeId].clusterSize > 1) { + this.selectionObj.nodes[nodeId].unselect(); + this._removeFromSelection(this.selectionObj.nodes[nodeId]); + } } - average += node.dynamicEdgesLength; - averageSquared += Math.pow(node.dynamicEdgesLength,2); - hubCounter += 1; } - average = average / hubCounter; - averageSquared = averageSquared / hubCounter; - - var variance = averageSquared - Math.pow(average,2); - - var standardDeviation = Math.sqrt(variance); - - this.hubThreshold = Math.floor(average + 2*standardDeviation); - // always have at least one to cluster - if (this.hubThreshold > largestHub) { - this.hubThreshold = largestHub; + if (doNotTrigger == false) { + this.emit('select', this.getSelection()); } - - // console.log("average",average,"averageSQ",averageSquared,"var",variance,"std",standardDeviation); - // console.log("hubThreshold:",this.hubThreshold); }; /** - * We reduce the amount of "extension nodes" or chains. These are not quickly clustered with the outliers and hubs methods - * with this amount we can cluster specifically on these chains. + * return the number of selected nodes * - * @param {Number} fraction | between 0 and 1, the percentage of chains to reduce + * @returns {number} * @private */ - exports._reduceAmountOfChains = function(fraction) { - this.hubThreshold = 2; - var reduceAmount = Math.floor(this.nodeIndices.length * fraction); - for (var nodeId in this.nodes) { - if (this.nodes.hasOwnProperty(nodeId)) { - if (this.nodes[nodeId].dynamicEdgesLength == 2 && this.nodes[nodeId].dynamicEdges.length >= 2) { - if (reduceAmount > 0) { - this._formClusterFromHub(this.nodes[nodeId],true,true,1); - reduceAmount -= 1; - } - } + exports._getSelectedNodeCount = function() { + var count = 0; + for (var nodeId in this.selectionObj.nodes) { + if (this.selectionObj.nodes.hasOwnProperty(nodeId)) { + count += 1; } } + return count; }; /** - * We get the amount of "extension nodes" or chains. These are not quickly clustered with the outliers and hubs methods - * with this amount we can cluster specifically on these chains. + * return the selected node * + * @returns {number} * @private */ - exports._getChainFraction = function() { - var chains = 0; - var total = 0; - for (var nodeId in this.nodes) { - if (this.nodes.hasOwnProperty(nodeId)) { - if (this.nodes[nodeId].dynamicEdgesLength == 2 && this.nodes[nodeId].dynamicEdges.length >= 2) { - chains += 1; - } - total += 1; + exports._getSelectedNode = function() { + for (var nodeId in this.selectionObj.nodes) { + if (this.selectionObj.nodes.hasOwnProperty(nodeId)) { + return this.selectionObj.nodes[nodeId]; } } - return chains/total; + return null; }; - -/***/ }, -/* 56 */ -/***/ function(module, exports, __webpack_require__) { - - var util = __webpack_require__(1); - /** - * Creation of the SectorMixin var. + * return the selected edge * - * This contains all the functions the Network object can use to employ the sector system. - * The sector system is always used by Network, though the benefits only apply to the use of clustering. - * If clustering is not used, there is no overhead except for a duplicate object with references to nodes and edges. + * @returns {number} + * @private */ + exports._getSelectedEdge = function() { + for (var edgeId in this.selectionObj.edges) { + if (this.selectionObj.edges.hasOwnProperty(edgeId)) { + return this.selectionObj.edges[edgeId]; + } + } + return null; + }; + /** - * This function is only called by the setData function of the Network object. - * This loads the global references into the active sector. This initializes the sector. + * return the number of selected edges * + * @returns {number} * @private */ - exports._putDataInSector = function() { - this.sectors["active"][this._sector()].nodes = this.nodes; - this.sectors["active"][this._sector()].edges = this.edges; - this.sectors["active"][this._sector()].nodeIndices = this.nodeIndices; + exports._getSelectedEdgeCount = function() { + var count = 0; + for (var edgeId in this.selectionObj.edges) { + if (this.selectionObj.edges.hasOwnProperty(edgeId)) { + count += 1; + } + } + return count; }; /** - * /** - * This function sets the global references to nodes, edges and nodeIndices back to - * those of the supplied (active) sector. If a type is defined, do the specific type + * return the number of selected objects. * - * @param {String} sectorId - * @param {String} [sectorType] | "active" or "frozen" + * @returns {number} * @private */ - exports._switchToSector = function(sectorId, sectorType) { - if (sectorType === undefined || sectorType == "active") { - this._switchToActiveSector(sectorId); + exports._getSelectedObjectCount = function() { + var count = 0; + for(var nodeId in this.selectionObj.nodes) { + if(this.selectionObj.nodes.hasOwnProperty(nodeId)) { + count += 1; + } } - else { - this._switchToFrozenSector(sectorId); + for(var edgeId in this.selectionObj.edges) { + if(this.selectionObj.edges.hasOwnProperty(edgeId)) { + count += 1; + } } + return count; }; - /** - * This function sets the global references to nodes, edges and nodeIndices back to - * those of the supplied active sector. + * Check if anything is selected * - * @param sectorId + * @returns {boolean} * @private */ - exports._switchToActiveSector = function(sectorId) { - this.nodeIndices = this.sectors["active"][sectorId]["nodeIndices"]; - this.nodes = this.sectors["active"][sectorId]["nodes"]; - this.edges = this.sectors["active"][sectorId]["edges"]; + exports._selectionIsEmpty = function() { + for(var nodeId in this.selectionObj.nodes) { + if(this.selectionObj.nodes.hasOwnProperty(nodeId)) { + return false; + } + } + for(var edgeId in this.selectionObj.edges) { + if(this.selectionObj.edges.hasOwnProperty(edgeId)) { + return false; + } + } + return true; }; /** - * This function sets the global references to nodes, edges and nodeIndices back to - * those of the supplied active sector. + * check if one of the selected nodes is a cluster. * + * @returns {boolean} * @private */ - exports._switchToSupportSector = function() { - this.nodeIndices = this.sectors["support"]["nodeIndices"]; - this.nodes = this.sectors["support"]["nodes"]; - this.edges = this.sectors["support"]["edges"]; + exports._clusterInSelection = function() { + for(var nodeId in this.selectionObj.nodes) { + if(this.selectionObj.nodes.hasOwnProperty(nodeId)) { + if (this.selectionObj.nodes[nodeId].clusterSize > 1) { + return true; + } + } + } + return false; }; - /** - * This function sets the global references to nodes, edges and nodeIndices back to - * those of the supplied frozen sector. + * select the edges connected to the node that is being selected * - * @param sectorId + * @param {Node} node * @private */ - exports._switchToFrozenSector = function(sectorId) { - this.nodeIndices = this.sectors["frozen"][sectorId]["nodeIndices"]; - this.nodes = this.sectors["frozen"][sectorId]["nodes"]; - this.edges = this.sectors["frozen"][sectorId]["edges"]; + exports._selectConnectedEdges = function(node) { + for (var i = 0; i < node.dynamicEdges.length; i++) { + var edge = node.dynamicEdges[i]; + edge.select(); + this._addToSelection(edge); + } }; - /** - * This function sets the global references to nodes, edges and nodeIndices back to - * those of the currently active sector. + * select the edges connected to the node that is being selected * + * @param {Node} node * @private */ - exports._loadLatestSector = function() { - this._switchToSector(this._sector()); + exports._hoverConnectedEdges = function(node) { + for (var i = 0; i < node.dynamicEdges.length; i++) { + var edge = node.dynamicEdges[i]; + edge.hover = true; + this._addToHover(edge); + } }; /** - * This function returns the currently active sector Id + * unselect the edges connected to the node that is being selected * - * @returns {String} + * @param {Node} node * @private */ - exports._sector = function() { - return this.activeSector[this.activeSector.length-1]; + exports._unselectConnectedEdges = function(node) { + for (var i = 0; i < node.dynamicEdges.length; i++) { + var edge = node.dynamicEdges[i]; + edge.unselect(); + this._removeFromSelection(edge); + } }; + + /** - * This function returns the previously active sector Id + * This is called when someone clicks on a node. either select or deselect it. + * If there is an existing selection and we don't want to append to it, clear the existing selection * - * @returns {String} + * @param {Node || Edge} object + * @param {Boolean} append + * @param {Boolean} [doNotTrigger] | ignore trigger * @private */ - exports._previousSector = function() { - if (this.activeSector.length > 1) { - return this.activeSector[this.activeSector.length-2]; + exports._selectObject = function(object, append, doNotTrigger, highlightEdges) { + if (doNotTrigger === undefined) { + doNotTrigger = false; + } + if (highlightEdges === undefined) { + highlightEdges = true; + } + + if (this._selectionIsEmpty() == false && append == false && this.forceAppendSelection == false) { + this._unselectAll(true); + } + + if (object.selected == false) { + object.select(); + this._addToSelection(object); + if (object instanceof Node && this.blockConnectingEdgeSelection == false && highlightEdges == true) { + this._selectConnectedEdges(object); + } } else { - throw new TypeError('there are not enough sectors in the this.activeSector array.'); + object.unselect(); + this._removeFromSelection(object); + } + + if (doNotTrigger == false) { + this.emit('select', this.getSelection()); + } + }; + + + /** + * This is called when someone clicks on a node. either select or deselect it. + * If there is an existing selection and we don't want to append to it, clear the existing selection + * + * @param {Node || Edge} object + * @private + */ + exports._blurObject = function(object) { + if (object.hover == true) { + object.hover = false; + this.emit("blurNode",{node:object.id}); } }; - /** - * We add the active sector at the end of the this.activeSector array - * This ensures it is the currently active sector returned by _sector() and it reaches the top - * of the activeSector stack. When we reverse our steps we move from the end to the beginning of this stack. + * This is called when someone clicks on a node. either select or deselect it. + * If there is an existing selection and we don't want to append to it, clear the existing selection * - * @param newId + * @param {Node || Edge} object * @private */ - exports._setActiveSector = function(newId) { - this.activeSector.push(newId); + exports._hoverObject = function(object) { + if (object.hover == false) { + object.hover = true; + this._addToHover(object); + if (object instanceof Node) { + this.emit("hoverNode",{node:object.id}); + } + } + if (object instanceof Node) { + this._hoverConnectedEdges(object); + } }; /** - * We remove the currently active sector id from the active sector stack. This happens when - * we reactivate the previously active sector + * handles the selection part of the touch, only for navigation controls elements; + * Touch is triggered before tap, also before hold. Hold triggers after a while. + * This is the most responsive solution * + * @param {Object} pointer * @private */ - exports._forgetLastSector = function() { - this.activeSector.pop(); + exports._handleTouch = function(pointer) { }; /** - * This function creates a new active sector with the supplied newId. This newId - * is the expanding node id. + * handles the selection part of the tap; * - * @param {String} newId | Id of the new active sector + * @param {Object} pointer * @private */ - exports._createNewSector = function(newId) { - // create the new sector - this.sectors["active"][newId] = {"nodes":{}, - "edges":{}, - "nodeIndices":[], - "formationScale": this.scale, - "drawingNode": undefined}; - - // create the new sector render node. This gives visual feedback that you are in a new sector. - this.sectors["active"][newId]['drawingNode'] = new Node( - {id:newId, - color: { - background: "#eaefef", - border: "495c5e" - } - },{},{},this.constants); - this.sectors["active"][newId]['drawingNode'].clusterSize = 2; + exports._handleTap = function(pointer) { + var node = this._getNodeAt(pointer); + if (node != null) { + this._selectObject(node,false); + } + else { + var edge = this._getEdgeAt(pointer); + if (edge != null) { + this._selectObject(edge,false); + } + else { + this._unselectAll(); + } + } + this.emit("click", this.getSelection()); + this._redraw(); }; /** - * This function removes the currently active sector. This is called when we create a new - * active sector. + * handles the selection part of the double tap and opens a cluster if needed * - * @param {String} sectorId | Id of the active sector that will be removed + * @param {Object} pointer * @private */ - exports._deleteActiveSector = function(sectorId) { - delete this.sectors["active"][sectorId]; + exports._handleDoubleTap = function(pointer) { + var node = this._getNodeAt(pointer); + if (node != null && node !== undefined) { + // we reset the areaCenter here so the opening of the node will occur + this.areaCenter = {"x" : this._XconvertDOMtoCanvas(pointer.x), + "y" : this._YconvertDOMtoCanvas(pointer.y)}; + this.openCluster(node); + } + this.emit("doubleClick", this.getSelection()); }; /** - * This function removes the currently active sector. This is called when we reactivate - * the previously active sector. + * Handle the onHold selection part * - * @param {String} sectorId | Id of the active sector that will be removed + * @param pointer * @private */ - exports._deleteFrozenSector = function(sectorId) { - delete this.sectors["frozen"][sectorId]; + exports._handleOnHold = function(pointer) { + var node = this._getNodeAt(pointer); + if (node != null) { + this._selectObject(node,true); + } + else { + var edge = this._getEdgeAt(pointer); + if (edge != null) { + this._selectObject(edge,true); + } + } + this._redraw(); }; /** - * Freezing an active sector means moving it from the "active" object to the "frozen" object. - * We copy the references, then delete the active entree. + * handle the onRelease event. These functions are here for the navigation controls module. * - * @param sectorId - * @private + * @private */ - exports._freezeSector = function(sectorId) { - // we move the set references from the active to the frozen stack. - this.sectors["frozen"][sectorId] = this.sectors["active"][sectorId]; + exports._handleOnRelease = function(pointer) { - // we have moved the sector data into the frozen set, we now remove it from the active set - this._deleteActiveSector(sectorId); }; + /** - * This is the reverse operation of _freezeSector. Activating means moving the sector from the "frozen" - * object to the "active" object. * - * @param sectorId - * @private + * retrieve the currently selected objects + * @return {{nodes: Array., edges: Array.}} selection */ - exports._activateSector = function(sectorId) { - // we move the set references from the frozen to the active stack. - this.sectors["active"][sectorId] = this.sectors["frozen"][sectorId]; - - // we have moved the sector data into the active set, we now remove it from the frozen stack - this._deleteFrozenSector(sectorId); + exports.getSelection = function() { + var nodeIds = this.getSelectedNodes(); + var edgeIds = this.getSelectedEdges(); + return {nodes:nodeIds, edges:edgeIds}; }; - /** - * This function merges the data from the currently active sector with a frozen sector. This is used - * in the process of reverting back to the previously active sector. - * The data that is placed in the frozen (the previously active) sector is the node that has been removed from it - * upon the creation of a new active sector. * - * @param sectorId - * @private + * retrieve the currently selected nodes + * @return {String[]} selection An array with the ids of the + * selected nodes. */ - exports._mergeThisWithFrozen = function(sectorId) { - // copy all nodes - for (var nodeId in this.nodes) { - if (this.nodes.hasOwnProperty(nodeId)) { - this.sectors["frozen"][sectorId]["nodes"][nodeId] = this.nodes[nodeId]; - } - } - - // copy all edges (if not fully clustered, else there are no edges) - for (var edgeId in this.edges) { - if (this.edges.hasOwnProperty(edgeId)) { - this.sectors["frozen"][sectorId]["edges"][edgeId] = this.edges[edgeId]; + exports.getSelectedNodes = function() { + var idArray = []; + for(var nodeId in this.selectionObj.nodes) { + if(this.selectionObj.nodes.hasOwnProperty(nodeId)) { + idArray.push(nodeId); } } - - // merge the nodeIndices - for (var i = 0; i < this.nodeIndices.length; i++) { - this.sectors["frozen"][sectorId]["nodeIndices"].push(this.nodeIndices[i]); - } + return idArray }; - /** - * This clusters the sector to one cluster. It was a single cluster before this process started so - * we revert to that state. The clusterToFit function with a maximum size of 1 node does this. * - * @private + * retrieve the currently selected edges + * @return {Array} selection An array with the ids of the + * selected nodes. */ - exports._collapseThisToSingleCluster = function() { - this.clusterToFit(1,false); + exports.getSelectedEdges = function() { + var idArray = []; + for(var edgeId in this.selectionObj.edges) { + if(this.selectionObj.edges.hasOwnProperty(edgeId)) { + idArray.push(edgeId); + } + } + return idArray; }; /** - * We create a new active sector from the node that we want to open. - * - * @param node - * @private + * select zero or more nodes + * @param {Number[] | String[]} selection An array with the ids of the + * selected nodes. */ - exports._addSector = function(node) { - // this is the currently active sector - var sector = this._sector(); - - // // this should allow me to select nodes from a frozen set. - // if (this.sectors['active'][sector]["nodes"].hasOwnProperty(node.id)) { - // console.log("the node is part of the active sector"); - // } - // else { - // console.log("I dont know what the fuck happened!!"); - // } - - // when we switch to a new sector, we remove the node that will be expanded from the current nodes list. - delete this.nodes[node.id]; + exports.setSelection = function(selection) { + var i, iMax, id; - var unqiueIdentifier = util.randomUUID(); + if (!selection || (selection.length == undefined)) + throw 'Selection must be an array with ids'; - // we fully freeze the currently active sector - this._freezeSector(sector); + // first unselect any selected node + this._unselectAll(true); - // we create a new active sector. This sector has the Id of the node to ensure uniqueness - this._createNewSector(unqiueIdentifier); + for (i = 0, iMax = selection.length; i < iMax; i++) { + id = selection[i]; - // we add the active sector to the sectors array to be able to revert these steps later on - this._setActiveSector(unqiueIdentifier); + var node = this.nodes[id]; + if (!node) { + throw new RangeError('Node with id "' + id + '" not found'); + } + this._selectObject(node,true,true); + } - // we redirect the global references to the new sector's references. this._sector() now returns unqiueIdentifier - this._switchToSector(this._sector()); + console.log("setSelection is deprecated. Please use selectNodes instead.") - // finally we add the node we removed from our previous active sector to the new active sector - this.nodes[node.id] = node; + this.redraw(); }; /** - * We close the sector that is currently open and revert back to the one before. - * If the active sector is the "default" sector, nothing happens. - * - * @private + * select zero or more nodes with the option to highlight edges + * @param {Number[] | String[]} selection An array with the ids of the + * selected nodes. + * @param {boolean} [highlightEdges] */ - exports._collapseSector = function() { - // the currently active sector - var sector = this._sector(); + exports.selectNodes = function(selection, highlightEdges) { + var i, iMax, id; - // we cannot collapse the default sector - if (sector != "default") { - if ((this.nodeIndices.length == 1) || - (this.sectors["active"][sector]["drawingNode"].width*this.scale < this.constants.clustering.screenSizeThreshold * this.frame.canvas.clientWidth) || - (this.sectors["active"][sector]["drawingNode"].height*this.scale < this.constants.clustering.screenSizeThreshold * this.frame.canvas.clientHeight)) { - var previousSector = this._previousSector(); + if (!selection || (selection.length == undefined)) + throw 'Selection must be an array with ids'; - // we collapse the sector back to a single cluster - this._collapseThisToSingleCluster(); + // first unselect any selected node + this._unselectAll(true); + + for (i = 0, iMax = selection.length; i < iMax; i++) { + id = selection[i]; - // we move the remaining nodes, edges and nodeIndices to the previous sector. - // This previous sector is the one we will reactivate - this._mergeThisWithFrozen(previousSector); + var node = this.nodes[id]; + if (!node) { + throw new RangeError('Node with id "' + id + '" not found'); + } + this._selectObject(node,true,true,highlightEdges); + } + this.redraw(); + }; - // the previously active (frozen) sector now has all the data from the currently active sector. - // we can now delete the active sector. - this._deleteActiveSector(sector); - // we activate the previously active (and currently frozen) sector. - this._activateSector(previousSector); + /** + * select zero or more edges + * @param {Number[] | String[]} selection An array with the ids of the + * selected nodes. + */ + exports.selectEdges = function(selection) { + var i, iMax, id; - // we load the references from the newly active sector into the global references - this._switchToSector(previousSector); + if (!selection || (selection.length == undefined)) + throw 'Selection must be an array with ids'; - // we forget the previously active sector because we reverted to the one before - this._forgetLastSector(); + // first unselect any selected node + this._unselectAll(true); - // finally, we update the node index list. - this._updateNodeIndexList(); + for (i = 0, iMax = selection.length; i < iMax; i++) { + id = selection[i]; - // we refresh the list with calulation nodes and calculation node indices. - this._updateCalculationNodes(); + var edge = this.edges[id]; + if (!edge) { + throw new RangeError('Edge with id "' + id + '" not found'); } + this._selectObject(edge,true,true,highlightEdges); } + this.redraw(); }; - /** - * This runs a function in all active sectors. This is used in _redraw() and the _initializeForceCalculation(). - * - * @param {String} runFunction | This is the NAME of a function we want to call in all active sectors - * | we dont pass the function itself because then the "this" is the window object - * | instead of the Network object - * @param {*} [argument] | Optional: arguments to pass to the runFunction + * Validate the selection: remove ids of nodes which no longer exist * @private */ - exports._doInAllActiveSectors = function(runFunction,argument) { - if (argument === undefined) { - for (var sector in this.sectors["active"]) { - if (this.sectors["active"].hasOwnProperty(sector)) { - // switch the global references to those of this sector - this._switchToActiveSector(sector); - this[runFunction](); + exports._updateSelection = function () { + for(var nodeId in this.selectionObj.nodes) { + if(this.selectionObj.nodes.hasOwnProperty(nodeId)) { + if (!this.nodes.hasOwnProperty(nodeId)) { + delete this.selectionObj.nodes[nodeId]; } } } - else { - for (var sector in this.sectors["active"]) { - if (this.sectors["active"].hasOwnProperty(sector)) { - // switch the global references to those of this sector - this._switchToActiveSector(sector); - var args = Array.prototype.splice.call(arguments, 1); - if (args.length > 1) { - this[runFunction](args[0],args[1]); - } - else { - this[runFunction](argument); - } + for(var edgeId in this.selectionObj.edges) { + if(this.selectionObj.edges.hasOwnProperty(edgeId)) { + if (!this.edges.hasOwnProperty(edgeId)) { + delete this.selectionObj.edges[edgeId]; } } } - // we revert the global references back to our active sector - this._loadLatestSector(); }; +/***/ }, +/* 53 */ +/***/ function(module, exports, __webpack_require__) { + + var util = __webpack_require__(1); + var Node = __webpack_require__(36); + var Edge = __webpack_require__(33); + /** - * This runs a function in all active sectors. This is used in _redraw() and the _initializeForceCalculation(). + * clears the toolbar div element of children * - * @param {String} runFunction | This is the NAME of a function we want to call in all active sectors - * | we dont pass the function itself because then the "this" is the window object - * | instead of the Network object - * @param {*} [argument] | Optional: arguments to pass to the runFunction * @private */ - exports._doInSupportSector = function(runFunction,argument) { - if (argument === undefined) { - this._switchToSupportSector(); - this[runFunction](); + exports._clearManipulatorBar = function() { + while (this.manipulationDiv.hasChildNodes()) { + this.manipulationDiv.removeChild(this.manipulationDiv.firstChild); } - else { - this._switchToSupportSector(); - var args = Array.prototype.splice.call(arguments, 1); - if (args.length > 1) { - this[runFunction](args[0],args[1]); - } - else { - this[runFunction](argument); + }; + + /** + * Manipulation UI temporarily overloads certain functions to extend or replace them. To be able to restore + * these functions to their original functionality, we saved them in this.cachedFunctions. + * This function restores these functions to their original function. + * + * @private + */ + exports._restoreOverloadedFunctions = function() { + for (var functionName in this.cachedFunctions) { + if (this.cachedFunctions.hasOwnProperty(functionName)) { + this[functionName] = this.cachedFunctions[functionName]; } } - // we revert the global references back to our active sector - this._loadLatestSector(); }; - /** - * This runs a function in all frozen sectors. This is used in the _redraw(). + * Enable or disable edit-mode. * - * @param {String} runFunction | This is the NAME of a function we want to call in all active sectors - * | we don't pass the function itself because then the "this" is the window object - * | instead of the Network object - * @param {*} [argument] | Optional: arguments to pass to the runFunction * @private */ - exports._doInAllFrozenSectors = function(runFunction,argument) { - if (argument === undefined) { - for (var sector in this.sectors["frozen"]) { - if (this.sectors["frozen"].hasOwnProperty(sector)) { - // switch the global references to those of this sector - this._switchToFrozenSector(sector); - this[runFunction](); - } - } + exports._toggleEditMode = function() { + this.editMode = !this.editMode; + var toolbar = document.getElementById("network-manipulationDiv"); + var closeDiv = document.getElementById("network-manipulation-closeDiv"); + var editModeDiv = document.getElementById("network-manipulation-editMode"); + if (this.editMode == true) { + toolbar.style.display="block"; + closeDiv.style.display="block"; + editModeDiv.style.display="none"; + closeDiv.onclick = this._toggleEditMode.bind(this); } else { - for (var sector in this.sectors["frozen"]) { - if (this.sectors["frozen"].hasOwnProperty(sector)) { - // switch the global references to those of this sector - this._switchToFrozenSector(sector); - var args = Array.prototype.splice.call(arguments, 1); - if (args.length > 1) { - this[runFunction](args[0],args[1]); - } - else { - this[runFunction](argument); - } - } - } + toolbar.style.display="none"; + closeDiv.style.display="none"; + editModeDiv.style.display="block"; + closeDiv.onclick = null; } - this._loadLatestSector(); + this._createManipulatorBar() }; - /** - * This runs a function in all sectors. This is used in the _redraw(). + * main function, creates the main toolbar. Removes functions bound to the select event. Binds all the buttons of the toolbar. * - * @param {String} runFunction | This is the NAME of a function we want to call in all active sectors - * | we don't pass the function itself because then the "this" is the window object - * | instead of the Network object - * @param {*} [argument] | Optional: arguments to pass to the runFunction * @private */ - exports._doInAllSectors = function(runFunction,argument) { - var args = Array.prototype.splice.call(arguments, 1); - if (argument === undefined) { - this._doInAllActiveSectors(runFunction); - this._doInAllFrozenSectors(runFunction); + exports._createManipulatorBar = function() { + // remove bound functions + if (this.boundFunction) { + this.off('select', this.boundFunction); + } + + if (this.edgeBeingEdited !== undefined) { + this.edgeBeingEdited._disableControlNodes(); + this.edgeBeingEdited = undefined; + this.selectedControlNode = null; + this.controlNodesActive = false; + } + + // restore overloaded functions + this._restoreOverloadedFunctions(); + + // resume calculation + this.freezeSimulation = false; + + // reset global variables + this.blockConnectingEdgeSelection = false; + this.forceAppendSelection = false; + + if (this.editMode == true) { + while (this.manipulationDiv.hasChildNodes()) { + this.manipulationDiv.removeChild(this.manipulationDiv.firstChild); + } + // add the icons to the manipulator div + this.manipulationDiv.innerHTML = "" + + "" + + ""+this.constants.labels['add'] +"" + + "
" + + "" + + ""+this.constants.labels['link'] +""; + if (this._getSelectedNodeCount() == 1 && this.triggerFunctions.edit) { + this.manipulationDiv.innerHTML += "" + + "
" + + "" + + ""+this.constants.labels['editNode'] +""; + } + else if (this._getSelectedEdgeCount() == 1 && this._getSelectedNodeCount() == 0) { + this.manipulationDiv.innerHTML += "" + + "
" + + "" + + ""+this.constants.labels['editEdge'] +""; + } + if (this._selectionIsEmpty() == false) { + this.manipulationDiv.innerHTML += "" + + "
" + + "" + + ""+this.constants.labels['del'] +""; + } + + + // bind the icons + var addNodeButton = document.getElementById("network-manipulate-addNode"); + addNodeButton.onclick = this._createAddNodeToolbar.bind(this); + var addEdgeButton = document.getElementById("network-manipulate-connectNode"); + addEdgeButton.onclick = this._createAddEdgeToolbar.bind(this); + if (this._getSelectedNodeCount() == 1 && this.triggerFunctions.edit) { + var editButton = document.getElementById("network-manipulate-editNode"); + editButton.onclick = this._editNode.bind(this); + } + else if (this._getSelectedEdgeCount() == 1 && this._getSelectedNodeCount() == 0) { + var editButton = document.getElementById("network-manipulate-editEdge"); + editButton.onclick = this._createEditEdgeToolbar.bind(this); + } + if (this._selectionIsEmpty() == false) { + var deleteButton = document.getElementById("network-manipulate-delete"); + deleteButton.onclick = this._deleteSelected.bind(this); + } + var closeDiv = document.getElementById("network-manipulation-closeDiv"); + closeDiv.onclick = this._toggleEditMode.bind(this); + + this.boundFunction = this._createManipulatorBar.bind(this); + this.on('select', this.boundFunction); } else { - if (args.length > 1) { - this._doInAllActiveSectors(runFunction,args[0],args[1]); - this._doInAllFrozenSectors(runFunction,args[0],args[1]); - } - else { - this._doInAllActiveSectors(runFunction,argument); - this._doInAllFrozenSectors(runFunction,argument); - } + this.editModeDiv.innerHTML = "" + + "" + + "" + this.constants.labels['edit'] + ""; + var editModeButton = document.getElementById("network-manipulate-editModeButton"); + editModeButton.onclick = this._toggleEditMode.bind(this); } }; + /** - * This clears the nodeIndices list. We cannot use this.nodeIndices = [] because we would break the link with the - * active sector. Thus we clear the nodeIndices in the active sector, then reconnect the this.nodeIndices to it. + * Create the toolbar for adding Nodes * * @private */ - exports._clearNodeIndexList = function() { - var sector = this._sector(); - this.sectors["active"][sector]["nodeIndices"] = []; - this.nodeIndices = this.sectors["active"][sector]["nodeIndices"]; + exports._createAddNodeToolbar = function() { + // clear the toolbar + this._clearManipulatorBar(); + if (this.boundFunction) { + this.off('select', this.boundFunction); + } + + // create the toolbar contents + this.manipulationDiv.innerHTML = "" + + "" + + "" + this.constants.labels['back'] + " " + + "
" + + "" + + "" + this.constants.labels['addDescription'] + ""; + + // bind the icon + var backButton = document.getElementById("network-manipulate-back"); + backButton.onclick = this._createManipulatorBar.bind(this); + + // we use the boundFunction so we can reference it when we unbind it from the "select" event. + this.boundFunction = this._addNode.bind(this); + this.on('select', this.boundFunction); }; /** - * Draw the encompassing sector node + * create the toolbar to connect nodes * - * @param ctx - * @param sectorType * @private */ - exports._drawSectorNodes = function(ctx,sectorType) { - var minY = 1e9, maxY = -1e9, minX = 1e9, maxX = -1e9, node; - for (var sector in this.sectors[sectorType]) { - if (this.sectors[sectorType].hasOwnProperty(sector)) { - if (this.sectors[sectorType][sector]["drawingNode"] !== undefined) { - - this._switchToSector(sector,sectorType); + exports._createAddEdgeToolbar = function() { + // clear the toolbar + this._clearManipulatorBar(); + this._unselectAll(true); + this.freezeSimulation = true; - minY = 1e9; maxY = -1e9; minX = 1e9; maxX = -1e9; - for (var nodeId in this.nodes) { - if (this.nodes.hasOwnProperty(nodeId)) { - node = this.nodes[nodeId]; - node.resize(ctx); - if (minX > node.x - 0.5 * node.width) {minX = node.x - 0.5 * node.width;} - if (maxX < node.x + 0.5 * node.width) {maxX = node.x + 0.5 * node.width;} - if (minY > node.y - 0.5 * node.height) {minY = node.y - 0.5 * node.height;} - if (maxY < node.y + 0.5 * node.height) {maxY = node.y + 0.5 * node.height;} - } - } - node = this.sectors[sectorType][sector]["drawingNode"]; - node.x = 0.5 * (maxX + minX); - node.y = 0.5 * (maxY + minY); - node.width = 2 * (node.x - minX); - node.height = 2 * (node.y - minY); - node.radius = Math.sqrt(Math.pow(0.5*node.width,2) + Math.pow(0.5*node.height,2)); - node.setScale(this.scale); - node._drawCircle(ctx); - } - } + if (this.boundFunction) { + this.off('select', this.boundFunction); } - }; - exports._drawAllSectorNodes = function(ctx) { - this._drawSectorNodes(ctx,"frozen"); - this._drawSectorNodes(ctx,"active"); - this._loadLatestSector(); - }; + this._unselectAll(); + this.forceAppendSelection = false; + this.blockConnectingEdgeSelection = true; + this.manipulationDiv.innerHTML = "" + + "" + + "" + this.constants.labels['back'] + " " + + "
" + + "" + + "" + this.constants.labels['linkDescription'] + ""; -/***/ }, -/* 57 */ -/***/ function(module, exports, __webpack_require__) { + // bind the icon + var backButton = document.getElementById("network-manipulate-back"); + backButton.onclick = this._createManipulatorBar.bind(this); - var Node = __webpack_require__(47); + // we use the boundFunction so we can reference it when we unbind it from the "select" event. + this.boundFunction = this._handleConnect.bind(this); + this.on('select', this.boundFunction); - /** - * This function can be called from the _doInAllSectors function - * - * @param object - * @param overlappingNodes - * @private - */ - exports._getNodesOverlappingWith = function(object, overlappingNodes) { - var nodes = this.nodes; - for (var nodeId in nodes) { - if (nodes.hasOwnProperty(nodeId)) { - if (nodes[nodeId].isOverlappingWith(object)) { - overlappingNodes.push(nodeId); - } - } - } - }; + // temporarily overload functions + this.cachedFunctions["_handleTouch"] = this._handleTouch; + this.cachedFunctions["_handleOnRelease"] = this._handleOnRelease; + this._handleTouch = this._handleConnect; + this._handleOnRelease = this._finishConnect; - /** - * retrieve all nodes overlapping with given object - * @param {Object} object An object with parameters left, top, right, bottom - * @return {Number[]} An array with id's of the overlapping nodes - * @private - */ - exports._getAllNodesOverlappingWith = function (object) { - var overlappingNodes = []; - this._doInAllActiveSectors("_getNodesOverlappingWith",object,overlappingNodes); - return overlappingNodes; + // redraw to show the unselect + this._redraw(); }; - /** - * Return a position object in canvasspace from a single point in screenspace + * create the toolbar to edit edges * - * @param pointer - * @returns {{left: number, top: number, right: number, bottom: number}} * @private */ - exports._pointerToPositionObject = function(pointer) { - var x = this._XconvertDOMtoCanvas(pointer.x); - var y = this._YconvertDOMtoCanvas(pointer.y); + exports._createEditEdgeToolbar = function() { + // clear the toolbar + this._clearManipulatorBar(); + this.controlNodesActive = true; - return { - left: x, - top: y, - right: x, - bottom: y - }; - }; + if (this.boundFunction) { + this.off('select', this.boundFunction); + } + this.edgeBeingEdited = this._getSelectedEdge(); + this.edgeBeingEdited._enableControlNodes(); - /** - * Get the top node at the a specific point (like a click) - * - * @param {{x: Number, y: Number}} pointer - * @return {Node | null} node - * @private - */ - exports._getNodeAt = function (pointer) { - // we first check if this is an navigation controls element - var positionObject = this._pointerToPositionObject(pointer); - var overlappingNodes = this._getAllNodesOverlappingWith(positionObject); + this.manipulationDiv.innerHTML = "" + + "" + + "" + this.constants.labels['back'] + " " + + "
" + + "" + + "" + this.constants.labels['editEdgeDescription'] + ""; - // if there are overlapping nodes, select the last one, this is the - // one which is drawn on top of the others - if (overlappingNodes.length > 0) { - return this.nodes[overlappingNodes[overlappingNodes.length - 1]]; - } - else { - return null; - } - }; + // bind the icon + var backButton = document.getElementById("network-manipulate-back"); + backButton.onclick = this._createManipulatorBar.bind(this); + // temporarily overload functions + this.cachedFunctions["_handleTouch"] = this._handleTouch; + this.cachedFunctions["_handleOnRelease"] = this._handleOnRelease; + this.cachedFunctions["_handleTap"] = this._handleTap; + this.cachedFunctions["_handleDragStart"] = this._handleDragStart; + this.cachedFunctions["_handleOnDrag"] = this._handleOnDrag; + this._handleTouch = this._selectControlNode; + this._handleTap = function () {}; + this._handleOnDrag = this._controlNodeDrag; + this._handleDragStart = function () {} + this._handleOnRelease = this._releaseControlNode; - /** - * retrieve all edges overlapping with given object, selector is around center - * @param {Object} object An object with parameters left, top, right, bottom - * @return {Number[]} An array with id's of the overlapping nodes - * @private - */ - exports._getEdgesOverlappingWith = function (object, overlappingEdges) { - var edges = this.edges; - for (var edgeId in edges) { - if (edges.hasOwnProperty(edgeId)) { - if (edges[edgeId].isOverlappingWith(object)) { - overlappingEdges.push(edgeId); - } - } - } + // redraw to show the unselect + this._redraw(); }; + + + /** - * retrieve all nodes overlapping with given object - * @param {Object} object An object with parameters left, top, right, bottom - * @return {Number[]} An array with id's of the overlapping nodes + * the function bound to the selection event. It checks if you want to connect a cluster and changes the description + * to walk the user through the process. + * * @private */ - exports._getAllEdgesOverlappingWith = function (object) { - var overlappingEdges = []; - this._doInAllActiveSectors("_getEdgesOverlappingWith",object,overlappingEdges); - return overlappingEdges; + exports._selectControlNode = function(pointer) { + this.edgeBeingEdited.controlNodes.from.unselect(); + this.edgeBeingEdited.controlNodes.to.unselect(); + this.selectedControlNode = this.edgeBeingEdited._getSelectedControlNode(this._XconvertDOMtoCanvas(pointer.x),this._YconvertDOMtoCanvas(pointer.y)); + if (this.selectedControlNode !== null) { + this.selectedControlNode.select(); + this.freezeSimulation = true; + } + this._redraw(); }; /** - * Place holder. To implement change the _getNodeAt to a _getObjectAt. Have the _getObjectAt call - * _getNodeAt and _getEdgesAt, then priortize the selection to user preferences. + * the function bound to the selection event. It checks if you want to connect a cluster and changes the description + * to walk the user through the process. * - * @param pointer - * @returns {null} * @private */ - exports._getEdgeAt = function(pointer) { - var positionObject = this._pointerToPositionObject(pointer); - var overlappingEdges = this._getAllEdgesOverlappingWith(positionObject); + exports._controlNodeDrag = function(event) { + var pointer = this._getPointer(event.gesture.center); + if (this.selectedControlNode !== null && this.selectedControlNode !== undefined) { + this.selectedControlNode.x = this._XconvertDOMtoCanvas(pointer.x); + this.selectedControlNode.y = this._YconvertDOMtoCanvas(pointer.y); + } + this._redraw(); + }; - if (overlappingEdges.length > 0) { - return this.edges[overlappingEdges[overlappingEdges.length - 1]]; + exports._releaseControlNode = function(pointer) { + var newNode = this._getNodeAt(pointer); + if (newNode != null) { + if (this.edgeBeingEdited.controlNodes.from.selected == true) { + this._editEdge(newNode.id, this.edgeBeingEdited.to.id); + this.edgeBeingEdited.controlNodes.from.unselect(); + } + if (this.edgeBeingEdited.controlNodes.to.selected == true) { + this._editEdge(this.edgeBeingEdited.from.id, newNode.id); + this.edgeBeingEdited.controlNodes.to.unselect(); + } } else { - return null; + this.edgeBeingEdited._restoreControlNodes(); } + this.freezeSimulation = false; + this._redraw(); }; - /** - * Add object to the selection array. + * the function bound to the selection event. It checks if you want to connect a cluster and changes the description + * to walk the user through the process. * - * @param obj * @private */ - exports._addToSelection = function(obj) { - if (obj instanceof Node) { - this.selectionObj.nodes[obj.id] = obj; + exports._handleConnect = function(pointer) { + if (this._getSelectedNodeCount() == 0) { + var node = this._getNodeAt(pointer); + if (node != null) { + if (node.clusterSize > 1) { + alert("Cannot create edges to a cluster.") + } + else { + this._selectObject(node,false); + // create a node the temporary line can look at + this.sectors['support']['nodes']['targetNode'] = new Node({id:'targetNode'},{},{},this.constants); + this.sectors['support']['nodes']['targetNode'].x = node.x; + this.sectors['support']['nodes']['targetNode'].y = node.y; + this.sectors['support']['nodes']['targetViaNode'] = new Node({id:'targetViaNode'},{},{},this.constants); + this.sectors['support']['nodes']['targetViaNode'].x = node.x; + this.sectors['support']['nodes']['targetViaNode'].y = node.y; + this.sectors['support']['nodes']['targetViaNode'].parentEdgeId = "connectionEdge"; + + // create a temporary edge + this.edges['connectionEdge'] = new Edge({id:"connectionEdge",from:node.id,to:this.sectors['support']['nodes']['targetNode'].id}, this, this.constants); + this.edges['connectionEdge'].from = node; + this.edges['connectionEdge'].connected = true; + this.edges['connectionEdge'].smooth = true; + this.edges['connectionEdge'].selected = true; + this.edges['connectionEdge'].to = this.sectors['support']['nodes']['targetNode']; + this.edges['connectionEdge'].via = this.sectors['support']['nodes']['targetViaNode']; + + this.cachedFunctions["_handleOnDrag"] = this._handleOnDrag; + this._handleOnDrag = function(event) { + var pointer = this._getPointer(event.gesture.center); + this.sectors['support']['nodes']['targetNode'].x = this._XconvertDOMtoCanvas(pointer.x); + this.sectors['support']['nodes']['targetNode'].y = this._YconvertDOMtoCanvas(pointer.y); + this.sectors['support']['nodes']['targetViaNode'].x = 0.5 * (this._XconvertDOMtoCanvas(pointer.x) + this.edges['connectionEdge'].from.x); + this.sectors['support']['nodes']['targetViaNode'].y = this._YconvertDOMtoCanvas(pointer.y); + }; + + this.moving = true; + this.start(); + } + } } - else { - this.selectionObj.edges[obj.id] = obj; + }; + + exports._finishConnect = function(pointer) { + if (this._getSelectedNodeCount() == 1) { + + // restore the drag function + this._handleOnDrag = this.cachedFunctions["_handleOnDrag"]; + delete this.cachedFunctions["_handleOnDrag"]; + + // remember the edge id + var connectFromId = this.edges['connectionEdge'].fromId; + + // remove the temporary nodes and edge + delete this.edges['connectionEdge']; + delete this.sectors['support']['nodes']['targetNode']; + delete this.sectors['support']['nodes']['targetViaNode']; + + var node = this._getNodeAt(pointer); + if (node != null) { + if (node.clusterSize > 1) { + alert("Cannot create edges to a cluster.") + } + else { + this._createEdge(connectFromId,node.id); + this._createManipulatorBar(); + } + } + this._unselectAll(); } }; + /** - * Add object to the selection array. - * - * @param obj - * @private + * Adds a node on the specified location */ - exports._addToHover = function(obj) { - if (obj instanceof Node) { - this.hoverObj.nodes[obj.id] = obj; - } - else { - this.hoverObj.edges[obj.id] = obj; + exports._addNode = function() { + if (this._selectionIsEmpty() && this.editMode == true) { + var positionObject = this._pointerToPositionObject(this.pointerPosition); + var defaultData = {id:util.randomUUID(),x:positionObject.left,y:positionObject.top,label:"new",allowedToMoveX:true,allowedToMoveY:true}; + if (this.triggerFunctions.add) { + if (this.triggerFunctions.add.length == 2) { + var me = this; + this.triggerFunctions.add(defaultData, function(finalizedData) { + me.nodesData.add(finalizedData); + me._createManipulatorBar(); + me.moving = true; + me.start(); + }); + } + else { + alert(this.constants.labels['addError']); + this._createManipulatorBar(); + this.moving = true; + this.start(); + } + } + else { + this.nodesData.add(defaultData); + this._createManipulatorBar(); + this.moving = true; + this.start(); + } } }; /** - * Remove a single option from selection. + * connect two nodes with a new edge. * - * @param {Object} obj * @private */ - exports._removeFromSelection = function(obj) { - if (obj instanceof Node) { - delete this.selectionObj.nodes[obj.id]; - } - else { - delete this.selectionObj.edges[obj.id]; + exports._createEdge = function(sourceNodeId,targetNodeId) { + if (this.editMode == true) { + var defaultData = {from:sourceNodeId, to:targetNodeId}; + if (this.triggerFunctions.connect) { + if (this.triggerFunctions.connect.length == 2) { + var me = this; + this.triggerFunctions.connect(defaultData, function(finalizedData) { + me.edgesData.add(finalizedData); + me.moving = true; + me.start(); + }); + } + else { + alert(this.constants.labels["linkError"]); + this.moving = true; + this.start(); + } + } + else { + this.edgesData.add(defaultData); + this.moving = true; + this.start(); + } } }; /** - * Unselect all. The selectionObj is useful for this. + * connect two nodes with a new edge. * - * @param {Boolean} [doNotTrigger] | ignore trigger * @private */ - exports._unselectAll = function(doNotTrigger) { - if (doNotTrigger === undefined) { - doNotTrigger = false; - } - for(var nodeId in this.selectionObj.nodes) { - if(this.selectionObj.nodes.hasOwnProperty(nodeId)) { - this.selectionObj.nodes[nodeId].unselect(); + exports._editEdge = function(sourceNodeId,targetNodeId) { + if (this.editMode == true) { + var defaultData = {id: this.edgeBeingEdited.id, from:sourceNodeId, to:targetNodeId}; + if (this.triggerFunctions.editEdge) { + if (this.triggerFunctions.editEdge.length == 2) { + var me = this; + this.triggerFunctions.editEdge(defaultData, function(finalizedData) { + me.edgesData.update(finalizedData); + me.moving = true; + me.start(); + }); + } + else { + alert(this.constants.labels["linkError"]); + this.moving = true; + this.start(); + } } - } - for(var edgeId in this.selectionObj.edges) { - if(this.selectionObj.edges.hasOwnProperty(edgeId)) { - this.selectionObj.edges[edgeId].unselect(); + else { + this.edgesData.update(defaultData); + this.moving = true; + this.start(); } } - - this.selectionObj = {nodes:{},edges:{}}; - - if (doNotTrigger == false) { - this.emit('select', this.getSelection()); - } }; /** - * Unselect all clusters. The selectionObj is useful for this. + * Create the toolbar to edit the selected node. The label and the color can be changed. Other colors are derived from the chosen color. * - * @param {Boolean} [doNotTrigger] | ignore trigger * @private */ - exports._unselectClusters = function(doNotTrigger) { - if (doNotTrigger === undefined) { - doNotTrigger = false; - } - - for (var nodeId in this.selectionObj.nodes) { - if (this.selectionObj.nodes.hasOwnProperty(nodeId)) { - if (this.selectionObj.nodes[nodeId].clusterSize > 1) { - this.selectionObj.nodes[nodeId].unselect(); - this._removeFromSelection(this.selectionObj.nodes[nodeId]); - } + exports._editNode = function() { + if (this.triggerFunctions.edit && this.editMode == true) { + var node = this._getSelectedNode(); + var data = {id:node.id, + label: node.label, + group: node.options.group, + shape: node.options.shape, + color: { + background:node.options.color.background, + border:node.options.color.border, + highlight: { + background:node.options.color.highlight.background, + border:node.options.color.highlight.border + } + }}; + if (this.triggerFunctions.edit.length == 2) { + var me = this; + this.triggerFunctions.edit(data, function (finalizedData) { + me.nodesData.update(finalizedData); + me._createManipulatorBar(); + me.moving = true; + me.start(); + }); + } + else { + alert(this.constants.labels["editError"]); } } - - if (doNotTrigger == false) { - this.emit('select', this.getSelection()); - } + else { + alert(this.constants.labels["editBoundError"]); + } }; + + /** - * return the number of selected nodes + * delete everything in the selection * - * @returns {number} * @private */ - exports._getSelectedNodeCount = function() { - var count = 0; - for (var nodeId in this.selectionObj.nodes) { - if (this.selectionObj.nodes.hasOwnProperty(nodeId)) { - count += 1; + exports._deleteSelected = function() { + if (!this._selectionIsEmpty() && this.editMode == true) { + if (!this._clusterInSelection()) { + var selectedNodes = this.getSelectedNodes(); + var selectedEdges = this.getSelectedEdges(); + if (this.triggerFunctions.del) { + var me = this; + var data = {nodes: selectedNodes, edges: selectedEdges}; + if (this.triggerFunctions.del.length = 2) { + this.triggerFunctions.del(data, function (finalizedData) { + me.edgesData.remove(finalizedData.edges); + me.nodesData.remove(finalizedData.nodes); + me._unselectAll(); + me.moving = true; + me.start(); + }); + } + else { + alert(this.constants.labels["deleteError"]) + } + } + else { + this.edgesData.remove(selectedEdges); + this.nodesData.remove(selectedNodes); + this._unselectAll(); + this.moving = true; + this.start(); + } + } + else { + alert(this.constants.labels["deleteClusterError"]); } } - return count; }; - /** - * return the selected node - * - * @returns {number} - * @private - */ - exports._getSelectedNode = function() { - for (var nodeId in this.selectionObj.nodes) { - if (this.selectionObj.nodes.hasOwnProperty(nodeId)) { - return this.selectionObj.nodes[nodeId]; - } + +/***/ }, +/* 54 */ +/***/ function(module, exports, __webpack_require__) { + + var util = __webpack_require__(1); + var Hammer = __webpack_require__(41); + + exports._cleanNavigation = function() { + // clean up previous navigation items + var wrapper = document.getElementById('network-navigation_wrapper'); + if (wrapper != null) { + this.containerElement.removeChild(wrapper); } - return null; + document.onmouseup = null; }; /** - * return the selected edge + * Creation of the navigation controls nodes. They are drawn over the rest of the nodes and are not affected by scale and translation + * they have a triggerFunction which is called on click. If the position of the navigation controls is dependent + * on this.frame.canvas.clientWidth or this.frame.canvas.clientHeight, we flag horizontalAlignLeft and verticalAlignTop false. + * This means that the location will be corrected by the _relocateNavigation function on a size change of the canvas. * - * @returns {number} * @private */ - exports._getSelectedEdge = function() { - for (var edgeId in this.selectionObj.edges) { - if (this.selectionObj.edges.hasOwnProperty(edgeId)) { - return this.selectionObj.edges[edgeId]; - } - } - return null; - }; + exports._loadNavigationElements = function() { + this._cleanNavigation(); + this.navigationDivs = {}; + var navigationDivs = ['up','down','left','right','zoomIn','zoomOut','zoomExtends']; + var navigationDivActions = ['_moveUp','_moveDown','_moveLeft','_moveRight','_zoomIn','_zoomOut','zoomExtent']; - /** - * return the number of selected edges - * - * @returns {number} - * @private - */ - exports._getSelectedEdgeCount = function() { - var count = 0; - for (var edgeId in this.selectionObj.edges) { - if (this.selectionObj.edges.hasOwnProperty(edgeId)) { - count += 1; - } + this.navigationDivs['wrapper'] = document.createElement('div'); + this.navigationDivs['wrapper'].id = "network-navigation_wrapper"; + this.navigationDivs['wrapper'].style.position = "absolute"; + this.navigationDivs['wrapper'].style.width = this.frame.canvas.clientWidth + "px"; + this.navigationDivs['wrapper'].style.height = this.frame.canvas.clientHeight + "px"; + this.containerElement.insertBefore(this.navigationDivs['wrapper'],this.frame); + + var me = this; + for (var i = 0; i < navigationDivs.length; i++) { + this.navigationDivs[navigationDivs[i]] = document.createElement('div'); + this.navigationDivs[navigationDivs[i]].id = "network-navigation_" + navigationDivs[i]; + this.navigationDivs[navigationDivs[i]].className = "network-navigation " + navigationDivs[i]; + this.navigationDivs['wrapper'].appendChild(this.navigationDivs[navigationDivs[i]]); + var hammer = Hammer(this.navigationDivs[navigationDivs[i]], {prevent_default: true}); + hammer.on("touch", me[navigationDivActions[i]].bind(me)); } - return count; + var hammer = Hammer(document, {prevent_default: false}); + hammer.on("release", me._stopMovement.bind(me)); }; - /** - * return the number of selected objects. + * this stops all movement induced by the navigation buttons * - * @returns {number} * @private */ - exports._getSelectedObjectCount = function() { - var count = 0; - for(var nodeId in this.selectionObj.nodes) { - if(this.selectionObj.nodes.hasOwnProperty(nodeId)) { - count += 1; - } - } - for(var edgeId in this.selectionObj.edges) { - if(this.selectionObj.edges.hasOwnProperty(edgeId)) { - count += 1; - } - } - return count; + exports._stopMovement = function() { + this._xStopMoving(); + this._yStopMoving(); + this._stopZoom(); }; + /** - * Check if anything is selected + * move the screen up + * By using the increments, instead of adding a fixed number to the translation, we keep fluent and + * instant movement. The onKeypress event triggers immediately, then pauses, then triggers frequently + * To avoid this behaviour, we do the translation in the start loop. * - * @returns {boolean} * @private */ - exports._selectionIsEmpty = function() { - for(var nodeId in this.selectionObj.nodes) { - if(this.selectionObj.nodes.hasOwnProperty(nodeId)) { - return false; - } - } - for(var edgeId in this.selectionObj.edges) { - if(this.selectionObj.edges.hasOwnProperty(edgeId)) { - return false; - } - } - return true; + exports._moveUp = function(event) { + this.yIncrement = this.constants.keyboard.speed.y; + this.start(); // if there is no node movement, the calculation wont be done }; /** - * check if one of the selected nodes is a cluster. - * - * @returns {boolean} + * move the screen down * @private */ - exports._clusterInSelection = function() { - for(var nodeId in this.selectionObj.nodes) { - if(this.selectionObj.nodes.hasOwnProperty(nodeId)) { - if (this.selectionObj.nodes[nodeId].clusterSize > 1) { - return true; - } - } - } - return false; + exports._moveDown = function(event) { + this.yIncrement = -this.constants.keyboard.speed.y; + this.start(); // if there is no node movement, the calculation wont be done }; + /** - * select the edges connected to the node that is being selected - * - * @param {Node} node + * move the screen left * @private */ - exports._selectConnectedEdges = function(node) { - for (var i = 0; i < node.dynamicEdges.length; i++) { - var edge = node.dynamicEdges[i]; - edge.select(); - this._addToSelection(edge); - } + exports._moveLeft = function(event) { + this.xIncrement = this.constants.keyboard.speed.x; + this.start(); // if there is no node movement, the calculation wont be done }; + /** - * select the edges connected to the node that is being selected - * - * @param {Node} node + * move the screen right * @private */ - exports._hoverConnectedEdges = function(node) { - for (var i = 0; i < node.dynamicEdges.length; i++) { - var edge = node.dynamicEdges[i]; - edge.hover = true; - this._addToHover(edge); - } + exports._moveRight = function(event) { + this.xIncrement = -this.constants.keyboard.speed.y; + this.start(); // if there is no node movement, the calculation wont be done }; /** - * unselect the edges connected to the node that is being selected - * - * @param {Node} node + * Zoom in, using the same method as the movement. * @private */ - exports._unselectConnectedEdges = function(node) { - for (var i = 0; i < node.dynamicEdges.length; i++) { - var edge = node.dynamicEdges[i]; - edge.unselect(); - this._removeFromSelection(edge); - } + exports._zoomIn = function(event) { + this.zoomIncrement = this.constants.keyboard.speed.zoom; + this.start(); // if there is no node movement, the calculation wont be done }; - - /** - * This is called when someone clicks on a node. either select or deselect it. - * If there is an existing selection and we don't want to append to it, clear the existing selection - * - * @param {Node || Edge} object - * @param {Boolean} append - * @param {Boolean} [doNotTrigger] | ignore trigger + * Zoom out * @private */ - exports._selectObject = function(object, append, doNotTrigger, highlightEdges) { - if (doNotTrigger === undefined) { - doNotTrigger = false; - } - if (highlightEdges === undefined) { - highlightEdges = true; - } - - if (this._selectionIsEmpty() == false && append == false && this.forceAppendSelection == false) { - this._unselectAll(true); - } - - if (object.selected == false) { - object.select(); - this._addToSelection(object); - if (object instanceof Node && this.blockConnectingEdgeSelection == false && highlightEdges == true) { - this._selectConnectedEdges(object); - } - } - else { - object.unselect(); - this._removeFromSelection(object); - } - - if (doNotTrigger == false) { - this.emit('select', this.getSelection()); - } + exports._zoomOut = function() { + this.zoomIncrement = -this.constants.keyboard.speed.zoom; + this.start(); // if there is no node movement, the calculation wont be done + util.preventDefault(event); }; /** - * This is called when someone clicks on a node. either select or deselect it. - * If there is an existing selection and we don't want to append to it, clear the existing selection - * - * @param {Node || Edge} object + * Stop zooming and unhighlight the zoom controls * @private */ - exports._blurObject = function(object) { - if (object.hover == true) { - object.hover = false; - this.emit("blurNode",{node:object.id}); - } + exports._stopZoom = function() { + this.zoomIncrement = 0; }; + /** - * This is called when someone clicks on a node. either select or deselect it. - * If there is an existing selection and we don't want to append to it, clear the existing selection - * - * @param {Node || Edge} object + * Stop moving in the Y direction and unHighlight the up and down * @private */ - exports._hoverObject = function(object) { - if (object.hover == false) { - object.hover = true; - this._addToHover(object); - if (object instanceof Node) { - this.emit("hoverNode",{node:object.id}); - } - } - if (object instanceof Node) { - this._hoverConnectedEdges(object); - } + exports._yStopMoving = function() { + this.yIncrement = 0; }; /** - * handles the selection part of the touch, only for navigation controls elements; - * Touch is triggered before tap, also before hold. Hold triggers after a while. - * This is the most responsive solution - * - * @param {Object} pointer + * Stop moving in the X direction and unHighlight left and right. * @private */ - exports._handleTouch = function(pointer) { + exports._xStopMoving = function() { + this.xIncrement = 0; }; +/***/ }, +/* 55 */ +/***/ function(module, exports, __webpack_require__) { + + exports._resetLevels = function() { + for (var nodeId in this.nodes) { + if (this.nodes.hasOwnProperty(nodeId)) { + var node = this.nodes[nodeId]; + if (node.preassignedLevel == false) { + node.level = -1; + } + } + } + }; + /** - * handles the selection part of the tap; + * This is the main function to layout the nodes in a hierarchical way. + * It checks if the node details are supplied correctly * - * @param {Object} pointer * @private */ - exports._handleTap = function(pointer) { - var node = this._getNodeAt(pointer); - if (node != null) { - this._selectObject(node,false); - } - else { - var edge = this._getEdgeAt(pointer); - if (edge != null) { - this._selectObject(edge,false); + exports._setupHierarchicalLayout = function() { + if (this.constants.hierarchicalLayout.enabled == true && this.nodeIndices.length > 0) { + if (this.constants.hierarchicalLayout.direction == "RL" || this.constants.hierarchicalLayout.direction == "DU") { + this.constants.hierarchicalLayout.levelSeparation *= -1; } else { - this._unselectAll(); + this.constants.hierarchicalLayout.levelSeparation = Math.abs(this.constants.hierarchicalLayout.levelSeparation); + } + + if (this.constants.hierarchicalLayout.direction == "RL" || this.constants.hierarchicalLayout.direction == "LR") { + if (this.constants.smoothCurves.enabled == true) { + this.constants.smoothCurves.type = "vertical"; + } + } + else { + if (this.constants.smoothCurves.enabled == true) { + this.constants.smoothCurves.type = "horizontal"; + } + } + // get the size of the largest hubs and check if the user has defined a level for a node. + var hubsize = 0; + var node, nodeId; + var definedLevel = false; + var undefinedLevel = false; + + for (nodeId in this.nodes) { + if (this.nodes.hasOwnProperty(nodeId)) { + node = this.nodes[nodeId]; + if (node.level != -1) { + definedLevel = true; + } + else { + undefinedLevel = true; + } + if (hubsize < node.edges.length) { + hubsize = node.edges.length; + } + } + } + + // if the user defined some levels but not all, alert and run without hierarchical layout + if (undefinedLevel == true && definedLevel == true) { + alert("To use the hierarchical layout, nodes require either no predefined levels or levels have to be defined for all nodes."); + this.zoomExtent(true,this.constants.clustering.enabled); + if (!this.constants.clustering.enabled) { + this.start(); + } + } + else { + // setup the system to use hierarchical method. + this._changeConstants(); + + // define levels if undefined by the users. Based on hubsize + if (undefinedLevel == true) { + this._determineLevels(hubsize); + } + // check the distribution of the nodes per level. + var distribution = this._getDistribution(); + + // place the nodes on the canvas. This also stablilizes the system. + this._placeNodesByHierarchy(distribution); + + // start the simulation. + this.start(); } } - this.emit("click", this.getSelection()); - this._redraw(); }; /** - * handles the selection part of the double tap and opens a cluster if needed + * This function places the nodes on the canvas based on the hierarchial distribution. * - * @param {Object} pointer + * @param {Object} distribution | obtained by the function this._getDistribution() * @private */ - exports._handleDoubleTap = function(pointer) { - var node = this._getNodeAt(pointer); - if (node != null && node !== undefined) { - // we reset the areaCenter here so the opening of the node will occur - this.areaCenter = {"x" : this._XconvertDOMtoCanvas(pointer.x), - "y" : this._YconvertDOMtoCanvas(pointer.y)}; - this.openCluster(node); + exports._placeNodesByHierarchy = function(distribution) { + var nodeId, node; + + // start placing all the level 0 nodes first. Then recursively position their branches. + for (var level in distribution) { + if (distribution.hasOwnProperty(level)) { + + for (nodeId in distribution[level].nodes) { + if (distribution[level].nodes.hasOwnProperty(nodeId)) { + node = distribution[level].nodes[nodeId]; + if (this.constants.hierarchicalLayout.direction == "UD" || this.constants.hierarchicalLayout.direction == "DU") { + if (node.xFixed) { + node.x = distribution[level].minPos; + node.xFixed = false; + + distribution[level].minPos += distribution[level].nodeSpacing; + } + } + else { + if (node.yFixed) { + node.y = distribution[level].minPos; + node.yFixed = false; + + distribution[level].minPos += distribution[level].nodeSpacing; + } + } + this._placeBranchNodes(node.edges,node.id,distribution,node.level); + } + } + } } - this.emit("doubleClick", this.getSelection()); + + // stabilize the system after positioning. This function calls zoomExtent. + this._stabilize(); }; /** - * Handle the onHold selection part + * This function get the distribution of levels based on hubsize * - * @param pointer + * @returns {Object} * @private */ - exports._handleOnHold = function(pointer) { - var node = this._getNodeAt(pointer); - if (node != null) { - this._selectObject(node,true); + exports._getDistribution = function() { + var distribution = {}; + var nodeId, node, level; + + // we fix Y because the hierarchy is vertical, we fix X so we do not give a node an x position for a second time. + // the fix of X is removed after the x value has been set. + for (nodeId in this.nodes) { + if (this.nodes.hasOwnProperty(nodeId)) { + node = this.nodes[nodeId]; + node.xFixed = true; + node.yFixed = true; + if (this.constants.hierarchicalLayout.direction == "UD" || this.constants.hierarchicalLayout.direction == "DU") { + node.y = this.constants.hierarchicalLayout.levelSeparation*node.level; + } + else { + node.x = this.constants.hierarchicalLayout.levelSeparation*node.level; + } + if (distribution[node.level] === undefined) { + distribution[node.level] = {amount: 0, nodes: {}, minPos:0, nodeSpacing:0}; + } + distribution[node.level].amount += 1; + distribution[node.level].nodes[nodeId] = node; + } } - else { - var edge = this._getEdgeAt(pointer); - if (edge != null) { - this._selectObject(edge,true); + + // determine the largest amount of nodes of all levels + var maxCount = 0; + for (level in distribution) { + if (distribution.hasOwnProperty(level)) { + if (maxCount < distribution[level].amount) { + maxCount = distribution[level].amount; + } + } + } + + // set the initial position and spacing of each nodes accordingly + for (level in distribution) { + if (distribution.hasOwnProperty(level)) { + distribution[level].nodeSpacing = (maxCount + 1) * this.constants.hierarchicalLayout.nodeSpacing; + distribution[level].nodeSpacing /= (distribution[level].amount + 1); + distribution[level].minPos = distribution[level].nodeSpacing - (0.5 * (distribution[level].amount + 1) * distribution[level].nodeSpacing); + } + } + + return distribution; + }; + + + /** + * this function allocates nodes in levels based on the recursive branching from the largest hubs. + * + * @param hubsize + * @private + */ + exports._determineLevels = function(hubsize) { + var nodeId, node; + + // determine hubs + for (nodeId in this.nodes) { + if (this.nodes.hasOwnProperty(nodeId)) { + node = this.nodes[nodeId]; + if (node.edges.length == hubsize) { + node.level = 0; + } + } + } + + // branch from hubs + for (nodeId in this.nodes) { + if (this.nodes.hasOwnProperty(nodeId)) { + node = this.nodes[nodeId]; + if (node.level == 0) { + this._setLevel(1,node.edges,node.id); + } } } - this._redraw(); }; /** - * handle the onRelease event. These functions are here for the navigation controls module. + * Since hierarchical layout does not support: + * - smooth curves (based on the physics), + * - clustering (based on dynamic node counts) * - * @private + * We disable both features so there will be no problems. + * + * @private */ - exports._handleOnRelease = function(pointer) { - + exports._changeConstants = function() { + this.constants.clustering.enabled = false; + this.constants.physics.barnesHut.enabled = false; + this.constants.physics.hierarchicalRepulsion.enabled = true; + this._loadSelectedForceSolver(); + if (this.constants.smoothCurves.enabled == true) { + this.constants.smoothCurves.dynamic = false; + } + this._configureSmoothCurves(); }; - /** + * This is a recursively called function to enumerate the branches from the largest hubs and place the nodes + * on a X position that ensures there will be no overlap. * - * retrieve the currently selected objects - * @return {{nodes: Array., edges: Array.}} selection + * @param edges + * @param parentId + * @param distribution + * @param parentLevel + * @private */ - exports.getSelection = function() { - var nodeIds = this.getSelectedNodes(); - var edgeIds = this.getSelectedEdges(); - return {nodes:nodeIds, edges:edgeIds}; - }; + exports._placeBranchNodes = function(edges, parentId, distribution, parentLevel) { + for (var i = 0; i < edges.length; i++) { + var childNode = null; + if (edges[i].toId == parentId) { + childNode = edges[i].from; + } + else { + childNode = edges[i].to; + } - /** - * - * retrieve the currently selected nodes - * @return {String[]} selection An array with the ids of the - * selected nodes. - */ - exports.getSelectedNodes = function() { - var idArray = []; - for(var nodeId in this.selectionObj.nodes) { - if(this.selectionObj.nodes.hasOwnProperty(nodeId)) { - idArray.push(nodeId); + // if a node is conneceted to another node on the same level (or higher (means lower level))!, this is not handled here. + var nodeMoved = false; + if (this.constants.hierarchicalLayout.direction == "UD" || this.constants.hierarchicalLayout.direction == "DU") { + if (childNode.xFixed && childNode.level > parentLevel) { + childNode.xFixed = false; + childNode.x = distribution[childNode.level].minPos; + nodeMoved = true; + } + } + else { + if (childNode.yFixed && childNode.level > parentLevel) { + childNode.yFixed = false; + childNode.y = distribution[childNode.level].minPos; + nodeMoved = true; + } + } + + if (nodeMoved == true) { + distribution[childNode.level].minPos += distribution[childNode.level].nodeSpacing; + if (childNode.edges.length > 1) { + this._placeBranchNodes(childNode.edges,childNode.id,distribution,childNode.level); + } } } - return idArray }; + /** + * this function is called recursively to enumerate the barnches of the largest hubs and give each node a level. * - * retrieve the currently selected edges - * @return {Array} selection An array with the ids of the - * selected nodes. + * @param level + * @param edges + * @param parentId + * @private */ - exports.getSelectedEdges = function() { - var idArray = []; - for(var edgeId in this.selectionObj.edges) { - if(this.selectionObj.edges.hasOwnProperty(edgeId)) { - idArray.push(edgeId); + exports._setLevel = function(level, edges, parentId) { + for (var i = 0; i < edges.length; i++) { + var childNode = null; + if (edges[i].toId == parentId) { + childNode = edges[i].from; + } + else { + childNode = edges[i].to; + } + if (childNode.level == -1 || childNode.level > level) { + childNode.level = level; + if (edges.length > 1) { + this._setLevel(level+1, childNode.edges, childNode.id); + } } } - return idArray; }; /** - * select zero or more nodes - * @param {Number[] | String[]} selection An array with the ids of the - * selected nodes. + * Unfix nodes + * + * @private */ - exports.setSelection = function(selection) { - var i, iMax, id; - - if (!selection || (selection.length == undefined)) - throw 'Selection must be an array with ids'; - - // first unselect any selected node - this._unselectAll(true); - - for (i = 0, iMax = selection.length; i < iMax; i++) { - id = selection[i]; - - var node = this.nodes[id]; - if (!node) { - throw new RangeError('Node with id "' + id + '" not found'); + exports._restoreNodes = function() { + for (var nodeId in this.nodes) { + if (this.nodes.hasOwnProperty(nodeId)) { + this.nodes[nodeId].xFixed = false; + this.nodes[nodeId].yFixed = false; } - this._selectObject(node,true,true); } + }; - console.log("setSelection is deprecated. Please use selectNodes instead.") - this.redraw(); - }; +/***/ }, +/* 56 */ +/***/ function(module, exports, __webpack_require__) { + var util = __webpack_require__(1); + var RepulsionMixin = __webpack_require__(58); + var HierarchialRepulsionMixin = __webpack_require__(59); + var BarnesHutMixin = __webpack_require__(60); /** - * select zero or more nodes with the option to highlight edges - * @param {Number[] | String[]} selection An array with the ids of the - * selected nodes. - * @param {boolean} [highlightEdges] + * Toggling barnes Hut calculation on and off. + * + * @private */ - exports.selectNodes = function(selection, highlightEdges) { - var i, iMax, id; - - if (!selection || (selection.length == undefined)) - throw 'Selection must be an array with ids'; - - // first unselect any selected node - this._unselectAll(true); - - for (i = 0, iMax = selection.length; i < iMax; i++) { - id = selection[i]; - - var node = this.nodes[id]; - if (!node) { - throw new RangeError('Node with id "' + id + '" not found'); - } - this._selectObject(node,true,true,highlightEdges); - } - this.redraw(); + exports._toggleBarnesHut = function () { + this.constants.physics.barnesHut.enabled = !this.constants.physics.barnesHut.enabled; + this._loadSelectedForceSolver(); + this.moving = true; + this.start(); }; /** - * select zero or more edges - * @param {Number[] | String[]} selection An array with the ids of the - * selected nodes. + * This loads the node force solver based on the barnes hut or repulsion algorithm + * + * @private */ - exports.selectEdges = function(selection) { - var i, iMax, id; - - if (!selection || (selection.length == undefined)) - throw 'Selection must be an array with ids'; - - // first unselect any selected node - this._unselectAll(true); + exports._loadSelectedForceSolver = function () { + // this overloads the this._calculateNodeForces + if (this.constants.physics.barnesHut.enabled == true) { + this._clearMixin(RepulsionMixin); + this._clearMixin(HierarchialRepulsionMixin); - for (i = 0, iMax = selection.length; i < iMax; i++) { - id = selection[i]; + this.constants.physics.centralGravity = this.constants.physics.barnesHut.centralGravity; + this.constants.physics.springLength = this.constants.physics.barnesHut.springLength; + this.constants.physics.springConstant = this.constants.physics.barnesHut.springConstant; + this.constants.physics.damping = this.constants.physics.barnesHut.damping; - var edge = this.edges[id]; - if (!edge) { - throw new RangeError('Edge with id "' + id + '" not found'); - } - this._selectObject(edge,true,true,highlightEdges); + this._loadMixin(BarnesHutMixin); } - this.redraw(); - }; + else if (this.constants.physics.hierarchicalRepulsion.enabled == true) { + this._clearMixin(BarnesHutMixin); + this._clearMixin(RepulsionMixin); - /** - * Validate the selection: remove ids of nodes which no longer exist - * @private - */ - exports._updateSelection = function () { - for(var nodeId in this.selectionObj.nodes) { - if(this.selectionObj.nodes.hasOwnProperty(nodeId)) { - if (!this.nodes.hasOwnProperty(nodeId)) { - delete this.selectionObj.nodes[nodeId]; - } - } - } - for(var edgeId in this.selectionObj.edges) { - if(this.selectionObj.edges.hasOwnProperty(edgeId)) { - if (!this.edges.hasOwnProperty(edgeId)) { - delete this.selectionObj.edges[edgeId]; - } - } - } - }; + this.constants.physics.centralGravity = this.constants.physics.hierarchicalRepulsion.centralGravity; + this.constants.physics.springLength = this.constants.physics.hierarchicalRepulsion.springLength; + this.constants.physics.springConstant = this.constants.physics.hierarchicalRepulsion.springConstant; + this.constants.physics.damping = this.constants.physics.hierarchicalRepulsion.damping; + this._loadMixin(HierarchialRepulsionMixin); + } + else { + this._clearMixin(BarnesHutMixin); + this._clearMixin(HierarchialRepulsionMixin); + this.barnesHutTree = undefined; -/***/ }, -/* 58 */ -/***/ function(module, exports, __webpack_require__) { + this.constants.physics.centralGravity = this.constants.physics.repulsion.centralGravity; + this.constants.physics.springLength = this.constants.physics.repulsion.springLength; + this.constants.physics.springConstant = this.constants.physics.repulsion.springConstant; + this.constants.physics.damping = this.constants.physics.repulsion.damping; - var util = __webpack_require__(1); - var Node = __webpack_require__(47); - var Edge = __webpack_require__(48); + this._loadMixin(RepulsionMixin); + } + }; /** - * clears the toolbar div element of children + * Before calculating the forces, we check if we need to cluster to keep up performance and we check + * if there is more than one node. If it is just one node, we dont calculate anything. * * @private */ - exports._clearManipulatorBar = function() { - while (this.manipulationDiv.hasChildNodes()) { - this.manipulationDiv.removeChild(this.manipulationDiv.firstChild); + exports._initializeForceCalculation = function () { + // stop calculation if there is only one node + if (this.nodeIndices.length == 1) { + this.nodes[this.nodeIndices[0]]._setForce(0, 0); + } + else { + // if there are too many nodes on screen, we cluster without repositioning + if (this.nodeIndices.length > this.constants.clustering.clusterThreshold && this.constants.clustering.enabled == true) { + this.clusterToFit(this.constants.clustering.reduceToNodes, false); + } + + // we now start the force calculation + this._calculateForces(); } }; + /** - * Manipulation UI temporarily overloads certain functions to extend or replace them. To be able to restore - * these functions to their original functionality, we saved them in this.cachedFunctions. - * This function restores these functions to their original function. - * + * Calculate the external forces acting on the nodes + * Forces are caused by: edges, repulsing forces between nodes, gravity * @private */ - exports._restoreOverloadedFunctions = function() { - for (var functionName in this.cachedFunctions) { - if (this.cachedFunctions.hasOwnProperty(functionName)) { - this[functionName] = this.cachedFunctions[functionName]; + exports._calculateForces = function () { + // Gravity is required to keep separated groups from floating off + // the forces are reset to zero in this loop by using _setForce instead + // of _addForce + + this._calculateGravitationalForces(); + this._calculateNodeForces(); + + if (this.constants.physics.springConstant > 0) { + if (this.constants.smoothCurves.enabled == true && this.constants.smoothCurves.dynamic == true) { + this._calculateSpringForcesWithSupport(); + } + else { + if (this.constants.physics.hierarchicalRepulsion.enabled == true) { + this._calculateHierarchicalSpringForces(); + } + else { + this._calculateSpringForces(); + } } } }; + /** - * Enable or disable edit-mode. + * Smooth curves are created by adding invisible nodes in the center of the edges. These nodes are also + * handled in the calculateForces function. We then use a quadratic curve with the center node as control. + * This function joins the datanodes and invisible (called support) nodes into one object. + * We do this so we do not contaminate this.nodes with the support nodes. * * @private */ - exports._toggleEditMode = function() { - this.editMode = !this.editMode; - var toolbar = document.getElementById("network-manipulationDiv"); - var closeDiv = document.getElementById("network-manipulation-closeDiv"); - var editModeDiv = document.getElementById("network-manipulation-editMode"); - if (this.editMode == true) { - toolbar.style.display="block"; - closeDiv.style.display="block"; - editModeDiv.style.display="none"; - closeDiv.onclick = this._toggleEditMode.bind(this); + exports._updateCalculationNodes = function () { + if (this.constants.smoothCurves.enabled == true && this.constants.smoothCurves.dynamic == true) { + this.calculationNodes = {}; + this.calculationNodeIndices = []; + + for (var nodeId in this.nodes) { + if (this.nodes.hasOwnProperty(nodeId)) { + this.calculationNodes[nodeId] = this.nodes[nodeId]; + } + } + var supportNodes = this.sectors['support']['nodes']; + for (var supportNodeId in supportNodes) { + if (supportNodes.hasOwnProperty(supportNodeId)) { + if (this.edges.hasOwnProperty(supportNodes[supportNodeId].parentEdgeId)) { + this.calculationNodes[supportNodeId] = supportNodes[supportNodeId]; + } + else { + supportNodes[supportNodeId]._setForce(0, 0); + } + } + } + + for (var idx in this.calculationNodes) { + if (this.calculationNodes.hasOwnProperty(idx)) { + this.calculationNodeIndices.push(idx); + } + } } else { - toolbar.style.display="none"; - closeDiv.style.display="none"; - editModeDiv.style.display="block"; - closeDiv.onclick = null; + this.calculationNodes = this.nodes; + this.calculationNodeIndices = this.nodeIndices; } - this._createManipulatorBar() }; + /** - * main function, creates the main toolbar. Removes functions bound to the select event. Binds all the buttons of the toolbar. + * this function applies the central gravity effect to keep groups from floating off * * @private */ - exports._createManipulatorBar = function() { - // remove bound functions - if (this.boundFunction) { - this.off('select', this.boundFunction); - } - - if (this.edgeBeingEdited !== undefined) { - this.edgeBeingEdited._disableControlNodes(); - this.edgeBeingEdited = undefined; - this.selectedControlNode = null; - this.controlNodesActive = false; - } - - // restore overloaded functions - this._restoreOverloadedFunctions(); - - // resume calculation - this.freezeSimulation = false; - - // reset global variables - this.blockConnectingEdgeSelection = false; - this.forceAppendSelection = false; - - if (this.editMode == true) { - while (this.manipulationDiv.hasChildNodes()) { - this.manipulationDiv.removeChild(this.manipulationDiv.firstChild); - } - // add the icons to the manipulator div - this.manipulationDiv.innerHTML = "" + - "" + - ""+this.constants.labels['add'] +"" + - "
" + - "" + - ""+this.constants.labels['link'] +""; - if (this._getSelectedNodeCount() == 1 && this.triggerFunctions.edit) { - this.manipulationDiv.innerHTML += "" + - "
" + - "" + - ""+this.constants.labels['editNode'] +""; - } - else if (this._getSelectedEdgeCount() == 1 && this._getSelectedNodeCount() == 0) { - this.manipulationDiv.innerHTML += "" + - "
" + - "" + - ""+this.constants.labels['editEdge'] +""; - } - if (this._selectionIsEmpty() == false) { - this.manipulationDiv.innerHTML += "" + - "
" + - "" + - ""+this.constants.labels['del'] +""; - } + exports._calculateGravitationalForces = function () { + var dx, dy, distance, node, i; + var nodes = this.calculationNodes; + var gravity = this.constants.physics.centralGravity; + var gravityForce = 0; + for (i = 0; i < this.calculationNodeIndices.length; i++) { + node = nodes[this.calculationNodeIndices[i]]; + node.damping = this.constants.physics.damping; // possibly add function to alter damping properties of clusters. + // gravity does not apply when we are in a pocket sector + if (this._sector() == "default" && gravity != 0) { + dx = -node.x; + dy = -node.y; + distance = Math.sqrt(dx * dx + dy * dy); - // bind the icons - var addNodeButton = document.getElementById("network-manipulate-addNode"); - addNodeButton.onclick = this._createAddNodeToolbar.bind(this); - var addEdgeButton = document.getElementById("network-manipulate-connectNode"); - addEdgeButton.onclick = this._createAddEdgeToolbar.bind(this); - if (this._getSelectedNodeCount() == 1 && this.triggerFunctions.edit) { - var editButton = document.getElementById("network-manipulate-editNode"); - editButton.onclick = this._editNode.bind(this); - } - else if (this._getSelectedEdgeCount() == 1 && this._getSelectedNodeCount() == 0) { - var editButton = document.getElementById("network-manipulate-editEdge"); - editButton.onclick = this._createEditEdgeToolbar.bind(this); + gravityForce = (distance == 0) ? 0 : (gravity / distance); + node.fx = dx * gravityForce; + node.fy = dy * gravityForce; } - if (this._selectionIsEmpty() == false) { - var deleteButton = document.getElementById("network-manipulate-delete"); - deleteButton.onclick = this._deleteSelected.bind(this); + else { + node.fx = 0; + node.fy = 0; } - var closeDiv = document.getElementById("network-manipulation-closeDiv"); - closeDiv.onclick = this._toggleEditMode.bind(this); - - this.boundFunction = this._createManipulatorBar.bind(this); - this.on('select', this.boundFunction); - } - else { - this.editModeDiv.innerHTML = "" + - "" + - "" + this.constants.labels['edit'] + ""; - var editModeButton = document.getElementById("network-manipulate-editModeButton"); - editModeButton.onclick = this._toggleEditMode.bind(this); } }; + /** - * Create the toolbar for adding Nodes + * this function calculates the effects of the springs in the case of unsmooth curves. * * @private */ - exports._createAddNodeToolbar = function() { - // clear the toolbar - this._clearManipulatorBar(); - if (this.boundFunction) { - this.off('select', this.boundFunction); - } + exports._calculateSpringForces = function () { + var edgeLength, edge, edgeId; + var dx, dy, fx, fy, springForce, distance; + var edges = this.edges; - // create the toolbar contents - this.manipulationDiv.innerHTML = "" + - "" + - "" + this.constants.labels['back'] + " " + - "
" + - "" + - "" + this.constants.labels['addDescription'] + ""; + // forces caused by the edges, modelled as springs + for (edgeId in edges) { + if (edges.hasOwnProperty(edgeId)) { + edge = edges[edgeId]; + if (edge.connected) { + // only calculate forces if nodes are in the same sector + if (this.nodes.hasOwnProperty(edge.toId) && this.nodes.hasOwnProperty(edge.fromId)) { + edgeLength = edge.physics.springLength; + // this implies that the edges between big clusters are longer + edgeLength += (edge.to.clusterSize + edge.from.clusterSize - 2) * this.constants.clustering.edgeGrowth; + + dx = (edge.from.x - edge.to.x); + dy = (edge.from.y - edge.to.y); + distance = Math.sqrt(dx * dx + dy * dy); + + if (distance == 0) { + distance = 0.01; + } + + // the 1/distance is so the fx and fy can be calculated without sine or cosine. + springForce = this.constants.physics.springConstant * (edgeLength - distance) / distance; + + fx = dx * springForce; + fy = dy * springForce; + + edge.from.fx += fx; + edge.from.fy += fy; + edge.to.fx -= fx; + edge.to.fy -= fy; + } + } + } + } + }; - // bind the icon - var backButton = document.getElementById("network-manipulate-back"); - backButton.onclick = this._createManipulatorBar.bind(this); - // we use the boundFunction so we can reference it when we unbind it from the "select" event. - this.boundFunction = this._addNode.bind(this); - this.on('select', this.boundFunction); - }; /** - * create the toolbar to connect nodes + * This function calculates the springforces on the nodes, accounting for the support nodes. * * @private */ - exports._createAddEdgeToolbar = function() { - // clear the toolbar - this._clearManipulatorBar(); - this._unselectAll(true); - this.freezeSimulation = true; + exports._calculateSpringForcesWithSupport = function () { + var edgeLength, edge, edgeId, combinedClusterSize; + var edges = this.edges; - if (this.boundFunction) { - this.off('select', this.boundFunction); + // forces caused by the edges, modelled as springs + for (edgeId in edges) { + if (edges.hasOwnProperty(edgeId)) { + edge = edges[edgeId]; + if (edge.connected) { + // only calculate forces if nodes are in the same sector + if (this.nodes.hasOwnProperty(edge.toId) && this.nodes.hasOwnProperty(edge.fromId)) { + if (edge.via != null) { + var node1 = edge.to; + var node2 = edge.via; + var node3 = edge.from; + + edgeLength = edge.physics.springLength; + + combinedClusterSize = node1.clusterSize + node3.clusterSize - 2; + + // this implies that the edges between big clusters are longer + edgeLength += combinedClusterSize * this.constants.clustering.edgeGrowth; + this._calculateSpringForce(node1, node2, 0.5 * edgeLength); + this._calculateSpringForce(node2, node3, 0.5 * edgeLength); + } + } + } + } } + }; - this._unselectAll(); - this.forceAppendSelection = false; - this.blockConnectingEdgeSelection = true; - this.manipulationDiv.innerHTML = "" + - "" + - "" + this.constants.labels['back'] + " " + - "
" + - "" + - "" + this.constants.labels['linkDescription'] + ""; + /** + * This is the code actually performing the calculation for the function above. It is split out to avoid repetition. + * + * @param node1 + * @param node2 + * @param edgeLength + * @private + */ + exports._calculateSpringForce = function (node1, node2, edgeLength) { + var dx, dy, fx, fy, springForce, distance; - // bind the icon - var backButton = document.getElementById("network-manipulate-back"); - backButton.onclick = this._createManipulatorBar.bind(this); + dx = (node1.x - node2.x); + dy = (node1.y - node2.y); + distance = Math.sqrt(dx * dx + dy * dy); - // we use the boundFunction so we can reference it when we unbind it from the "select" event. - this.boundFunction = this._handleConnect.bind(this); - this.on('select', this.boundFunction); + if (distance == 0) { + distance = 0.01; + } - // temporarily overload functions - this.cachedFunctions["_handleTouch"] = this._handleTouch; - this.cachedFunctions["_handleOnRelease"] = this._handleOnRelease; - this._handleTouch = this._handleConnect; - this._handleOnRelease = this._finishConnect; + // the 1/distance is so the fx and fy can be calculated without sine or cosine. + springForce = this.constants.physics.springConstant * (edgeLength - distance) / distance; - // redraw to show the unselect - this._redraw(); + fx = dx * springForce; + fy = dy * springForce; + + node1.fx += fx; + node1.fy += fy; + node2.fx -= fx; + node2.fy -= fy; }; + /** - * create the toolbar to edit edges - * + * Load the HTML for the physics config and bind it * @private */ - exports._createEditEdgeToolbar = function() { - // clear the toolbar - this._clearManipulatorBar(); - this.controlNodesActive = true; + exports._loadPhysicsConfiguration = function () { + if (this.physicsConfiguration === undefined) { + this.backupConstants = {}; + util.deepExtend(this.backupConstants,this.constants); - if (this.boundFunction) { - this.off('select', this.boundFunction); - } + var hierarchicalLayoutDirections = ["LR", "RL", "UD", "DU"]; + this.physicsConfiguration = document.createElement('div'); + this.physicsConfiguration.className = "PhysicsConfiguration"; + this.physicsConfiguration.innerHTML = '' + + '' + + '' + + '' + + '' + + '' + + '' + + '
Simulation Mode:
Barnes HutRepulsionHierarchical
' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '
Options:
' + this.containerElement.parentElement.insertBefore(this.physicsConfiguration, this.containerElement); + this.optionsDiv = document.createElement("div"); + this.optionsDiv.style.fontSize = "14px"; + this.optionsDiv.style.fontFamily = "verdana"; + this.containerElement.parentElement.insertBefore(this.optionsDiv, this.containerElement); - this.edgeBeingEdited = this._getSelectedEdge(); - this.edgeBeingEdited._enableControlNodes(); + var rangeElement; + rangeElement = document.getElementById('graph_BH_gc'); + rangeElement.onchange = showValueOfRange.bind(this, 'graph_BH_gc', -1, "physics_barnesHut_gravitationalConstant"); + rangeElement = document.getElementById('graph_BH_cg'); + rangeElement.onchange = showValueOfRange.bind(this, 'graph_BH_cg', 1, "physics_centralGravity"); + rangeElement = document.getElementById('graph_BH_sc'); + rangeElement.onchange = showValueOfRange.bind(this, 'graph_BH_sc', 1, "physics_springConstant"); + rangeElement = document.getElementById('graph_BH_sl'); + rangeElement.onchange = showValueOfRange.bind(this, 'graph_BH_sl', 1, "physics_springLength"); + rangeElement = document.getElementById('graph_BH_damp'); + rangeElement.onchange = showValueOfRange.bind(this, 'graph_BH_damp', 1, "physics_damping"); - this.manipulationDiv.innerHTML = "" + - "" + - "" + this.constants.labels['back'] + " " + - "
" + - "" + - "" + this.constants.labels['editEdgeDescription'] + ""; + rangeElement = document.getElementById('graph_R_nd'); + rangeElement.onchange = showValueOfRange.bind(this, 'graph_R_nd', 1, "physics_repulsion_nodeDistance"); + rangeElement = document.getElementById('graph_R_cg'); + rangeElement.onchange = showValueOfRange.bind(this, 'graph_R_cg', 1, "physics_centralGravity"); + rangeElement = document.getElementById('graph_R_sc'); + rangeElement.onchange = showValueOfRange.bind(this, 'graph_R_sc', 1, "physics_springConstant"); + rangeElement = document.getElementById('graph_R_sl'); + rangeElement.onchange = showValueOfRange.bind(this, 'graph_R_sl', 1, "physics_springLength"); + rangeElement = document.getElementById('graph_R_damp'); + rangeElement.onchange = showValueOfRange.bind(this, 'graph_R_damp', 1, "physics_damping"); - // bind the icon - var backButton = document.getElementById("network-manipulate-back"); - backButton.onclick = this._createManipulatorBar.bind(this); + rangeElement = document.getElementById('graph_H_nd'); + rangeElement.onchange = showValueOfRange.bind(this, 'graph_H_nd', 1, "physics_hierarchicalRepulsion_nodeDistance"); + rangeElement = document.getElementById('graph_H_cg'); + rangeElement.onchange = showValueOfRange.bind(this, 'graph_H_cg', 1, "physics_centralGravity"); + rangeElement = document.getElementById('graph_H_sc'); + rangeElement.onchange = showValueOfRange.bind(this, 'graph_H_sc', 1, "physics_springConstant"); + rangeElement = document.getElementById('graph_H_sl'); + rangeElement.onchange = showValueOfRange.bind(this, 'graph_H_sl', 1, "physics_springLength"); + rangeElement = document.getElementById('graph_H_damp'); + rangeElement.onchange = showValueOfRange.bind(this, 'graph_H_damp', 1, "physics_damping"); + rangeElement = document.getElementById('graph_H_direction'); + rangeElement.onchange = showValueOfRange.bind(this, 'graph_H_direction', hierarchicalLayoutDirections, "hierarchicalLayout_direction"); + rangeElement = document.getElementById('graph_H_levsep'); + rangeElement.onchange = showValueOfRange.bind(this, 'graph_H_levsep', 1, "hierarchicalLayout_levelSeparation"); + rangeElement = document.getElementById('graph_H_nspac'); + rangeElement.onchange = showValueOfRange.bind(this, 'graph_H_nspac', 1, "hierarchicalLayout_nodeSpacing"); - // temporarily overload functions - this.cachedFunctions["_handleTouch"] = this._handleTouch; - this.cachedFunctions["_handleOnRelease"] = this._handleOnRelease; - this.cachedFunctions["_handleTap"] = this._handleTap; - this.cachedFunctions["_handleDragStart"] = this._handleDragStart; - this.cachedFunctions["_handleOnDrag"] = this._handleOnDrag; - this._handleTouch = this._selectControlNode; - this._handleTap = function () {}; - this._handleOnDrag = this._controlNodeDrag; - this._handleDragStart = function () {} - this._handleOnRelease = this._releaseControlNode; + var radioButton1 = document.getElementById("graph_physicsMethod1"); + var radioButton2 = document.getElementById("graph_physicsMethod2"); + var radioButton3 = document.getElementById("graph_physicsMethod3"); + radioButton2.checked = true; + if (this.constants.physics.barnesHut.enabled) { + radioButton1.checked = true; + } + if (this.constants.hierarchicalLayout.enabled) { + radioButton3.checked = true; + } - // redraw to show the unselect - this._redraw(); - }; + var graph_toggleSmooth = document.getElementById("graph_toggleSmooth"); + var graph_repositionNodes = document.getElementById("graph_repositionNodes"); + var graph_generateOptions = document.getElementById("graph_generateOptions"); + graph_toggleSmooth.onclick = graphToggleSmoothCurves.bind(this); + graph_repositionNodes.onclick = graphRepositionNodes.bind(this); + graph_generateOptions.onclick = graphGenerateOptions.bind(this); + if (this.constants.smoothCurves == true && this.constants.dynamicSmoothCurves == false) { + graph_toggleSmooth.style.background = "#A4FF56"; + } + else { + graph_toggleSmooth.style.background = "#FF8532"; + } + switchConfigurations.apply(this); + radioButton1.onchange = switchConfigurations.bind(this); + radioButton2.onchange = switchConfigurations.bind(this); + radioButton3.onchange = switchConfigurations.bind(this); + } + }; /** - * the function bound to the selection event. It checks if you want to connect a cluster and changes the description - * to walk the user through the process. + * This overwrites the this.constants. * + * @param constantsVariableName + * @param value * @private */ - exports._selectControlNode = function(pointer) { - this.edgeBeingEdited.controlNodes.from.unselect(); - this.edgeBeingEdited.controlNodes.to.unselect(); - this.selectedControlNode = this.edgeBeingEdited._getSelectedControlNode(this._XconvertDOMtoCanvas(pointer.x),this._YconvertDOMtoCanvas(pointer.y)); - if (this.selectedControlNode !== null) { - this.selectedControlNode.select(); - this.freezeSimulation = true; + exports._overWriteGraphConstants = function (constantsVariableName, value) { + var nameArray = constantsVariableName.split("_"); + if (nameArray.length == 1) { + this.constants[nameArray[0]] = value; + } + else if (nameArray.length == 2) { + this.constants[nameArray[0]][nameArray[1]] = value; + } + else if (nameArray.length == 3) { + this.constants[nameArray[0]][nameArray[1]][nameArray[2]] = value; } - this._redraw(); }; + /** - * the function bound to the selection event. It checks if you want to connect a cluster and changes the description - * to walk the user through the process. - * - * @private + * this function is bound to the toggle smooth curves button. That is also why it is not in the prototype. */ - exports._controlNodeDrag = function(event) { - var pointer = this._getPointer(event.gesture.center); - if (this.selectedControlNode !== null && this.selectedControlNode !== undefined) { - this.selectedControlNode.x = this._XconvertDOMtoCanvas(pointer.x); - this.selectedControlNode.y = this._YconvertDOMtoCanvas(pointer.y); - } - this._redraw(); - }; + function graphToggleSmoothCurves () { + this.constants.smoothCurves.enabled = !this.constants.smoothCurves.enabled; + var graph_toggleSmooth = document.getElementById("graph_toggleSmooth"); + if (this.constants.smoothCurves.enabled == true) {graph_toggleSmooth.style.background = "#A4FF56";} + else {graph_toggleSmooth.style.background = "#FF8532";} - exports._releaseControlNode = function(pointer) { - var newNode = this._getNodeAt(pointer); - if (newNode != null) { - if (this.edgeBeingEdited.controlNodes.from.selected == true) { - this._editEdge(newNode.id, this.edgeBeingEdited.to.id); - this.edgeBeingEdited.controlNodes.from.unselect(); - } - if (this.edgeBeingEdited.controlNodes.to.selected == true) { - this._editEdge(this.edgeBeingEdited.from.id, newNode.id); - this.edgeBeingEdited.controlNodes.to.unselect(); + this._configureSmoothCurves(false); + } + + /** + * this function is used to scramble the nodes + * + */ + function graphRepositionNodes () { + for (var nodeId in this.calculationNodes) { + if (this.calculationNodes.hasOwnProperty(nodeId)) { + this.calculationNodes[nodeId].vx = 0; this.calculationNodes[nodeId].vy = 0; + this.calculationNodes[nodeId].fx = 0; this.calculationNodes[nodeId].fy = 0; } } + if (this.constants.hierarchicalLayout.enabled == true) { + this._setupHierarchicalLayout(); + showValueOfRange.call(this, 'graph_H_nd', 1, "physics_hierarchicalRepulsion_nodeDistance"); + showValueOfRange.call(this, 'graph_H_cg', 1, "physics_centralGravity"); + showValueOfRange.call(this, 'graph_H_sc', 1, "physics_springConstant"); + showValueOfRange.call(this, 'graph_H_sl', 1, "physics_springLength"); + showValueOfRange.call(this, 'graph_H_damp', 1, "physics_damping"); + } else { - this.edgeBeingEdited._restoreControlNodes(); + this.repositionNodes(); } - this.freezeSimulation = false; - this._redraw(); - }; + this.moving = true; + this.start(); + } /** - * the function bound to the selection event. It checks if you want to connect a cluster and changes the description - * to walk the user through the process. - * - * @private + * this is used to generate an options file from the playing with physics system. */ - exports._handleConnect = function(pointer) { - if (this._getSelectedNodeCount() == 0) { - var node = this._getNodeAt(pointer); - if (node != null) { - if (node.clusterSize > 1) { - alert("Cannot create edges to a cluster.") - } - else { - this._selectObject(node,false); - // create a node the temporary line can look at - this.sectors['support']['nodes']['targetNode'] = new Node({id:'targetNode'},{},{},this.constants); - this.sectors['support']['nodes']['targetNode'].x = node.x; - this.sectors['support']['nodes']['targetNode'].y = node.y; - this.sectors['support']['nodes']['targetViaNode'] = new Node({id:'targetViaNode'},{},{},this.constants); - this.sectors['support']['nodes']['targetViaNode'].x = node.x; - this.sectors['support']['nodes']['targetViaNode'].y = node.y; - this.sectors['support']['nodes']['targetViaNode'].parentEdgeId = "connectionEdge"; - - // create a temporary edge - this.edges['connectionEdge'] = new Edge({id:"connectionEdge",from:node.id,to:this.sectors['support']['nodes']['targetNode'].id}, this, this.constants); - this.edges['connectionEdge'].from = node; - this.edges['connectionEdge'].connected = true; - this.edges['connectionEdge'].smooth = true; - this.edges['connectionEdge'].selected = true; - this.edges['connectionEdge'].to = this.sectors['support']['nodes']['targetNode']; - this.edges['connectionEdge'].via = this.sectors['support']['nodes']['targetViaNode']; - - this.cachedFunctions["_handleOnDrag"] = this._handleOnDrag; - this._handleOnDrag = function(event) { - var pointer = this._getPointer(event.gesture.center); - this.sectors['support']['nodes']['targetNode'].x = this._XconvertDOMtoCanvas(pointer.x); - this.sectors['support']['nodes']['targetNode'].y = this._YconvertDOMtoCanvas(pointer.y); - this.sectors['support']['nodes']['targetViaNode'].x = 0.5 * (this._XconvertDOMtoCanvas(pointer.x) + this.edges['connectionEdge'].from.x); - this.sectors['support']['nodes']['targetViaNode'].y = this._YconvertDOMtoCanvas(pointer.y); - }; - - this.moving = true; - this.start(); + function graphGenerateOptions () { + var options = "No options are required, default values used."; + var optionsSpecific = []; + var radioButton1 = document.getElementById("graph_physicsMethod1"); + var radioButton2 = document.getElementById("graph_physicsMethod2"); + if (radioButton1.checked == true) { + if (this.constants.physics.barnesHut.gravitationalConstant != this.backupConstants.physics.barnesHut.gravitationalConstant) {optionsSpecific.push("gravitationalConstant: " + this.constants.physics.barnesHut.gravitationalConstant);} + if (this.constants.physics.centralGravity != this.backupConstants.physics.barnesHut.centralGravity) {optionsSpecific.push("centralGravity: " + this.constants.physics.centralGravity);} + if (this.constants.physics.springLength != this.backupConstants.physics.barnesHut.springLength) {optionsSpecific.push("springLength: " + this.constants.physics.springLength);} + if (this.constants.physics.springConstant != this.backupConstants.physics.barnesHut.springConstant) {optionsSpecific.push("springConstant: " + this.constants.physics.springConstant);} + if (this.constants.physics.damping != this.backupConstants.physics.barnesHut.damping) {optionsSpecific.push("damping: " + this.constants.physics.damping);} + if (optionsSpecific.length != 0) { + options = "var options = {"; + options += "physics: {barnesHut: {"; + for (var i = 0; i < optionsSpecific.length; i++) { + options += optionsSpecific[i]; + if (i < optionsSpecific.length - 1) { + options += ", " + } } + options += '}}' + } + if (this.constants.smoothCurves.enabled != this.backupConstants.smoothCurves.enabled) { + if (optionsSpecific.length == 0) {options = "var options = {";} + else {options += ", "} + options += "smoothCurves: " + this.constants.smoothCurves.enabled; + } + if (options != "No options are required, default values used.") { + options += '};' } } - }; - - exports._finishConnect = function(pointer) { - if (this._getSelectedNodeCount() == 1) { - - // restore the drag function - this._handleOnDrag = this.cachedFunctions["_handleOnDrag"]; - delete this.cachedFunctions["_handleOnDrag"]; - - // remember the edge id - var connectFromId = this.edges['connectionEdge'].fromId; - - // remove the temporary nodes and edge - delete this.edges['connectionEdge']; - delete this.sectors['support']['nodes']['targetNode']; - delete this.sectors['support']['nodes']['targetViaNode']; - - var node = this._getNodeAt(pointer); - if (node != null) { - if (node.clusterSize > 1) { - alert("Cannot create edges to a cluster.") - } - else { - this._createEdge(connectFromId,node.id); - this._createManipulatorBar(); + else if (radioButton2.checked == true) { + options = "var options = {"; + options += "physics: {barnesHut: {enabled: false}"; + if (this.constants.physics.repulsion.nodeDistance != this.backupConstants.physics.repulsion.nodeDistance) {optionsSpecific.push("nodeDistance: " + this.constants.physics.repulsion.nodeDistance);} + if (this.constants.physics.centralGravity != this.backupConstants.physics.repulsion.centralGravity) {optionsSpecific.push("centralGravity: " + this.constants.physics.centralGravity);} + if (this.constants.physics.springLength != this.backupConstants.physics.repulsion.springLength) {optionsSpecific.push("springLength: " + this.constants.physics.springLength);} + if (this.constants.physics.springConstant != this.backupConstants.physics.repulsion.springConstant) {optionsSpecific.push("springConstant: " + this.constants.physics.springConstant);} + if (this.constants.physics.damping != this.backupConstants.physics.repulsion.damping) {optionsSpecific.push("damping: " + this.constants.physics.damping);} + if (optionsSpecific.length != 0) { + options += ", repulsion: {"; + for (var i = 0; i < optionsSpecific.length; i++) { + options += optionsSpecific[i]; + if (i < optionsSpecific.length - 1) { + options += ", " + } } + options += '}}' } - this._unselectAll(); + if (optionsSpecific.length == 0) {options += "}"} + if (this.constants.smoothCurves != this.backupConstants.smoothCurves) { + options += ", smoothCurves: " + this.constants.smoothCurves; + } + options += '};' } - }; - - - /** - * Adds a node on the specified location - */ - exports._addNode = function() { - if (this._selectionIsEmpty() && this.editMode == true) { - var positionObject = this._pointerToPositionObject(this.pointerPosition); - var defaultData = {id:util.randomUUID(),x:positionObject.left,y:positionObject.top,label:"new",allowedToMoveX:true,allowedToMoveY:true}; - if (this.triggerFunctions.add) { - if (this.triggerFunctions.add.length == 2) { - var me = this; - this.triggerFunctions.add(defaultData, function(finalizedData) { - me.nodesData.add(finalizedData); - me._createManipulatorBar(); - me.moving = true; - me.start(); - }); + else { + options = "var options = {"; + if (this.constants.physics.hierarchicalRepulsion.nodeDistance != this.backupConstants.physics.hierarchicalRepulsion.nodeDistance) {optionsSpecific.push("nodeDistance: " + this.constants.physics.hierarchicalRepulsion.nodeDistance);} + if (this.constants.physics.centralGravity != this.backupConstants.physics.hierarchicalRepulsion.centralGravity) {optionsSpecific.push("centralGravity: " + this.constants.physics.centralGravity);} + if (this.constants.physics.springLength != this.backupConstants.physics.hierarchicalRepulsion.springLength) {optionsSpecific.push("springLength: " + this.constants.physics.springLength);} + if (this.constants.physics.springConstant != this.backupConstants.physics.hierarchicalRepulsion.springConstant) {optionsSpecific.push("springConstant: " + this.constants.physics.springConstant);} + if (this.constants.physics.damping != this.backupConstants.physics.hierarchicalRepulsion.damping) {optionsSpecific.push("damping: " + this.constants.physics.damping);} + if (optionsSpecific.length != 0) { + options += "physics: {hierarchicalRepulsion: {"; + for (var i = 0; i < optionsSpecific.length; i++) { + options += optionsSpecific[i]; + if (i < optionsSpecific.length - 1) { + options += ", "; + } } - else { - alert(this.constants.labels['addError']); - this._createManipulatorBar(); - this.moving = true; - this.start(); + options += '}},'; + } + options += 'hierarchicalLayout: {'; + optionsSpecific = []; + if (this.constants.hierarchicalLayout.direction != this.backupConstants.hierarchicalLayout.direction) {optionsSpecific.push("direction: " + this.constants.hierarchicalLayout.direction);} + if (Math.abs(this.constants.hierarchicalLayout.levelSeparation) != this.backupConstants.hierarchicalLayout.levelSeparation) {optionsSpecific.push("levelSeparation: " + this.constants.hierarchicalLayout.levelSeparation);} + if (this.constants.hierarchicalLayout.nodeSpacing != this.backupConstants.hierarchicalLayout.nodeSpacing) {optionsSpecific.push("nodeSpacing: " + this.constants.hierarchicalLayout.nodeSpacing);} + if (optionsSpecific.length != 0) { + for (var i = 0; i < optionsSpecific.length; i++) { + options += optionsSpecific[i]; + if (i < optionsSpecific.length - 1) { + options += ", " + } } + options += '}' } else { - this.nodesData.add(defaultData); - this._createManipulatorBar(); - this.moving = true; - this.start(); + options += "enabled:true}"; } + options += '};' } - }; - /** - * connect two nodes with a new edge. - * - * @private - */ - exports._createEdge = function(sourceNodeId,targetNodeId) { - if (this.editMode == true) { - var defaultData = {from:sourceNodeId, to:targetNodeId}; - if (this.triggerFunctions.connect) { - if (this.triggerFunctions.connect.length == 2) { - var me = this; - this.triggerFunctions.connect(defaultData, function(finalizedData) { - me.edgesData.add(finalizedData); - me.moving = true; - me.start(); - }); - } - else { - alert(this.constants.labels["linkError"]); - this.moving = true; - this.start(); - } - } - else { - this.edgesData.add(defaultData); - this.moving = true; - this.start(); - } - } - }; + this.optionsDiv.innerHTML = options; + } /** - * connect two nodes with a new edge. + * this is used to switch between barnesHut, repulsion and hierarchical. * - * @private */ - exports._editEdge = function(sourceNodeId,targetNodeId) { - if (this.editMode == true) { - var defaultData = {id: this.edgeBeingEdited.id, from:sourceNodeId, to:targetNodeId}; - if (this.triggerFunctions.editEdge) { - if (this.triggerFunctions.editEdge.length == 2) { - var me = this; - this.triggerFunctions.editEdge(defaultData, function(finalizedData) { - me.edgesData.update(finalizedData); - me.moving = true; - me.start(); - }); - } - else { - alert(this.constants.labels["linkError"]); - this.moving = true; - this.start(); - } + function switchConfigurations () { + var ids = ["graph_BH_table", "graph_R_table", "graph_H_table"]; + var radioButton = document.querySelector('input[name="graph_physicsMethod"]:checked').value; + var tableId = "graph_" + radioButton + "_table"; + var table = document.getElementById(tableId); + table.style.display = "block"; + for (var i = 0; i < ids.length; i++) { + if (ids[i] != tableId) { + table = document.getElementById(ids[i]); + table.style.display = "none"; } - else { - this.edgesData.update(defaultData); - this.moving = true; - this.start(); + } + this._restoreNodes(); + if (radioButton == "R") { + this.constants.hierarchicalLayout.enabled = false; + this.constants.physics.hierarchicalRepulsion.enabled = false; + this.constants.physics.barnesHut.enabled = false; + } + else if (radioButton == "H") { + if (this.constants.hierarchicalLayout.enabled == false) { + this.constants.hierarchicalLayout.enabled = true; + this.constants.physics.hierarchicalRepulsion.enabled = true; + this.constants.physics.barnesHut.enabled = false; + this.constants.smoothCurves.enabled = false; + this._setupHierarchicalLayout(); } } - }; + else { + this.constants.hierarchicalLayout.enabled = false; + this.constants.physics.hierarchicalRepulsion.enabled = false; + this.constants.physics.barnesHut.enabled = true; + } + this._loadSelectedForceSolver(); + var graph_toggleSmooth = document.getElementById("graph_toggleSmooth"); + if (this.constants.smoothCurves.enabled == true) {graph_toggleSmooth.style.background = "#A4FF56";} + else {graph_toggleSmooth.style.background = "#FF8532";} + this.moving = true; + this.start(); + } + /** - * Create the toolbar to edit the selected node. The label and the color can be changed. Other colors are derived from the chosen color. + * this generates the ranges depending on the iniital values. * - * @private + * @param id + * @param map + * @param constantsVariableName */ - exports._editNode = function() { - if (this.triggerFunctions.edit && this.editMode == true) { - var node = this._getSelectedNode(); - var data = {id:node.id, - label: node.label, - group: node.options.group, - shape: node.options.shape, - color: { - background:node.options.color.background, - border:node.options.color.border, - highlight: { - background:node.options.color.highlight.background, - border:node.options.color.highlight.border - } - }}; - if (this.triggerFunctions.edit.length == 2) { - var me = this; - this.triggerFunctions.edit(data, function (finalizedData) { - me.nodesData.update(finalizedData); - me._createManipulatorBar(); - me.moving = true; - me.start(); - }); - } - else { - alert(this.constants.labels["editError"]); - } + function showValueOfRange (id,map,constantsVariableName) { + var valueId = id + "_value"; + var rangeValue = document.getElementById(id).value; + + if (map instanceof Array) { + document.getElementById(valueId).value = map[parseInt(rangeValue)]; + this._overWriteGraphConstants(constantsVariableName,map[parseInt(rangeValue)]); } else { - alert(this.constants.labels["editBoundError"]); + document.getElementById(valueId).value = parseInt(map) * parseFloat(rangeValue); + this._overWriteGraphConstants(constantsVariableName, parseInt(map) * parseFloat(rangeValue)); } - }; + if (constantsVariableName == "hierarchicalLayout_direction" || + constantsVariableName == "hierarchicalLayout_levelSeparation" || + constantsVariableName == "hierarchicalLayout_nodeSpacing") { + this._setupHierarchicalLayout(); + } + this.moving = true; + this.start(); + } + + +/***/ }, +/* 57 */ +/***/ function(module, exports, __webpack_require__) { + + var map = {}; + function webpackContext(req) { + return __webpack_require__(webpackContextResolve(req)); + }; + function webpackContextResolve(req) { + return map[req] || (function() { throw new Error("Cannot find module '" + req + "'.") }()); + }; + webpackContext.keys = function webpackContextKeys() { + return Object.keys(map); + }; + webpackContext.resolve = webpackContextResolve; + module.exports = webpackContext; +/***/ }, +/* 58 */ +/***/ function(module, exports, __webpack_require__) { /** - * delete everything in the selection + * Calculate the forces the nodes apply on each other based on a repulsion field. + * This field is linearly approximated. * * @private */ - exports._deleteSelected = function() { - if (!this._selectionIsEmpty() && this.editMode == true) { - if (!this._clusterInSelection()) { - var selectedNodes = this.getSelectedNodes(); - var selectedEdges = this.getSelectedEdges(); - if (this.triggerFunctions.del) { - var me = this; - var data = {nodes: selectedNodes, edges: selectedEdges}; - if (this.triggerFunctions.del.length = 2) { - this.triggerFunctions.del(data, function (finalizedData) { - me.edgesData.remove(finalizedData.edges); - me.nodesData.remove(finalizedData.nodes); - me._unselectAll(); - me.moving = true; - me.start(); - }); + exports._calculateNodeForces = function () { + var dx, dy, angle, distance, fx, fy, combinedClusterSize, + repulsingForce, node1, node2, i, j; + + var nodes = this.calculationNodes; + var nodeIndices = this.calculationNodeIndices; + + // approximation constants + var a_base = -2 / 3; + var b = 4 / 3; + + // repulsing forces between nodes + var nodeDistance = this.constants.physics.repulsion.nodeDistance; + var minimumDistance = nodeDistance; + + // we loop from i over all but the last entree in the array + // j loops from i+1 to the last. This way we do not double count any of the indices, nor i == j + for (i = 0; i < nodeIndices.length - 1; i++) { + node1 = nodes[nodeIndices[i]]; + for (j = i + 1; j < nodeIndices.length; j++) { + node2 = nodes[nodeIndices[j]]; + combinedClusterSize = node1.clusterSize + node2.clusterSize - 2; + + dx = node2.x - node1.x; + dy = node2.y - node1.y; + distance = Math.sqrt(dx * dx + dy * dy); + + minimumDistance = (combinedClusterSize == 0) ? nodeDistance : (nodeDistance * (1 + combinedClusterSize * this.constants.clustering.distanceAmplification)); + var a = a_base / minimumDistance; + if (distance < 2 * minimumDistance) { + if (distance < 0.5 * minimumDistance) { + repulsingForce = 1.0; } else { - alert(this.constants.labels["deleteError"]) - } - } - else { - this.edgesData.remove(selectedEdges); - this.nodesData.remove(selectedNodes); - this._unselectAll(); - this.moving = true; - this.start(); + repulsingForce = a * distance + b; // linear approx of 1 / (1 + Math.exp((distance / minimumDistance - 1) * steepness)) + } + + // amplify the repulsion for clusters. + repulsingForce *= (combinedClusterSize == 0) ? 1 : 1 + combinedClusterSize * this.constants.clustering.forceAmplification; + repulsingForce = repulsingForce / distance; + + fx = dx * repulsingForce; + fy = dy * repulsingForce; + + node1.fx -= fx; + node1.fy -= fy; + node2.fx += fx; + node2.fy += fy; } } - else { - alert(this.constants.labels["deleteClusterError"]); - } } }; @@ -30122,713 +30256,579 @@ return /******/ (function(modules) { // webpackBootstrap /* 59 */ /***/ function(module, exports, __webpack_require__) { - var util = __webpack_require__(1); - var Hammer = __webpack_require__(18); - - exports._cleanNavigation = function() { - // clean up previous navigation items - var wrapper = document.getElementById('network-navigation_wrapper'); - if (wrapper != null) { - this.containerElement.removeChild(wrapper); - } - document.onmouseup = null; - }; - /** - * Creation of the navigation controls nodes. They are drawn over the rest of the nodes and are not affected by scale and translation - * they have a triggerFunction which is called on click. If the position of the navigation controls is dependent - * on this.frame.canvas.clientWidth or this.frame.canvas.clientHeight, we flag horizontalAlignLeft and verticalAlignTop false. - * This means that the location will be corrected by the _relocateNavigation function on a size change of the canvas. + * Calculate the forces the nodes apply on eachother based on a repulsion field. + * This field is linearly approximated. * * @private */ - exports._loadNavigationElements = function() { - this._cleanNavigation(); + exports._calculateNodeForces = function () { + var dx, dy, distance, fx, fy, + repulsingForce, node1, node2, i, j; - this.navigationDivs = {}; - var navigationDivs = ['up','down','left','right','zoomIn','zoomOut','zoomExtends']; - var navigationDivActions = ['_moveUp','_moveDown','_moveLeft','_moveRight','_zoomIn','_zoomOut','zoomExtent']; + var nodes = this.calculationNodes; + var nodeIndices = this.calculationNodeIndices; - this.navigationDivs['wrapper'] = document.createElement('div'); - this.navigationDivs['wrapper'].id = "network-navigation_wrapper"; - this.navigationDivs['wrapper'].style.position = "absolute"; - this.navigationDivs['wrapper'].style.width = this.frame.canvas.clientWidth + "px"; - this.navigationDivs['wrapper'].style.height = this.frame.canvas.clientHeight + "px"; - this.containerElement.insertBefore(this.navigationDivs['wrapper'],this.frame); + // repulsing forces between nodes + var nodeDistance = this.constants.physics.hierarchicalRepulsion.nodeDistance; - var me = this; - for (var i = 0; i < navigationDivs.length; i++) { - this.navigationDivs[navigationDivs[i]] = document.createElement('div'); - this.navigationDivs[navigationDivs[i]].id = "network-navigation_" + navigationDivs[i]; - this.navigationDivs[navigationDivs[i]].className = "network-navigation " + navigationDivs[i]; - this.navigationDivs['wrapper'].appendChild(this.navigationDivs[navigationDivs[i]]); - var hammer = Hammer(this.navigationDivs[navigationDivs[i]], {prevent_default: true}); - hammer.on("touch", me[navigationDivActions[i]].bind(me)); - } - var hammer = Hammer(document, {prevent_default: false}); - hammer.on("release", me._stopMovement.bind(me)); - }; + // we loop from i over all but the last entree in the array + // j loops from i+1 to the last. This way we do not double count any of the indices, nor i == j + for (i = 0; i < nodeIndices.length - 1; i++) { + node1 = nodes[nodeIndices[i]]; + for (j = i + 1; j < nodeIndices.length; j++) { + node2 = nodes[nodeIndices[j]]; - /** - * this stops all movement induced by the navigation buttons - * - * @private - */ - exports._stopMovement = function() { - this._xStopMoving(); - this._yStopMoving(); - this._stopZoom(); + // nodes only affect nodes on their level + if (node1.level == node2.level) { + + dx = node2.x - node1.x; + dy = node2.y - node1.y; + distance = Math.sqrt(dx * dx + dy * dy); + + + var steepness = 0.05; + if (distance < nodeDistance) { + repulsingForce = -Math.pow(steepness*distance,2) + Math.pow(steepness*nodeDistance,2); + } + else { + repulsingForce = 0; + } + // normalize force with + if (distance == 0) { + distance = 0.01; + } + else { + repulsingForce = repulsingForce / distance; + } + fx = dx * repulsingForce; + fy = dy * repulsingForce; + + node1.fx -= fx; + node1.fy -= fy; + node2.fx += fx; + node2.fy += fy; + } + } + } }; /** - * move the screen up - * By using the increments, instead of adding a fixed number to the translation, we keep fluent and - * instant movement. The onKeypress event triggers immediately, then pauses, then triggers frequently - * To avoid this behaviour, we do the translation in the start loop. + * this function calculates the effects of the springs in the case of unsmooth curves. * * @private */ - exports._moveUp = function(event) { - this.yIncrement = this.constants.keyboard.speed.y; - this.start(); // if there is no node movement, the calculation wont be done - }; + exports._calculateHierarchicalSpringForces = function () { + var edgeLength, edge, edgeId; + var dx, dy, fx, fy, springForce, distance; + var edges = this.edges; + var nodes = this.calculationNodes; + var nodeIndices = this.calculationNodeIndices; - /** - * move the screen down - * @private - */ - exports._moveDown = function(event) { - this.yIncrement = -this.constants.keyboard.speed.y; - this.start(); // if there is no node movement, the calculation wont be done - }; + for (var i = 0; i < nodeIndices.length; i++) { + var node1 = nodes[nodeIndices[i]]; + node1.springFx = 0; + node1.springFy = 0; + } - /** - * move the screen left - * @private - */ - exports._moveLeft = function(event) { - this.xIncrement = this.constants.keyboard.speed.x; - this.start(); // if there is no node movement, the calculation wont be done - }; + // forces caused by the edges, modelled as springs + for (edgeId in edges) { + if (edges.hasOwnProperty(edgeId)) { + edge = edges[edgeId]; + if (edge.connected) { + // only calculate forces if nodes are in the same sector + if (this.nodes.hasOwnProperty(edge.toId) && this.nodes.hasOwnProperty(edge.fromId)) { + edgeLength = edge.physics.springLength; + // this implies that the edges between big clusters are longer + edgeLength += (edge.to.clusterSize + edge.from.clusterSize - 2) * this.constants.clustering.edgeGrowth; - /** - * move the screen right - * @private - */ - exports._moveRight = function(event) { - this.xIncrement = -this.constants.keyboard.speed.y; - this.start(); // if there is no node movement, the calculation wont be done - }; + dx = (edge.from.x - edge.to.x); + dy = (edge.from.y - edge.to.y); + distance = Math.sqrt(dx * dx + dy * dy); + if (distance == 0) { + distance = 0.01; + } - /** - * Zoom in, using the same method as the movement. - * @private - */ - exports._zoomIn = function(event) { - this.zoomIncrement = this.constants.keyboard.speed.zoom; - this.start(); // if there is no node movement, the calculation wont be done - }; + // the 1/distance is so the fx and fy can be calculated without sine or cosine. + springForce = this.constants.physics.springConstant * (edgeLength - distance) / distance; + fx = dx * springForce; + fy = dy * springForce; - /** - * Zoom out - * @private - */ - exports._zoomOut = function() { - this.zoomIncrement = -this.constants.keyboard.speed.zoom; - this.start(); // if there is no node movement, the calculation wont be done - util.preventDefault(event); - }; - /** - * Stop zooming and unhighlight the zoom controls - * @private - */ - exports._stopZoom = function() { - this.zoomIncrement = 0; - }; + if (edge.to.level != edge.from.level) { + edge.to.springFx -= fx; + edge.to.springFy -= fy; + edge.from.springFx += fx; + edge.from.springFy += fy; + } + else { + var factor = 0.5; + edge.to.fx -= factor*fx; + edge.to.fy -= factor*fy; + edge.from.fx += factor*fx; + edge.from.fy += factor*fy; + } + } + } + } + } + // normalize spring forces + var springForce = 1; + var springFx, springFy; + for (i = 0; i < nodeIndices.length; i++) { + var node = nodes[nodeIndices[i]]; + springFx = Math.min(springForce,Math.max(-springForce,node.springFx)); + springFy = Math.min(springForce,Math.max(-springForce,node.springFy)); - /** - * Stop moving in the Y direction and unHighlight the up and down - * @private - */ - exports._yStopMoving = function() { - this.yIncrement = 0; - }; + node.fx += springFx; + node.fy += springFy; + } + + // retain energy balance + var totalFx = 0; + var totalFy = 0; + for (i = 0; i < nodeIndices.length; i++) { + var node = nodes[nodeIndices[i]]; + totalFx += node.fx; + totalFy += node.fy; + } + var correctionFx = totalFx / nodeIndices.length; + var correctionFy = totalFy / nodeIndices.length; + for (i = 0; i < nodeIndices.length; i++) { + var node = nodes[nodeIndices[i]]; + node.fx -= correctionFx; + node.fy -= correctionFy; + } - /** - * Stop moving in the X direction and unHighlight left and right. - * @private - */ - exports._xStopMoving = function() { - this.xIncrement = 0; }; - /***/ }, /* 60 */ /***/ function(module, exports, __webpack_require__) { - exports._resetLevels = function() { - for (var nodeId in this.nodes) { - if (this.nodes.hasOwnProperty(nodeId)) { - var node = this.nodes[nodeId]; - if (node.preassignedLevel == false) { - node.level = -1; - } - } - } - }; - /** - * This is the main function to layout the nodes in a hierarchical way. - * It checks if the node details are supplied correctly + * This function calculates the forces the nodes apply on eachother based on a gravitational model. + * The Barnes Hut method is used to speed up this N-body simulation. * * @private */ - exports._setupHierarchicalLayout = function() { - if (this.constants.hierarchicalLayout.enabled == true && this.nodeIndices.length > 0) { - if (this.constants.hierarchicalLayout.direction == "RL" || this.constants.hierarchicalLayout.direction == "DU") { - this.constants.hierarchicalLayout.levelSeparation *= -1; - } - else { - this.constants.hierarchicalLayout.levelSeparation = Math.abs(this.constants.hierarchicalLayout.levelSeparation); - } - - if (this.constants.hierarchicalLayout.direction == "RL" || this.constants.hierarchicalLayout.direction == "LR") { - if (this.constants.smoothCurves.enabled == true) { - this.constants.smoothCurves.type = "vertical"; - } - } - else { - if (this.constants.smoothCurves.enabled == true) { - this.constants.smoothCurves.type = "horizontal"; - } - } - // get the size of the largest hubs and check if the user has defined a level for a node. - var hubsize = 0; - var node, nodeId; - var definedLevel = false; - var undefinedLevel = false; + exports._calculateNodeForces = function() { + if (this.constants.physics.barnesHut.gravitationalConstant != 0) { + var node; + var nodes = this.calculationNodes; + var nodeIndices = this.calculationNodeIndices; + var nodeCount = nodeIndices.length; - for (nodeId in this.nodes) { - if (this.nodes.hasOwnProperty(nodeId)) { - node = this.nodes[nodeId]; - if (node.level != -1) { - definedLevel = true; - } - else { - undefinedLevel = true; - } - if (hubsize < node.edges.length) { - hubsize = node.edges.length; - } - } - } + this._formBarnesHutTree(nodes,nodeIndices); - // if the user defined some levels but not all, alert and run without hierarchical layout - if (undefinedLevel == true && definedLevel == true) { - alert("To use the hierarchical layout, nodes require either no predefined levels or levels have to be defined for all nodes."); - this.zoomExtent(true,this.constants.clustering.enabled); - if (!this.constants.clustering.enabled) { - this.start(); - } - } - else { - // setup the system to use hierarchical method. - this._changeConstants(); + var barnesHutTree = this.barnesHutTree; - // define levels if undefined by the users. Based on hubsize - if (undefinedLevel == true) { - this._determineLevels(hubsize); + // place the nodes one by one recursively + for (var i = 0; i < nodeCount; i++) { + node = nodes[nodeIndices[i]]; + if (node.options.mass > 0) { + // starting with root is irrelevant, it never passes the BarnesHut condition + this._getForceContribution(barnesHutTree.root.children.NW,node); + this._getForceContribution(barnesHutTree.root.children.NE,node); + this._getForceContribution(barnesHutTree.root.children.SW,node); + this._getForceContribution(barnesHutTree.root.children.SE,node); } - // check the distribution of the nodes per level. - var distribution = this._getDistribution(); - - // place the nodes on the canvas. This also stablilizes the system. - this._placeNodesByHierarchy(distribution); - - // start the simulation. - this.start(); } } }; /** - * This function places the nodes on the canvas based on the hierarchial distribution. + * This function traverses the barnesHutTree. It checks when it can approximate distant nodes with their center of mass. + * If a region contains a single node, we check if it is not itself, then we apply the force. * - * @param {Object} distribution | obtained by the function this._getDistribution() + * @param parentBranch + * @param node * @private */ - exports._placeNodesByHierarchy = function(distribution) { - var nodeId, node; - - // start placing all the level 0 nodes first. Then recursively position their branches. - for (var level in distribution) { - if (distribution.hasOwnProperty(level)) { - - for (nodeId in distribution[level].nodes) { - if (distribution[level].nodes.hasOwnProperty(nodeId)) { - node = distribution[level].nodes[nodeId]; - if (this.constants.hierarchicalLayout.direction == "UD" || this.constants.hierarchicalLayout.direction == "DU") { - if (node.xFixed) { - node.x = distribution[level].minPos; - node.xFixed = false; + exports._getForceContribution = function(parentBranch,node) { + // we get no force contribution from an empty region + if (parentBranch.childrenCount > 0) { + var dx,dy,distance; - distribution[level].minPos += distribution[level].nodeSpacing; - } - } - else { - if (node.yFixed) { - node.y = distribution[level].minPos; - node.yFixed = false; + // get the distance from the center of mass to the node. + dx = parentBranch.centerOfMass.x - node.x; + dy = parentBranch.centerOfMass.y - node.y; + distance = Math.sqrt(dx * dx + dy * dy); - distribution[level].minPos += distribution[level].nodeSpacing; - } + // BarnesHut condition + // original condition : s/d < theta = passed === d/s > 1/theta = passed + // calcSize = 1/s --> d * 1/s > 1/theta = passed + if (distance * parentBranch.calcSize > this.constants.physics.barnesHut.theta) { + // duplicate code to reduce function calls to speed up program + if (distance == 0) { + distance = 0.1*Math.random(); + dx = distance; + } + var gravityForce = this.constants.physics.barnesHut.gravitationalConstant * parentBranch.mass * node.options.mass / (distance * distance * distance); + var fx = dx * gravityForce; + var fy = dy * gravityForce; + node.fx += fx; + node.fy += fy; + } + else { + // Did not pass the condition, go into children if available + if (parentBranch.childrenCount == 4) { + this._getForceContribution(parentBranch.children.NW,node); + this._getForceContribution(parentBranch.children.NE,node); + this._getForceContribution(parentBranch.children.SW,node); + this._getForceContribution(parentBranch.children.SE,node); + } + else { // parentBranch must have only one node, if it was empty we wouldnt be here + if (parentBranch.children.data.id != node.id) { // if it is not self + // duplicate code to reduce function calls to speed up program + if (distance == 0) { + distance = 0.5*Math.random(); + dx = distance; } - this._placeBranchNodes(node.edges,node.id,distribution,node.level); + var gravityForce = this.constants.physics.barnesHut.gravitationalConstant * parentBranch.mass * node.options.mass / (distance * distance * distance); + var fx = dx * gravityForce; + var fy = dy * gravityForce; + node.fx += fx; + node.fy += fy; } } } } - - // stabilize the system after positioning. This function calls zoomExtent. - this._stabilize(); }; - /** - * This function get the distribution of levels based on hubsize + * This function constructs the barnesHut tree recursively. It creates the root, splits it and starts placing the nodes. * - * @returns {Object} + * @param nodes + * @param nodeIndices * @private */ - exports._getDistribution = function() { - var distribution = {}; - var nodeId, node, level; + exports._formBarnesHutTree = function(nodes,nodeIndices) { + var node; + var nodeCount = nodeIndices.length; - // we fix Y because the hierarchy is vertical, we fix X so we do not give a node an x position for a second time. - // the fix of X is removed after the x value has been set. - for (nodeId in this.nodes) { - if (this.nodes.hasOwnProperty(nodeId)) { - node = this.nodes[nodeId]; - node.xFixed = true; - node.yFixed = true; - if (this.constants.hierarchicalLayout.direction == "UD" || this.constants.hierarchicalLayout.direction == "DU") { - node.y = this.constants.hierarchicalLayout.levelSeparation*node.level; - } - else { - node.x = this.constants.hierarchicalLayout.levelSeparation*node.level; - } - if (distribution[node.level] === undefined) { - distribution[node.level] = {amount: 0, nodes: {}, minPos:0, nodeSpacing:0}; - } - distribution[node.level].amount += 1; - distribution[node.level].nodes[nodeId] = node; + var minX = Number.MAX_VALUE, + minY = Number.MAX_VALUE, + maxX =-Number.MAX_VALUE, + maxY =-Number.MAX_VALUE; + + // get the range of the nodes + for (var i = 0; i < nodeCount; i++) { + var x = nodes[nodeIndices[i]].x; + var y = nodes[nodeIndices[i]].y; + if (nodes[nodeIndices[i]].options.mass > 0) { + if (x < minX) { minX = x; } + if (x > maxX) { maxX = x; } + if (y < minY) { minY = y; } + if (y > maxY) { maxY = y; } } } + // make the range a square + var sizeDiff = Math.abs(maxX - minX) - Math.abs(maxY - minY); // difference between X and Y + if (sizeDiff > 0) {minY -= 0.5 * sizeDiff; maxY += 0.5 * sizeDiff;} // xSize > ySize + else {minX += 0.5 * sizeDiff; maxX -= 0.5 * sizeDiff;} // xSize < ySize - // determine the largest amount of nodes of all levels - var maxCount = 0; - for (level in distribution) { - if (distribution.hasOwnProperty(level)) { - if (maxCount < distribution[level].amount) { - maxCount = distribution[level].amount; - } + + var minimumTreeSize = 1e-5; + var rootSize = Math.max(minimumTreeSize,Math.abs(maxX - minX)); + var halfRootSize = 0.5 * rootSize; + var centerX = 0.5 * (minX + maxX), centerY = 0.5 * (minY + maxY); + + // construct the barnesHutTree + var barnesHutTree = { + root:{ + centerOfMass: {x:0, y:0}, + mass:0, + range: { + minX: centerX-halfRootSize,maxX:centerX+halfRootSize, + minY: centerY-halfRootSize,maxY:centerY+halfRootSize + }, + size: rootSize, + calcSize: 1 / rootSize, + children: { data:null}, + maxWidth: 0, + level: 0, + childrenCount: 4 } - } + }; + this._splitBranch(barnesHutTree.root); - // set the initial position and spacing of each nodes accordingly - for (level in distribution) { - if (distribution.hasOwnProperty(level)) { - distribution[level].nodeSpacing = (maxCount + 1) * this.constants.hierarchicalLayout.nodeSpacing; - distribution[level].nodeSpacing /= (distribution[level].amount + 1); - distribution[level].minPos = distribution[level].nodeSpacing - (0.5 * (distribution[level].amount + 1) * distribution[level].nodeSpacing); + // place the nodes one by one recursively + for (i = 0; i < nodeCount; i++) { + node = nodes[nodeIndices[i]]; + if (node.options.mass > 0) { + this._placeInTree(barnesHutTree.root,node); } } - return distribution; + // make global + this.barnesHutTree = barnesHutTree }; /** - * this function allocates nodes in levels based on the recursive branching from the largest hubs. + * this updates the mass of a branch. this is increased by adding a node. * - * @param hubsize + * @param parentBranch + * @param node * @private */ - exports._determineLevels = function(hubsize) { - var nodeId, node; + exports._updateBranchMass = function(parentBranch, node) { + var totalMass = parentBranch.mass + node.options.mass; + var totalMassInv = 1/totalMass; - // determine hubs - for (nodeId in this.nodes) { - if (this.nodes.hasOwnProperty(nodeId)) { - node = this.nodes[nodeId]; - if (node.edges.length == hubsize) { - node.level = 0; - } - } - } + parentBranch.centerOfMass.x = parentBranch.centerOfMass.x * parentBranch.mass + node.x * node.options.mass; + parentBranch.centerOfMass.x *= totalMassInv; - // branch from hubs - for (nodeId in this.nodes) { - if (this.nodes.hasOwnProperty(nodeId)) { - node = this.nodes[nodeId]; - if (node.level == 0) { - this._setLevel(1,node.edges,node.id); - } - } - } - }; + parentBranch.centerOfMass.y = parentBranch.centerOfMass.y * parentBranch.mass + node.y * node.options.mass; + parentBranch.centerOfMass.y *= totalMassInv; + parentBranch.mass = totalMass; + var biggestSize = Math.max(Math.max(node.height,node.radius),node.width); + parentBranch.maxWidth = (parentBranch.maxWidth < biggestSize) ? biggestSize : parentBranch.maxWidth; - /** - * Since hierarchical layout does not support: - * - smooth curves (based on the physics), - * - clustering (based on dynamic node counts) - * - * We disable both features so there will be no problems. - * - * @private - */ - exports._changeConstants = function() { - this.constants.clustering.enabled = false; - this.constants.physics.barnesHut.enabled = false; - this.constants.physics.hierarchicalRepulsion.enabled = true; - this._loadSelectedForceSolver(); - if (this.constants.smoothCurves.enabled == true) { - this.constants.smoothCurves.dynamic = false; - } - this._configureSmoothCurves(); }; /** - * This is a recursively called function to enumerate the branches from the largest hubs and place the nodes - * on a X position that ensures there will be no overlap. + * determine in which branch the node will be placed. * - * @param edges - * @param parentId - * @param distribution - * @param parentLevel + * @param parentBranch + * @param node + * @param skipMassUpdate * @private */ - exports._placeBranchNodes = function(edges, parentId, distribution, parentLevel) { - for (var i = 0; i < edges.length; i++) { - var childNode = null; - if (edges[i].toId == parentId) { - childNode = edges[i].from; - } - else { - childNode = edges[i].to; - } + exports._placeInTree = function(parentBranch,node,skipMassUpdate) { + if (skipMassUpdate != true || skipMassUpdate === undefined) { + // update the mass of the branch. + this._updateBranchMass(parentBranch,node); + } - // if a node is conneceted to another node on the same level (or higher (means lower level))!, this is not handled here. - var nodeMoved = false; - if (this.constants.hierarchicalLayout.direction == "UD" || this.constants.hierarchicalLayout.direction == "DU") { - if (childNode.xFixed && childNode.level > parentLevel) { - childNode.xFixed = false; - childNode.x = distribution[childNode.level].minPos; - nodeMoved = true; - } + if (parentBranch.children.NW.range.maxX > node.x) { // in NW or SW + if (parentBranch.children.NW.range.maxY > node.y) { // in NW + this._placeInRegion(parentBranch,node,"NW"); } - else { - if (childNode.yFixed && childNode.level > parentLevel) { - childNode.yFixed = false; - childNode.y = distribution[childNode.level].minPos; - nodeMoved = true; - } + else { // in SW + this._placeInRegion(parentBranch,node,"SW"); } - - if (nodeMoved == true) { - distribution[childNode.level].minPos += distribution[childNode.level].nodeSpacing; - if (childNode.edges.length > 1) { - this._placeBranchNodes(childNode.edges,childNode.id,distribution,childNode.level); - } + } + else { // in NE or SE + if (parentBranch.children.NW.range.maxY > node.y) { // in NE + this._placeInRegion(parentBranch,node,"NE"); + } + else { // in SE + this._placeInRegion(parentBranch,node,"SE"); } } }; /** - * this function is called recursively to enumerate the barnches of the largest hubs and give each node a level. + * actually place the node in a region (or branch) * - * @param level - * @param edges - * @param parentId + * @param parentBranch + * @param node + * @param region * @private */ - exports._setLevel = function(level, edges, parentId) { - for (var i = 0; i < edges.length; i++) { - var childNode = null; - if (edges[i].toId == parentId) { - childNode = edges[i].from; - } - else { - childNode = edges[i].to; - } - if (childNode.level == -1 || childNode.level > level) { - childNode.level = level; - if (edges.length > 1) { - this._setLevel(level+1, childNode.edges, childNode.id); + exports._placeInRegion = function(parentBranch,node,region) { + switch (parentBranch.children[region].childrenCount) { + case 0: // place node here + parentBranch.children[region].children.data = node; + parentBranch.children[region].childrenCount = 1; + this._updateBranchMass(parentBranch.children[region],node); + break; + case 1: // convert into children + // if there are two nodes exactly overlapping (on init, on opening of cluster etc.) + // we move one node a pixel and we do not put it in the tree. + if (parentBranch.children[region].children.data.x == node.x && + parentBranch.children[region].children.data.y == node.y) { + node.x += Math.random(); + node.y += Math.random(); } - } + else { + this._splitBranch(parentBranch.children[region]); + this._placeInTree(parentBranch.children[region],node); + } + break; + case 4: // place in branch + this._placeInTree(parentBranch.children[region],node); + break; } }; /** - * Unfix nodes + * this function splits a branch into 4 sub branches. If the branch contained a node, we place it in the subbranch + * after the split is complete. * + * @param parentBranch * @private */ - exports._restoreNodes = function() { - for (var nodeId in this.nodes) { - if (this.nodes.hasOwnProperty(nodeId)) { - this.nodes[nodeId].xFixed = false; - this.nodes[nodeId].yFixed = false; - } - } - }; - - -/***/ }, -/* 61 */ -/***/ function(module, exports, __webpack_require__) { - - /** - * Canvas shapes used by Network - */ - if (typeof CanvasRenderingContext2D !== 'undefined') { - - /** - * Draw a circle shape - */ - CanvasRenderingContext2D.prototype.circle = function(x, y, r) { - this.beginPath(); - this.arc(x, y, r, 0, 2*Math.PI, false); - }; - - /** - * Draw a square shape - * @param {Number} x horizontal center - * @param {Number} y vertical center - * @param {Number} r size, width and height of the square - */ - CanvasRenderingContext2D.prototype.square = function(x, y, r) { - this.beginPath(); - this.rect(x - r, y - r, r * 2, r * 2); - }; - - /** - * Draw a triangle shape - * @param {Number} x horizontal center - * @param {Number} y vertical center - * @param {Number} r radius, half the length of the sides of the triangle - */ - CanvasRenderingContext2D.prototype.triangle = function(x, y, r) { - // http://en.wikipedia.org/wiki/Equilateral_triangle - this.beginPath(); - - var s = r * 2; - var s2 = s / 2; - var ir = Math.sqrt(3) / 6 * s; // radius of inner circle - var h = Math.sqrt(s * s - s2 * s2); // height - - this.moveTo(x, y - (h - ir)); - this.lineTo(x + s2, y + ir); - this.lineTo(x - s2, y + ir); - this.lineTo(x, y - (h - ir)); - this.closePath(); - }; - - /** - * Draw a triangle shape in downward orientation - * @param {Number} x horizontal center - * @param {Number} y vertical center - * @param {Number} r radius - */ - CanvasRenderingContext2D.prototype.triangleDown = function(x, y, r) { - // http://en.wikipedia.org/wiki/Equilateral_triangle - this.beginPath(); - - var s = r * 2; - var s2 = s / 2; - var ir = Math.sqrt(3) / 6 * s; // radius of inner circle - var h = Math.sqrt(s * s - s2 * s2); // height - - this.moveTo(x, y + (h - ir)); - this.lineTo(x + s2, y - ir); - this.lineTo(x - s2, y - ir); - this.lineTo(x, y + (h - ir)); - this.closePath(); - }; - - /** - * Draw a star shape, a star with 5 points - * @param {Number} x horizontal center - * @param {Number} y vertical center - * @param {Number} r radius, half the length of the sides of the triangle - */ - CanvasRenderingContext2D.prototype.star = function(x, y, r) { - // http://www.html5canvastutorials.com/labs/html5-canvas-star-spinner/ - this.beginPath(); + exports._splitBranch = function(parentBranch) { + // if the branch is shaded with a node, replace the node in the new subset. + var containedNode = null; + if (parentBranch.childrenCount == 1) { + containedNode = parentBranch.children.data; + parentBranch.mass = 0; parentBranch.centerOfMass.x = 0; parentBranch.centerOfMass.y = 0; + } + parentBranch.childrenCount = 4; + parentBranch.children.data = null; + this._insertRegion(parentBranch,"NW"); + this._insertRegion(parentBranch,"NE"); + this._insertRegion(parentBranch,"SW"); + this._insertRegion(parentBranch,"SE"); - for (var n = 0; n < 10; n++) { - var radius = (n % 2 === 0) ? r * 1.3 : r * 0.5; - this.lineTo( - x + radius * Math.sin(n * 2 * Math.PI / 10), - y - radius * Math.cos(n * 2 * Math.PI / 10) - ); - } + if (containedNode != null) { + this._placeInTree(parentBranch,containedNode); + } + }; - this.closePath(); - }; - /** - * http://stackoverflow.com/questions/1255512/how-to-draw-a-rounded-rectangle-on-html-canvas - */ - CanvasRenderingContext2D.prototype.roundRect = function(x, y, w, h, r) { - var r2d = Math.PI/180; - if( w - ( 2 * r ) < 0 ) { r = ( w / 2 ); } //ensure that the radius isn't too large for x - if( h - ( 2 * r ) < 0 ) { r = ( h / 2 ); } //ensure that the radius isn't too large for y - this.beginPath(); - this.moveTo(x+r,y); - this.lineTo(x+w-r,y); - this.arc(x+w-r,y+r,r,r2d*270,r2d*360,false); - this.lineTo(x+w,y+h-r); - this.arc(x+w-r,y+h-r,r,0,r2d*90,false); - this.lineTo(x+r,y+h); - this.arc(x+r,y+h-r,r,r2d*90,r2d*180,false); - this.lineTo(x,y+r); - this.arc(x+r,y+r,r,r2d*180,r2d*270,false); - }; + /** + * This function subdivides the region into four new segments. + * Specifically, this inserts a single new segment. + * It fills the children section of the parentBranch + * + * @param parentBranch + * @param region + * @param parentRange + * @private + */ + exports._insertRegion = function(parentBranch, region) { + var minX,maxX,minY,maxY; + var childSize = 0.5 * parentBranch.size; + switch (region) { + case "NW": + minX = parentBranch.range.minX; + maxX = parentBranch.range.minX + childSize; + minY = parentBranch.range.minY; + maxY = parentBranch.range.minY + childSize; + break; + case "NE": + minX = parentBranch.range.minX + childSize; + maxX = parentBranch.range.maxX; + minY = parentBranch.range.minY; + maxY = parentBranch.range.minY + childSize; + break; + case "SW": + minX = parentBranch.range.minX; + maxX = parentBranch.range.minX + childSize; + minY = parentBranch.range.minY + childSize; + maxY = parentBranch.range.maxY; + break; + case "SE": + minX = parentBranch.range.minX + childSize; + maxX = parentBranch.range.maxX; + minY = parentBranch.range.minY + childSize; + maxY = parentBranch.range.maxY; + break; + } - /** - * http://stackoverflow.com/questions/2172798/how-to-draw-an-oval-in-html5-canvas - */ - CanvasRenderingContext2D.prototype.ellipse = function(x, y, w, h) { - var kappa = .5522848, - ox = (w / 2) * kappa, // control point offset horizontal - oy = (h / 2) * kappa, // control point offset vertical - xe = x + w, // x-end - ye = y + h, // y-end - xm = x + w / 2, // x-middle - ym = y + h / 2; // y-middle - this.beginPath(); - this.moveTo(x, ym); - this.bezierCurveTo(x, ym - oy, xm - ox, y, xm, y); - this.bezierCurveTo(xm + ox, y, xe, ym - oy, xe, ym); - this.bezierCurveTo(xe, ym + oy, xm + ox, ye, xm, ye); - this.bezierCurveTo(xm - ox, ye, x, ym + oy, x, ym); + parentBranch.children[region] = { + centerOfMass:{x:0,y:0}, + mass:0, + range:{minX:minX,maxX:maxX,minY:minY,maxY:maxY}, + size: 0.5 * parentBranch.size, + calcSize: 2 * parentBranch.calcSize, + children: {data:null}, + maxWidth: 0, + level: parentBranch.level+1, + childrenCount: 0 }; + }; + /** + * This function is for debugging purposed, it draws the tree. + * + * @param ctx + * @param color + * @private + */ + exports._drawTree = function(ctx,color) { + if (this.barnesHutTree !== undefined) { - /** - * http://stackoverflow.com/questions/2172798/how-to-draw-an-oval-in-html5-canvas - */ - CanvasRenderingContext2D.prototype.database = function(x, y, w, h) { - var f = 1/3; - var wEllipse = w; - var hEllipse = h * f; - - var kappa = .5522848, - ox = (wEllipse / 2) * kappa, // control point offset horizontal - oy = (hEllipse / 2) * kappa, // control point offset vertical - xe = x + wEllipse, // x-end - ye = y + hEllipse, // y-end - xm = x + wEllipse / 2, // x-middle - ym = y + hEllipse / 2, // y-middle - ymb = y + (h - hEllipse/2), // y-midlle, bottom ellipse - yeb = y + h; // y-end, bottom ellipse + ctx.lineWidth = 1; - this.beginPath(); - this.moveTo(xe, ym); + this._drawBranch(this.barnesHutTree.root,ctx,color); + } + }; - this.bezierCurveTo(xe, ym + oy, xm + ox, ye, xm, ye); - this.bezierCurveTo(xm - ox, ye, x, ym + oy, x, ym); - this.bezierCurveTo(x, ym - oy, xm - ox, y, xm, y); - this.bezierCurveTo(xm + ox, y, xe, ym - oy, xe, ym); + /** + * This function is for debugging purposes. It draws the branches recursively. + * + * @param branch + * @param ctx + * @param color + * @private + */ + exports._drawBranch = function(branch,ctx,color) { + if (color === undefined) { + color = "#FF0000"; + } - this.lineTo(xe, ymb); + if (branch.childrenCount == 4) { + this._drawBranch(branch.children.NW,ctx); + this._drawBranch(branch.children.NE,ctx); + this._drawBranch(branch.children.SE,ctx); + this._drawBranch(branch.children.SW,ctx); + } + ctx.strokeStyle = color; + ctx.beginPath(); + ctx.moveTo(branch.range.minX,branch.range.minY); + ctx.lineTo(branch.range.maxX,branch.range.minY); + ctx.stroke(); - this.bezierCurveTo(xe, ymb + oy, xm + ox, yeb, xm, yeb); - this.bezierCurveTo(xm - ox, yeb, x, ymb + oy, x, ymb); + ctx.beginPath(); + ctx.moveTo(branch.range.maxX,branch.range.minY); + ctx.lineTo(branch.range.maxX,branch.range.maxY); + ctx.stroke(); - this.lineTo(x, ym); - }; + ctx.beginPath(); + ctx.moveTo(branch.range.maxX,branch.range.maxY); + ctx.lineTo(branch.range.minX,branch.range.maxY); + ctx.stroke(); + ctx.beginPath(); + ctx.moveTo(branch.range.minX,branch.range.maxY); + ctx.lineTo(branch.range.minX,branch.range.minY); + ctx.stroke(); - /** - * Draw an arrow point (no line) + /* + if (branch.mass > 0) { + ctx.circle(branch.centerOfMass.x, branch.centerOfMass.y, 3*branch.mass); + ctx.stroke(); + } */ - CanvasRenderingContext2D.prototype.arrow = function(x, y, angle, length) { - // tail - var xt = x - length * Math.cos(angle); - var yt = y - length * Math.sin(angle); - - // inner tail - // TODO: allow to customize different shapes - var xi = x - length * 0.9 * Math.cos(angle); - var yi = y - length * 0.9 * Math.sin(angle); - - // left - var xl = xt + length / 3 * Math.cos(angle + 0.5 * Math.PI); - var yl = yt + length / 3 * Math.sin(angle + 0.5 * Math.PI); - - // right - var xr = xt + length / 3 * Math.cos(angle - 0.5 * Math.PI); - var yr = yt + length / 3 * Math.sin(angle - 0.5 * Math.PI); + }; - this.beginPath(); - this.moveTo(x, y); - this.lineTo(xl, yl); - this.lineTo(xi, yi); - this.lineTo(xr, yr); - this.closePath(); - }; - /** - * Sets up the dashedLine functionality for drawing - * Original code came from http://stackoverflow.com/questions/4576724/dotted-stroke-in-canvas - * @author David Jordan - * @date 2012-08-08 - */ - CanvasRenderingContext2D.prototype.dashedLine = function(x,y,x2,y2,dashArray){ - if (!dashArray) dashArray=[10,5]; - if (dashLength==0) dashLength = 0.001; // Hack for Safari - var dashCount = dashArray.length; - this.moveTo(x, y); - var dx = (x2-x), dy = (y2-y); - var slope = dy/dx; - var distRemaining = Math.sqrt( dx*dx + dy*dy ); - var dashIndex=0, draw=true; - while (distRemaining>=0.1){ - var dashLength = dashArray[dashIndex++%dashCount]; - if (dashLength > distRemaining) dashLength = distRemaining; - var xStep = Math.sqrt( dashLength*dashLength / (1 + slope*slope) ); - if (dx<0) xStep = -xStep; - x += xStep; - y += slope*xStep; - this[draw ? 'lineTo' : 'moveTo'](x,y); - distRemaining -= dashLength; - draw = !draw; - } - }; +/***/ }, +/* 61 */ +/***/ function(module, exports, __webpack_require__) { - // TODO: add diamond shape + module.exports = function(module) { + if(!module.webpackPolyfill) { + module.deprecate = function() {}; + module.paths = []; + // module.parent = undefined by default + module.children = []; + module.webpackPolyfill = 1; + } + return module; } diff --git a/dist/vis.map b/dist/vis.map index a641baab..1a5ce27b 100644 --- a/dist/vis.map +++ b/dist/vis.map @@ -1 +1 @@ -{"version":3,"file":"vis.map","sources":["./dist/vis.js"],"names":["root","factory","exports","module","define","amd","this","modules","__webpack_require__","moduleId","installedModules","id","loaded","call","m","c","p","util","DOMutil","DataSet","DataView","Graph3d","graph3d","Camera","Filter","Point2d","Point3d","Slider","StepNumber","Timeline","Graph2d","timeline","DataStep","Range","stack","TimeStep","components","items","Item","ItemBox","ItemPoint","ItemRange","Component","CurrentTime","CustomTime","DataAxis","GraphGroup","Group","ItemSet","Legend","LineGraph","TimeAxis","Network","network","Edge","Groups","Images","Node","Popup","dotparser","gephiParser","Graph","Error","moment","hammer","prepareElements","JSONcontainer","elementType","hasOwnProperty","redundant","used","cleanupElements","i","length","parentNode","removeChild","getSVGElement","svgContainer","element","shift","document","createElementNS","appendChild","push","getDOMElement","DOMContainer","createElement","drawPoint","x","y","group","point","options","drawPoints","style","setAttributeNS","size","className","drawBar","width","height","rect","isNumber","object","Number","isString","String","isDate","Date","match","ASPDateRegex","exec","isNaN","parse","isDataTable","google","visualization","DataTable","randomUUID","S4","Math","floor","random","toString","extend","a","len","arguments","other","prop","selectiveExtend","props","Array","isArray","selectiveDeepExtend","b","TypeError","constructor","Object","undefined","deepExtend","selectiveNotDeepExtend","indexOf","equalArray","convert","type","Boolean","valueOf","isMoment","toDate","getType","toISOString","value","getAbsoluteLeft","elem","getBoundingClientRect","left","window","pageXOffset","getAbsoluteTop","top","pageYOffset","addClassName","classes","split","join","removeClassName","index","splice","forEach","callback","toArray","array","updateProperty","key","addEventListener","action","listener","useCapture","navigator","userAgent","attachEvent","removeEventListener","detachEvent","preventDefault","event","returnValue","getTarget","target","srcElement","nodeType","option","asBoolean","defaultValue","asNumber","asString","asSize","asElement","GiveDec","Hex","Value","eval","GiveHex","Dec","parseColor","color","isValidRGB","rgb","substr","RGBToHex","isValidHex","hsv","hexToHSV","lighterColorHSV","h","s","v","min","darkerColorHSV","darkerColorHex","HSVToHex","lighterColorHex","background","border","highlight","hover","hexToRGB","hex","replace","toUpperCase","substring","d","e","f","r","g","red","green","blue","RGBToHSV","minRGB","maxRGB","max","hue","saturation","HSVToRGB","q","t","isOk","test","selectiveBridgeObject","fields","referenceObject","objectTo","create","bridgeObject","mergeOptions","mergeTarget","enabled","binarySearch","orderedItems","range","field","field2","maxIterations","iteration","found","low","high","newLow","newHigh","guess","isVisible","start","console","log","binarySearchGeneric","sidePreference","newGuess","prevValue","nextValue","data","_options","_data","_fieldId","fieldId","_type","_subscribers","add","prototype","on","subscribers","subscribe","off","filter","unsubscribe","_trigger","params","senderId","concat","subscriber","addedIds","me","_addItem","columns","_getColumnNames","row","rows","getNumberOfRows","item","col","cols","getValue","update","updatedIds","addOrUpdate","_updateItem","get","ids","firstType","returnType","allowedValues","itemId","_getItem","order","_sort","_filterFields","_appendRow","result","getIds","getDataSet","map","mappedItems","filteredItem","name","sort","av","bv","remove","removedId","removedIds","_remove","clear","keys","maxField","itemField","minField","distinct","values","fieldType","count","exists","types","raw","converted","JSON","stringify","dataTable","getNumberOfColumns","getColumnId","getColumnLabel","addRow","setValue","_ids","_onEvent","apply","setData","viewOptions","getArguments","defaultFilter","dataSet","added","updated","removed","container","SyntaxError","containerElement","margin","defaultXCenter","defaultYCenter","xLabel","yLabel","zLabel","filterLabel","legendLabel","STYLE","DOT","showPerspective","showGrid","keepAspectRatio","showShadow","showGrayBottom","showTooltip","verticalRatio","animationInterval","animationPreload","camera","eye","dataPoints","colX","colY","colZ","colValue","colFilter","xMin","xStep","xMax","yMin","yStep","yMax","zMin","zStep","zMax","valueMin","valueMax","xBarWidth","yBarWidth","colorAxis","colorGrid","colorDot","colorDotBorder","setOptions","Emitter","_setScale","scale","z","xCenter","yCenter","zCenter","setArmLocation","_convert3Dto2D","point3d","translation","_convertPointToTranslation","_convertTranslationToScreen","ax","ay","az","cx","getCameraLocation","cy","cz","sinTx","sin","getCameraRotation","cosTx","cos","sinTy","cosTy","sinTz","cosTz","dx","dy","dz","bx","by","ex","ey","ez","getArmLength","xcenter","frame","canvas","clientWidth","ycenter","_setBackgroundColor","backgroundColor","fill","stroke","strokeWidth","borderColor","borderWidth","borderStyle","BAR","BARCOLOR","BARSIZE","DOTLINE","DOTCOLOR","DOTSIZE","GRID","LINE","SURFACE","_getStyleNumber","styleName","_determineColumnIndexes","counter","column","getDistinctValues","distinctValues","getColumnRange","minMax","_dataInitialize","rawData","_onChange","dataFilter","setOnLoadCallback","redraw","withBars","defaultXBarWidth","dataX","defaultYBarWidth","dataY","xRange","defaultXMin","defaultXMax","defaultXStep","yRange","defaultYMin","defaultYMax","defaultYStep","zRange","defaultZMin","defaultZMax","defaultZStep","valueRange","defaultValueMin","defaultValueMax","_getDataPoints","sortNumber","obj","dataMatrix","xIndex","yIndex","trans","screen","bottom","pointRight","pointTop","pointCross","hasChildNodes","firstChild","position","overflow","noCanvas","fontWeight","padding","innerHTML","onmousedown","_onMouseDown","ontouchstart","_onTouchStart","onmousewheel","_onWheel","ontooltip","_onTooltip","onkeydown","setSize","_resizeCanvas","clientHeight","animationStart","slider","play","animationStop","stop","_resizeCenter","charAt","parseFloat","setCameraPosition","pos","horizontal","vertical","setArmRotation","distance","setArmLength","getCameraPosition","getArmRotation","_readData","_redrawFilter","animationAutoStart","cameraPosition","styleNumber","tooltip","showAnimationControls","_redrawSlider","_redrawClear","_redrawAxis","_redrawDataGrid","_redrawDataLine","_redrawDataBar","_redrawDataDot","_redrawInfo","_redrawLegend","ctx","getContext","clearRect","widthMin","widthMax","dotSize","right","lineWidth","font","ymin","ymax","_hsv2rgb","strokeStyle","beginPath","moveTo","lineTo","strokeRect","fillStyle","closePath","gridLineLen","step","getCurrent","next","end","textAlign","textBaseline","fillText","label","visible","setValues","setPlayInterval","onchange","getIndex","selectValue","setOnChangeCallback","lineStyle","getLabel","getSelectedValue","from","to","prettyStep","text","xText","yText","zText","offset","xOffset","yOffset","xMin2d","xMax2d","gridLenX","gridLenY","textMargin","armAngle","H","S","V","R","G","B","C","Hi","X","abs","parseInt","cross","topSideVisible","zAvg","transBottom","dist","sortDepth","aDiff","subtract","bDiff","crossproduct","crossProduct","radius","arc","PI","j","surface","corners","xWidth","yWidth","surfaces","center","avg","transCenter","diff","leftButtonDown","_onMouseUp","which","button","touchDown","startMouseX","getMouseX","startMouseY","getMouseY","startStart","startEnd","startArmRotation","cursor","onmousemove","_onMouseMove","onmouseup","diffX","diffY","horizontalNew","verticalNew","snapAngle","snapValue","round","parameters","emit","delay","mouseX","mouseY","tooltipTimeout","clearTimeout","_hideTooltip","dataPoint","_dataPointFromXY","_showTooltip","setTimeout","ontouchmove","_onTouchMove","ontouchend","_onTouchEnd","delta","wheelDelta","detail","oldLength","newLength","_insideTriangle","triangle","sign","as","bs","cs","distMax","closestDataPoint","closestDist","triangle1","triangle2","distX","distY","sqrt","content","line","dot","dom","borderRadius","boxShadow","borderLeft","contentWidth","offsetWidth","contentHeight","offsetHeight","lineHeight","dotWidth","dotHeight","clientX","targetTouches","clientY","armLocation","armRotation","armLength","cameraLocation","cameraRotation","calculateCameraOrientation","rot","graph","onLoadCallback","loadInBackground","isLoaded","getLoadedProgress","getColumn","getValues","dataView","progress","sub","sum","prev","bar","MozBorderRadius","slide","onclick","togglePlay","onChangeCallback","playTimeout","playInterval","playLoop","setIndex","playNext","interval","clearInterval","getPlayInterval","setPlayLoop","doLoop","onChange","indexToLeft","startClientX","startSlideX","leftToIndex","_start","_end","_step","precision","_current","setRange","setStep","calculatePrettyStep","log10","LN10","step1","pow","step2","step5","toPrecision","getStep","coreProp","Core","defaultOptions","autoResize","orientation","maxHeight","minHeight","_create","body","domProps","emitter","bind","snap","toScreen","_toScreen","toGlobalScreen","_toGlobalScreen","toTime","_toTime","toGlobalTime","_toGlobalTime","timeAxis","currentTime","customTime","itemSet","itemsData","groupsData","setItems","_initAutoResize","component","newDataSet","initialLoad","fit","setWindow","setGroups","groups","setSelection","getSelection","getItemRange","dataset","minItem","maxStartItem","maxEndItem","linegraph","getLegend","groupId","isGroupVisible","minimumStep","containerHeight","forcedStepSize","current","autoScale","stepIndex","marginStart","marginEnd","majorSteps","minorSteps","setMinimumStep","setFirst","safeSize","minimumStepValue","orderOfMagnitude","minorStepIdx","magnitudefactor","solutionFound","stepSize","first","niceStart","niceEnd","roundToMinor","marginRange","rounded","hasNext","previous","slice","isMajor","now","hours","minutes","seconds","milliseconds","clone","direction","moveable","zoomable","zoomMin","zoomMax","touch","_onDragStart","_onDrag","_onDragEnd","_onHold","_onMouseWheel","_onTouch","_onPinch","validateDirection","getPointer","pageX","pageY","hammerUtil","changed","_applyRange","newStart","newEnd","getRange","conversion","allowDragging","gesture","deltaX","deltaY","diffRange","fakeGesture","pointer","pointerDate","_pointerToDate","zoom","touches","initDate","move","EPSILON","orderByStart","orderByEnd","aTime","bTime","force","iMax","axis","collidingItem","jj","collision","nostack","SCALE","DAY","MILLISECOND","SECOND","MINUTE","HOUR","WEEKDAY","MONTH","YEAR","setFullYear","getFullYear","setMonth","setDate","setHours","setMinutes","setSeconds","setMilliseconds","getMilliseconds","getSeconds","getMinutes","getHours","getDate","getMonth","setScale","newScale","newStep","setAutoScale","enable","stepYear","stepMonth","stepDay","stepHour","stepMinute","stepSecond","stepMillisecond","date","year","getLabelMinor","format","getLabelMajor","showCurrentTime","destroy","parent","backgroundVertical","title","currentTimeTimer","_isResized","resized","_previousWidth","_previousHeight","showCustomTime","eventParams","Hammer","drag","prevent_default","setCustomTime","time","getCustomTime","dragging","stopPropagation","svg","showMinorLabels","showMajorLabels","icons","majorLinesOffset","minorLinesOffset","labelOffsetX","labelOffsetY","iconWidth","linegraphSVG","DOMelements","lines","labels","conversionFactor","minWidth","stepPixels","stepPixelsForced","lineOffset","master","svgElements","amountOfGroups","addGroup","graphOptions","updateGroup","removeGroup","hide","show","lineContainer","display","_redrawGroupIcons","iconHeight","iconOffset","drawIcon","backgroundHorizontal","changeCalled","activeGroups","_calculateCharSize","minorLabelHeight","minorCharHeight","majorLabelHeight","majorCharHeight","minorLineWidth","minorLineHeight","majorLineWidth","majorLineHeight","_redrawLabels","amountOfSteps","stepDifference","valueAtZero","marginStartPos","maxLabelSize","_redrawLabel","_redrawLine","characterHeight","largestWidth","majorCharWidth","minorCharWidth","convertValue","invertedValue","convertedValue","textMinor","createTextNode","measureCharMinor","textMajor","measureCharMajor","groupsUsingDefaultStyles","usingDefaultStyle","zeroPosition","setZeroPosition","catmullRom","parametrization","alpha","SVGcontainer","path","fillPath","fillHeight","outline","shaded","barWidth","bar1Height","bar2Height","icon","yAxisOrientation","visibleItems","byStart","byEnd","inner","foreground","marker","visibility","Element","getLabelWidth","restack","_updateVisibleItems","markerHeight","lastMarkerHeight","dirty","displayed","offsetTop","offsetLeft","ii","repositionY","labelSet","setParent","_checkIfVisible","removeFromDataSet","removeItem","_constructByEndArray","endArray","initialPosByStart","newVisibleItems","initialPosByEnd","_checkIfInvisible","repositionX","align","groupOrder","selectable","editable","updateTime","onAdd","onUpdate","onMove","onRemove","itemOptions","itemListeners","_onAdd","_onUpdate","_onRemove","groupListeners","_onAddGroups","_onUpdateGroups","_onRemoveGroups","groupIds","selection","stackDirty","touchParams","_moveToGroup","oldGroup","UNGROUPED","box","_updateUngrouped","centerContainer","_onSelectItem","_onMultiSelectItem","_onAddItem","addCallback","fn","Function","markDirty","unselect","select","getVisibleItems","rawVisibleItems","_deselect","_orderGroups","visibleInterval","zoomed","lastVisibleInterval","lastWidth","firstGroup","_firstGroup","firstMargin","nonFirstMargin","groupMargin","groupResized","firstGroupIndex","firstGroupId","ungrouped","getLabelSet","oldItemsData","getItems","_order","getGroups","itemData","_removeItem","groupData","groupOptions","oldGroupId","itemFromTarget","selected","dragLeftItem","dragRightItem","itemProps","groupFromTarget","changes","ctrlKey","srcEvent","shiftKey","oldSelection","newSelection","xAbs","newItem","itemSetFromTarget","side","iconSize","iconSpacing","textArea","drawLegendIcons","getComputedStyle","paddingTop","defaultGroup","sampling","graphHeight","barChart","allowOverlap","dataAxis","legend","lastStart","rangePerPixelInv","_updateGraph","yAxisLeft","yAxisRight","legendLeft","legendRight","_updateAllGroupData","_updateGroup","groupsContent","ungroupedCounter","preprocessedGroup","preprocessedGroupData","processedGroupData","groupRanges","minDate","maxDate","_preprocessData","_updateYAxis","_convertYvalues","_drawLineGraph","_drawBarGraph","minVal","maxVal","yAxisLeftUsed","yAxisRightUsed","minLeft","minRight","maxLeft","maxRight","_toggleAxisVisiblity","drawIcons","axisUsed","coreDistance","intersections","amount","resolved","drawData","_getSafeDrawData","nextKey","prevKey","_drawPoints","slots","total","slot","svgHeight","_catmullRom","_linear","dFill","datapoints","xValue","yValue","extractedData","increment","amountOfPoints","xDistance","pointsPerPixel","ceil","_catmullRomUniform","p0","p1","p2","p3","bp1","bp2","normalization","d1","d2","d3","A","N","M","d3powA","d2powA","d3pow2A","d2pow2A","d1pow2A","d1powA","majorLines","majorTexts","minorLines","minorTexts","lineTop","parentChanged","foregroundNextSibling","nextSibling","backgroundNextSibling","_repaintLabels","insertBefore","xFirstMajorLabel","cur","_repaintMinorText","_repaintMajorText","_repaintMajorLine","_repaintMinorLine","leftTime","leftText","widthText","arr","pop","childNodes","nodeValue","_repaintDeleteButton","anchor","deleteButton","itemSetHeight","marginLeft","baseClassName","_repaintDragLeft","_repaintDragRight","contentLeft","parentWidth","boxWidth","dragLeft","dragRight","_initializeMixinLoaders","renderRefreshRate","renderTimestep","renderTime","maxPhysicsTicksPerRender","physicsDiscreteStepsize","initializing","triggerFunctions","edit","editEdge","connect","del","nodes","mass","radiusMin","radiusMax","shape","image","fixed","fontColor","fontSize","fontFace","level","highlightColor","edges","widthSelectionMultiplier","hoverWidth","fontFill","arrowScaleFactor","dash","gap","altLength","inheritColor","configurePhysics","physics","barnesHut","theta","gravitationalConstant","centralGravity","springLength","springConstant","damping","repulsion","nodeDistance","hierarchicalRepulsion","clustering","initialMaxNodes","clusterThreshold","reduceToNodes","chainThreshold","clusterEdgeThreshold","sectorThreshold","screenSizeThreshold","fontSizeMultiplier","maxFontSize","forceAmplification","distanceAmplification","edgeGrowth","nodeScaling","maxNodeSizeIncrements","activeAreaBoxSize","clusterLevelDifference","navigation","keyboard","speed","dataManipulation","initiallyVisible","hierarchicalLayout","levelSeparation","nodeSpacing","freezeForStabilization","smoothCurves","dynamic","roundness","dynamicSmoothCurves","maxVelocity","minVelocity","stabilize","stabilizationIterations","link","editNode","back","addDescription","linkDescription","editEdgeDescription","addError","linkError","editError","editBoundError","deleteError","deleteClusterError","dragNetwork","dragNodes","hideEdgesOnDrag","hideNodesOnDrag","constants","hoverObj","controlNodesActive","images","setOnloadCallback","_redraw","xIncrement","yIncrement","zoomIncrement","_loadPhysicsSystem","_loadSectorSystem","_loadClusterSystem","_loadSelectionSystem","_loadHierarchySystem","_setTranslation","freezeSimulation","cachedFunctions","calculationNodes","calculationNodeIndices","nodeIndices","canvasTopLeft","canvasBottomRight","pointerPosition","areaCenter","previousScale","nodesData","edgesData","nodesListeners","_addNodes","_updateNodes","_removeNodes","edgesListeners","_addEdges","_updateEdges","_removeEdges","moving","timer","_setupHierarchicalLayout","zoomExtent","startWithClustering","mousetrap","MixinLoader","_getScriptPath","scripts","getElementsByTagName","src","_getRange","node","minY","maxY","minX","maxX","nodeId","_findCenter","_centerNetwork","initialZoom","disableStart","zoomLevel","numberOfNodes","factor","yDistance","xZoomLevel","yZoomLevel","_updateNodeIndexList","_clearNodeIndexList","idx","dotData","DOTToGraph","gephi","gephiData","parseGephi","_setNodes","_setEdges","_putDataInSector","_stabilize","onEdit","onEditEdge","onConnect","onDelete","editMode","newColorObj","groupname","_loadNavigationControls","_loadManipulationSystem","_configureSmoothCurves","_createKeyBinds","pinch","_onTap","_onDoubleTap","_onRelease","_onMouseMoveTitle","reset","_moveUp","_yStopMoving","_moveDown","_moveLeft","_xStopMoving","_moveRight","_zoomIn","_stopZoom","_zoomOut","_createManipulatorBar","_deleteSelected","_getPointer","pinched","_getScale","_handleTouch","_handleDragStart","_getNodeAt","_getTranslation","isSelected","_selectObject","objectId","selectionObj","xFixed","yFixed","_handleOnDrag","_XconvertDOMtoCanvas","_XconvertCanvasToDOM","_YconvertDOMtoCanvas","_YconvertCanvasToDOM","_handleTap","_handleDoubleTap","_handleOnHold","_handleOnRelease","_zoom","scaleOld","preScaleDragPointer","DOMtoCanvas","scaleFrac","tx","ty","updateClustersDefault","postScaleDragPointer","canvasToDOM","popupObj","_checkHidePopup","checkShow","_checkShowPopup","popupTimer","edgeId","_getEdgeAt","_hoverObject","_blurObject","lastPopupNode","getTitle","isOverlappingWith","edge","connected","popup","setPosition","setText","manipulationDiv","navigationDivs","oldNodesData","_updateSelection","angle","_resetLevels","_updateCalculationNodes","_reconnectEdges","_updateValueRange","updateLabels","setProperties","properties","oldEdgesData","oldEdge","disconnect","showInternalIds","_createBezierNodes","via","sectors","setValueRange","w","save","translate","_doInAllSectors","restore","offsetX","offsetY","_drawNodes","alwaysShow","setScaleAndPos","inArea","draw","sMax","_drawEdges","_drawControlNodes","_freezeDefinedNodes","_physicsTick","_restoreFrozenNodes","iterations","fixedData","_isMoving","vmin","isMoving","_discreteStepNodes","nodesPresent","discreteStepLimited","discreteStep","vminCorrected","_doInAllActiveSectors","_doInSupportSector","_animationStep","_handleNavigation","calculationTime","maxSteps","timeRequired","requestAnimationFrame","mozRequestAnimationFrame","webkitRequestAnimationFrame","msRequestAnimationFrame","ua","toLowerCase","requiresTimeout","toggleFreeze","parentEdgeId","internalMultiplier","positionBezierNode","mixin","storePosition","dataArray","allowedToMoveX","allowedToMoveY","focusOnNode","nodePosition","requiredScale","canvasCenter","distanceFromCenter","networkConstants","fromId","toId","widthSelected","originalFromId","originalToId","widthFixed","lengthFixed","controlNodesEnabled","controlNodes","positions","connectedNode","_drawLine","_drawArrow","_drawArrowCenter","_drawDashLine","attachEdge","detachEdge","xFrom","yFrom","xTo","yTo","xObj","yObj","_getDistanceToEdge","_getColor","colorObj","_getLineWidth","_line","midpointX","midpointY","_pointOnLine","_label","resize","_circle","_pointOnCircle","networkScaleInv","_getViaCoordinates","xVia","yVia","quadraticCurveTo","measureText","fillRect","mozDash","setLineDash","pattern","lineDashOffset","mozDashOffset","lineCap","dashedLine","percentage","atan2","arrow","edgeSegmentLength","fromBorderDist","distanceToBorder","fromBorderPoint","toBorderDist","toBorderPoint","x1","y1","x2","y2","x3","y3","lastX","lastY","minDistance","_getDistanceToLine","px","py","something","u","nodeIdFrom","nodeIdTo","getControlNodePositions","_enableControlNodes","_disableControlNodes","_getSelectedControlNode","fromDistance","toDistance","_restoreControlNodes","defaultIndex","DEFAULT","load","url","img","Image","onload","imagelist","grouplist","dynamicEdges","reroutedEdges","fontDrawThreshold","horizontalAlignLeft","verticalAlignTop","baseRadiusValue","radiusFixed","preassignedLevel","fx","fy","vx","vy","resetCluster","dynamicEdgesLength","clusterSession","clusterSizeWidthFactor","clusterSizeHeightFactor","clusterSizeRadiusFactor","growthIndicator","networkScale","formationScale","clusterSize","containedNodes","containedEdges","clusterSessions","originalLabel","triggerFunction","groupObj","imageObj","_drawDatabase","_resizeDatabase","_drawBox","_resizeBox","_drawCircle","_resizeCircle","_drawEllipse","_resizeEllipse","_drawImage","_resizeImage","_drawText","_resizeText","_drawDot","_resizeShape","_drawSquare","_drawTriangle","_drawTriangleDown","_drawStar","_reset","clearSizeCache","_setForce","_addForce","isFixed","getDistance","globalAlpha","drawImage","textSize","getTextSize","clusterLineWidth","selectionLineWidth","borderWidthSelected","roundRect","database","diameter","circle","defaultSize","ellipse","_drawShape","radiusMultiplier","baseline","labelUnderNode","lineCount","yLine","inView","clearVelocity","updateVelocity","massBeforeClustering","energyBefore","styleAttr","fontFamily","WebkitBorderRadius","whiteSpace","maxWidth","parseDOT","parseGraph","nextPreview","isAlphaNumeric","regexAlphaNumeric","merge","o","addNode","graphs","attr","addEdge","createEdge","getToken","tokenType","TOKENTYPE","NULL","token","isComment","DELIMITER","c2","DELIMITERS","IDENTIFIER","newSyntaxError","UNKNOWN","chop","strict","parseStatements","parseStatement","subgraph","parseSubgraph","parseEdge","parseAttributeStatement","parseNodeStatement","subgraphs","parseAttributeList","message","maxLength","forEach2","array1","array2","elem1","elem2","convertEdge","dotEdge","graphEdge","graphData","dotNode","graphNode","subEdge","{","}","[","]",";","=",",","->","--","gephiJSON","allowedToMove","gEdges","gNodes","gEdge","source","attributes","gNode","leftContainer","rightContainer","shadowTop","shadowBottom","shadowTopLeft","shadowBottomLeft","shadowTopRight","shadowBottomRight","listeners","events","args","scrollTop","scrollTopMin","_stopAutoResize","what","dataRange","getWindow","borderRootHeight","borderRootWidth","autoHeight","centerWidth","_updateScrollTop","visibilityTop","visibilityBottom","repaint","_startAutoResize","_onResize","lastHeight","watchTimer","setInterval","initialScrollTop","oldScrollTop","_getScrollTop","newScrollTop","_setScrollTop","eventType","getTouchList","collectEventData","CanvasRenderingContext2D","square","s2","ir","triangleDown","star","n","r2d","kappa","ox","oy","xe","ye","xm","ym","bezierCurveTo","wEllipse","hEllipse","ymb","yeb","xt","yt","xi","yi","xl","yl","xr","yr","dashArray","dashLength","dashCount","slope","distRemaining","dashIndex","PhysicsMixin","ClusterMixin","SectorsMixin","SelectionMixin","ManipulationMixin","NavigationMixin","HierarchicalLayoutMixin","_loadMixin","sourceVariable","mixinFunction","_clearMixin","_loadSelectedForceSolver","_loadPhysicsConfiguration","hubThreshold","activeSector","drawingNode","blockConnectingEdgeSelection","forceAppendSelection","editModeDiv","closeDiv","_cleanNavigation","_loadNavigationElements","_callbacks","once","self","removeListener","removeAllListeners","callbacks","cb","hasListeners","_addEvent","_characterFromEvent","fromCharCode","_MAP","_KEYCODE_MAP","_stop","tag_name","tagName","contentEditable","_modifiersMatch","modifiers1","modifiers2","_resetSequences","do_not_reset","active_sequences","_sequence_levels","_inside_sequence","_getMatches","character","modifiers","combination","matches","_isModifier","seq","combo","_eventModifiers","altKey","metaKey","_fireCallback","cancelBubble","_handleCharacter","processed_sequence_callback","_handleKey","keyCode","_ignore_next_keyup","_resetSequenceTimer","_reset_timer","_getReverseMap","_REVERSE_MAP","_pickBestAction","_bindSequence","_increaseSequence","_callbackAndReset","_bindSingle","sequence_name","sequence","_SPECIAL_ALIASES","_SHIFT_MAP","_bindMultiple","combinations",8,9,13,16,17,18,20,27,32,33,34,35,36,37,38,39,40,45,46,91,93,224,106,107,109,110,111,186,187,188,189,190,191,192,219,220,221,222,"~","!","@","#","$","%","^","&","*","(",")","_","+",":","\"","<",">","?","|","command","return","escape","_direct_map","unbind","trigger","__WEBPACK_AMD_DEFINE_RESULT__","setup","READY","Event","determineEventTypes","Utils","each","gestures","Detection","register","onTouch","DOCUMENT","EVENT_MOVE","detect","EVENT_END","Instance","VERSION","defaults","behavior","userSelect","touchAction","touchCallout","contentZooming","userDrag","tapHighlightColor","HAS_POINTEREVENTS","pointerEnabled","msPointerEnabled","HAS_TOUCHEVENTS","IS_MOBILE","NO_MOUSEEVENTS","CALCULATE_INTERVAL","EVENT_TYPES","DIRECTION_DOWN","DIRECTION_LEFT","DIRECTION_UP","DIRECTION_RIGHT","POINTER_MOUSE","POINTER_TOUCH","POINTER_PEN","EVENT_START","EVENT_RELEASE","EVENT_TOUCH","plugins","utils","dest","handler","iterator","context","inStr","find","inArray","hasParent","getCenter","getVelocity","deltaTime","getAngle","touch1","touch2","getDirection","getScale","getRotation","isVertical","setPrefixedCss","toggle","prefixes","toCamelCase","toggleBehavior","falseFn","onselectstart","ondragstart","str","preventMouseEvents","started","shouldDetect","hook","onTouchHandler","ev","triggerType","srcType","isPointer","isMouse","buttons","PointerEvent","matchType","updatePointer","doDetect","touchList","touchListLength","triggerChange","changedLength","changedTouches","evData","identifiers","identifier","pointerType","timeStamp","preventManipulation","stopDetect","pointers","touchlist","pointerEvent","pointerId","pt","MSPOINTER_TYPE_MOUSE","MSPOINTER_TYPE_TOUCH","MSPOINTER_TYPE_PEN","detection","stopped","startDetect","inst","eventData","startEvent","lastEvent","lastCalcEvent","futureCalcEvent","lastCalcData","extendEventData","instOptions","getCalculatedData","recalc","calcEv","calcData","velocity","velocityX","velocityY","interimAngle","interimDirection","startEv","lastEv","rotation","eventStartHandler","eventHandlers","createEvent","initEvent","dispatchEvent","state","dispose","eh","dragGesture","dragMaxTouches","triggered","dragMinDistance","startCenter","dragDistanceCorrection","dragLockToAxis","dragLockMinDistance","lastDirection","dragBlockVertical","dragBlockHorizontal","Drag","Gesture","holdGesture","holdTimeout","holdThreshold","Hold","Release","Infinity","Swipe","swipeMinTouches","swipeMaxTouches","swipeVelocityX","swipeVelocityY","tapGesture","sincePrev","didDoubleTap","hasMoved","tapMaxDistance","tapMaxTime","doubleTapInterval","doubleTapDistance","tapAlways","Tap","Touch","preventMouse","transformGesture","scaleThreshold","rotationThreshold","transformMinScale","transformMinRotation","Transform","global","dfl","defaultParsingFlags","empty","unusedTokens","unusedInput","charsLeftOver","nullInput","invalidMonth","invalidFormat","userInvalidated","iso","deprecate","msg","printMsg","suppressDeprecationWarnings","warn","firstTime","padToken","func","leftZeroFill","ordinalizeToken","period","lang","ordinal","Language","Moment","config","checkOverflow","Duration","duration","normalizedInput","normalizeObjectUnits","years","quarters","quarter","months","month","weeks","week","days","day","hour","minute","second","millisecond","_milliseconds","_days","_months","_bubble","cloneMoment","momentProperties","absRound","number","targetLength","forceSign","output","addOrSubtractDurationFromMoment","mom","isAdding","updateOffset","_d","setTime","rawSetter","rawGetter","rawMonthSetter","input","compareArrays","dontConvert","lengthDiff","diffs","toInt","normalizeUnits","units","lowered","unitAliases","camelFunctions","inputObject","normalizedProp","makeList","setter","getter","method","_lang","results","utc","set","argumentForCoercion","coercedNumber","isFinite","daysInMonth","UTC","getUTCDate","weeksInYear","dow","doy","weekOfYear","daysInYear","isLeapYear","_a","_pf","DATE","_overflowDayOfYear","isValid","_isValid","getTime","_strict","normalizeLanguage","makeAs","model","_isUTC","zone","_offset","local","loadLang","abbr","languages","unloadLang","getLangDefinition","k","hasModule","removeFormattingTokens","makeFormatFunction","formattingTokens","formatTokenFunctions","formatMoment","expandFormat","formatFunctions","invalidDate","replaceLongDateFormatTokens","longDateFormat","localFormattingTokens","lastIndex","getParseRegexForToken","parseTokenOneDigit","parseTokenThreeDigits","parseTokenFourDigits","parseTokenOneToFourDigits","parseTokenSignedNumber","parseTokenSixDigits","parseTokenOneToSixDigits","parseTokenTwoDigits","parseTokenOneToThreeDigits","parseTokenWord","_l","_meridiemParse","parseTokenTimestampMs","parseTokenTimezone","parseTokenT","parseTokenDigits","parseTokenOneOrTwoDigits","parseTokenOrdinal","RegExp","regexpEscape","unescapeFormat","timezoneMinutesFromString","string","possibleTzMatches","tzChunk","parts","parseTimezoneChunker","addTimeToArrayFromToken","datePartArray","monthsParse","_dayOfYear","parseTwoDigitYear","_isPm","isPM","_useUTC","_tzm","weekdaysParse","_w","invalidWeekday","dayOfYearFromWeekInfo","weekYear","weekday","temp","GG","W","E","_week","gg","dayOfYearFromWeeks","dayOfYear","dateFromConfig","currentDate","yearToUse","currentDateArray","makeUTCDate","getUTCMonth","makeDate","setUTCMinutes","getUTCMinutes","dateFromObject","_i","getUTCFullYear","makeDateFromStringAndFormat","_f","ISO_8601","parseISO","parsedInput","tokens","skipped","stringLength","totalParsedInputLength","matched","p4","makeDateFromStringAndArray","tempConfig","bestMoment","scoreToBeat","currentScore","NaN","score","l","isoRegex","isoDates","isoTimes","makeDateFromString","createFromInputFallback","makeDateFromInput","aspNetJsonRegex","ms","setUTCFullYear","parseWeekday","language","substituteTimeAgo","withoutSuffix","isFuture","relativeTime","relativeTimeThresholds","dd","dm","firstDayOfWeek","firstDayOfWeekOfYear","adjustedMoment","daysToDayOfWeek","daysToAdd","getUTCDay","makeMoment","invalid","preparse","pickBy","moments","res","dayOfMonth","unit","makeAccessor","keepTime","makeDurationGetter","makeDurationAsGetter","makeGlobal","shouldDeprecate","ender","oldGlobalMoment","globalScope","_isAMomentObject","aspNetTimeSpanJsonRegex","isoDurationRegex","isoFormat","unitMillisecondFactors","Milliseconds","Seconds","Minutes","Hours","Days","Months","Years","D","Q","DDD","dayofyear","isoweekday","isoweek","weekyear","isoweekyear","ordinalizeTokens","paddedTokens","MMM","monthsShort","MMMM","weekdaysMin","ddd","weekdaysShort","dddd","weekdays","isoWeek","YY","YYYY","YYYYY","YYYYYY","gggg","ggggg","isoWeekYear","GGGG","GGGGG","isoWeekday","meridiem","SS","SSS","SSSS","Z","ZZ","zoneAbbr","zz","zoneName","unix","lists","DDDD","_monthsShort","monthName","regex","_monthsParse","_weekdays","_weekdaysShort","_weekdaysMin","weekdayName","_weekdaysParse","_longDateFormat","LT","L","LL","LLL","LLLL","val","isLower","_calendar","sameDay","nextDay","nextWeek","lastDay","lastWeek","sameElse","calendar","_relativeTime","future","past","mm","hh","MM","yy","pastFuture","_ordinal","postformat","_invalidDate","ret","parseIso","isDuration","inp","version","defaultFormat","relativeTimeThreshold","threshold","limit","_abbr","langData","flags","parseZone","isDSTShifted","parsingFlags","invalidAt","inputString","dur","asFloat","that","zoneDiff","startOf","humanize","fromNow","sod","isDST","getDay","endOf","isAfter","isBefore","isSame","getTimezoneOffset","_changeInProgress","hasAlignedHourOffset","isoWeeksInYear","weekInfo","dates","isoWeeks","toJSON","withSuffix","difference","toIsoString","asSeconds","asMonths","require","noGlobal","clusterToFit","maxNumberOfNodes","reposition","maxLevels","forceAggregateHubs","normalizeClusterLevels","increaseClusterLevel","repositionNodes","openCluster","isMovingBeforeClustering","_nodeInActiveArea","_sector","_addSector","decreaseClusterLevel","_expandClusterNode","_updateDynamicEdges","updateClusters","zoomDirection","recursive","doNotStart","amountOfNodes","_collapseSector","_formClusters","_openClusters","_openClustersBySize","_aggregateHubs","handleChains","chainPercentage","_getChainFraction","_reduceAmountOfChains","_getHubSize","_formClustersByHub","openAll","containedNodeId","childNode","_expelChildFromParent","_unselectAll","_releaseContainedEdges","_connectEdgeBackToChild","_validateEdges","othersPresent","childNodeId","_repositionBezierNodes","_formClustersByZoom","_forceClustersByZoom","minLength","_addToCluster","_clusterToSmallestNeighbour","smallestNeighbour","smallestNeighbourNode","neighbour","onlyEqual","_formClusterFromHub","hubNode","absorptionSizeOffset","allowCluster","edgesIdarray","amountOfInitialEdges","_addToContainedEdges","_connectEdgeToCluster","_containCircularEdgesFromNode","massBefore","correction","edgeToId","edgeFromId","_addToReroutedEdges","maxLevel","minLevel","clusterLevel","targetLevel","average","averageSquared","hubCounter","largestHub","variance","standardDeviation","fraction","reduceAmount","chains","_switchToSector","sectorId","sectorType","_switchToActiveSector","_switchToFrozenSector","_switchToSupportSector","_loadLatestSector","_previousSector","_setActiveSector","newId","_forgetLastSector","_createNewSector","_deleteActiveSector","_deleteFrozenSector","_freezeSector","_activateSector","_mergeThisWithFrozen","_collapseThisToSingleCluster","sector","unqiueIdentifier","previousSector","runFunction","argument","_doInAllFrozenSectors","_drawSectorNodes","_drawAllSectorNodes","_getNodesOverlappingWith","overlappingNodes","_getAllNodesOverlappingWith","_pointerToPositionObject","positionObject","_getEdgesOverlappingWith","overlappingEdges","_getAllEdgesOverlappingWith","_addToSelection","_addToHover","_removeFromSelection","doNotTrigger","_unselectClusters","_getSelectedNodeCount","_getSelectedNode","_getSelectedEdge","_getSelectedEdgeCount","_getSelectedObjectCount","_selectionIsEmpty","_clusterInSelection","_selectConnectedEdges","_hoverConnectedEdges","_unselectConnectedEdges","append","highlightEdges","nodeIds","getSelectedNodes","edgeIds","getSelectedEdges","idArray","RangeError","selectNodes","selectEdges","_clearManipulatorBar","_restoreOverloadedFunctions","functionName","_toggleEditMode","toolbar","getElementById","boundFunction","edgeBeingEdited","selectedControlNode","addNodeButton","_createAddNodeToolbar","addEdgeButton","_createAddEdgeToolbar","editButton","_editNode","_createEditEdgeToolbar","editModeButton","backButton","_addNode","_handleConnect","_finishConnect","_selectControlNode","_controlNodeDrag","_releaseControlNode","newNode","_editEdge","alert","smooth","connectFromId","_createEdge","defaultData","finalizedData","sourceNodeId","targetNodeId","selectedNodes","selectedEdges","wrapper","navigationDivActions","_stopMovement","hubsize","definedLevel","undefinedLevel","_changeConstants","_determineLevels","distribution","_getDistribution","_placeNodesByHierarchy","minPos","_placeBranchNodes","maxCount","_setLevel","parentId","parentLevel","nodeMoved","_restoreNodes","graphToggleSmoothCurves","graph_toggleSmooth","graphRepositionNodes","showValueOfRange","graphGenerateOptions","optionsSpecific","radioButton1","radioButton2","checked","backupConstants","optionsDiv","switchConfigurations","radioButton","querySelector","tableId","table","constantsVariableName","valueId","rangeValue","_overWriteGraphConstants","RepulsionMixin","HierarchialRepulsionMixin","BarnesHutMixin","_toggleBarnesHut","barnesHutTree","_initializeForceCalculation","_calculateForces","_calculateGravitationalForces","_calculateNodeForces","_calculateSpringForcesWithSupport","_calculateHierarchicalSpringForces","_calculateSpringForces","supportNodes","supportNodeId","gravity","gravityForce","edgeLength","springForce","combinedClusterSize","node1","node2","node3","_calculateSpringForce","physicsConfiguration","hierarchicalLayoutDirections","parentElement","rangeElement","radioButton3","graph_repositionNodes","graph_generateOptions","nameArray","webpackContext","req","webpackContextResolve","resolve","repulsingForce","a_base","minimumDistance","steepness","springFx","springFy","totalFx","totalFy","correctionFx","correctionFy","nodeCount","_formBarnesHutTree","_getForceContribution","children","NW","NE","SW","SE","parentBranch","childrenCount","centerOfMass","calcSize","MAX_VALUE","sizeDiff","minimumTreeSize","rootSize","halfRootSize","centerX","centerY","_splitBranch","_placeInTree","_updateBranchMass","totalMass","totalMassInv","biggestSize","skipMassUpdate","_placeInRegion","region","containedNode","_insertRegion","childSize","_drawTree","_drawBranch","branch","webpackPolyfill","paths"],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"vis.map","sources":["./dist/vis.js"],"names":["root","factory","exports","module","define","amd","this","modules","__webpack_require__","moduleId","installedModules","id","loaded","call","m","c","p","util","DOMutil","DataSet","DataView","Graph3d","graph3d","Camera","Filter","Point2d","Point3d","Slider","StepNumber","Timeline","Graph2d","timeline","DataStep","Range","stack","TimeStep","components","items","Item","ItemBox","ItemPoint","ItemRange","Component","CurrentTime","CustomTime","DataAxis","GraphGroup","Group","ItemSet","Legend","LineGraph","TimeAxis","Network","network","Edge","Groups","Images","Node","Popup","dotparser","gephiParser","Graph","Error","moment","hammer","isNumber","object","Number","isString","String","isDate","Date","match","ASPDateRegex","exec","isNaN","parse","isDataTable","google","visualization","DataTable","randomUUID","S4","Math","floor","random","toString","extend","a","i","len","arguments","length","other","prop","hasOwnProperty","selectiveExtend","props","Array","isArray","selectiveDeepExtend","b","TypeError","constructor","Object","undefined","deepExtend","selectiveNotDeepExtend","indexOf","equalArray","convert","type","Boolean","valueOf","isMoment","toDate","getType","toISOString","value","getAbsoluteLeft","elem","getBoundingClientRect","left","window","pageXOffset","getAbsoluteTop","top","pageYOffset","addClassName","className","classes","split","push","join","removeClassName","index","splice","forEach","callback","toArray","array","updateProperty","key","addEventListener","element","action","listener","useCapture","navigator","userAgent","attachEvent","removeEventListener","detachEvent","preventDefault","event","returnValue","getTarget","target","srcElement","nodeType","parentNode","option","asBoolean","defaultValue","asNumber","asString","asSize","asElement","GiveDec","Hex","Value","eval","GiveHex","Dec","parseColor","color","isValidRGB","rgb","substr","RGBToHex","isValidHex","hsv","hexToHSV","lighterColorHSV","h","s","v","min","darkerColorHSV","darkerColorHex","HSVToHex","lighterColorHex","background","border","highlight","hover","hexToRGB","hex","replace","toUpperCase","substring","d","e","f","r","g","red","green","blue","RGBToHSV","minRGB","maxRGB","max","hue","saturation","HSVToRGB","q","t","isOk","test","selectiveBridgeObject","fields","referenceObject","objectTo","create","bridgeObject","mergeOptions","mergeTarget","options","enabled","binarySearch","orderedItems","range","field","field2","maxIterations","iteration","found","low","high","newLow","newHigh","guess","isVisible","start","console","log","binarySearchGeneric","sidePreference","newGuess","prevValue","nextValue","prepareElements","JSONcontainer","elementType","redundant","used","cleanupElements","removeChild","getSVGElement","svgContainer","shift","document","createElementNS","appendChild","getDOMElement","DOMContainer","createElement","drawPoint","x","y","group","point","drawPoints","style","setAttributeNS","size","drawBar","width","height","rect","data","_options","_data","_fieldId","fieldId","_type","_subscribers","add","prototype","on","subscribers","subscribe","off","filter","unsubscribe","_trigger","params","senderId","concat","subscriber","addedIds","me","_addItem","columns","_getColumnNames","row","rows","getNumberOfRows","item","col","cols","getValue","update","updatedIds","addOrUpdate","_updateItem","get","ids","firstType","returnType","allowedValues","itemId","_getItem","order","_sort","_filterFields","_appendRow","result","getIds","getDataSet","map","mappedItems","filteredItem","name","sort","av","bv","remove","removedId","removedIds","_remove","clear","keys","maxField","itemField","minField","distinct","values","fieldType","count","exists","types","raw","converted","JSON","stringify","dataTable","getNumberOfColumns","getColumnId","getColumnLabel","addRow","setValue","_ids","_onEvent","apply","setData","viewOptions","getArguments","defaultFilter","dataSet","added","updated","removed","container","SyntaxError","containerElement","margin","defaultXCenter","defaultYCenter","xLabel","yLabel","zLabel","filterLabel","legendLabel","STYLE","DOT","showPerspective","showGrid","keepAspectRatio","showShadow","showGrayBottom","showTooltip","verticalRatio","animationInterval","animationPreload","camera","eye","dataPoints","colX","colY","colZ","colValue","colFilter","xMin","xStep","xMax","yMin","yStep","yMax","zMin","zStep","zMax","valueMin","valueMax","xBarWidth","yBarWidth","colorAxis","colorGrid","colorDot","colorDotBorder","setOptions","Emitter","_setScale","scale","z","xCenter","yCenter","zCenter","setArmLocation","_convert3Dto2D","point3d","translation","_convertPointToTranslation","_convertTranslationToScreen","ax","ay","az","cx","getCameraLocation","cy","cz","sinTx","sin","getCameraRotation","cosTx","cos","sinTy","cosTy","sinTz","cosTz","dx","dy","dz","bx","by","ex","ey","ez","getArmLength","xcenter","frame","canvas","clientWidth","ycenter","_setBackgroundColor","backgroundColor","fill","stroke","strokeWidth","borderColor","borderWidth","borderStyle","BAR","BARCOLOR","BARSIZE","DOTLINE","DOTCOLOR","DOTSIZE","GRID","LINE","SURFACE","_getStyleNumber","styleName","_determineColumnIndexes","counter","column","getDistinctValues","distinctValues","getColumnRange","minMax","_dataInitialize","rawData","_onChange","dataFilter","setOnLoadCallback","redraw","withBars","defaultXBarWidth","dataX","defaultYBarWidth","dataY","xRange","defaultXMin","defaultXMax","defaultXStep","yRange","defaultYMin","defaultYMax","defaultYStep","zRange","defaultZMin","defaultZMax","defaultZStep","valueRange","defaultValueMin","defaultValueMax","_getDataPoints","sortNumber","obj","dataMatrix","xIndex","yIndex","trans","screen","bottom","pointRight","pointTop","pointCross","hasChildNodes","firstChild","position","overflow","noCanvas","fontWeight","padding","innerHTML","onmousedown","_onMouseDown","ontouchstart","_onTouchStart","onmousewheel","_onWheel","ontooltip","_onTooltip","onkeydown","setSize","_resizeCanvas","clientHeight","animationStart","slider","play","animationStop","stop","_resizeCenter","charAt","parseFloat","setCameraPosition","pos","horizontal","vertical","setArmRotation","distance","setArmLength","getCameraPosition","getArmRotation","_readData","_redrawFilter","animationAutoStart","cameraPosition","styleNumber","tooltip","showAnimationControls","_redrawSlider","_redrawClear","_redrawAxis","_redrawDataGrid","_redrawDataLine","_redrawDataBar","_redrawDataDot","_redrawInfo","_redrawLegend","ctx","getContext","clearRect","widthMin","widthMax","dotSize","right","lineWidth","font","ymin","ymax","_hsv2rgb","strokeStyle","beginPath","moveTo","lineTo","strokeRect","fillStyle","closePath","gridLineLen","step","getCurrent","next","end","textAlign","textBaseline","fillText","label","visible","setValues","setPlayInterval","onchange","getIndex","selectValue","setOnChangeCallback","lineStyle","getLabel","getSelectedValue","from","to","prettyStep","text","xText","yText","zText","offset","xOffset","yOffset","xMin2d","xMax2d","gridLenX","gridLenY","textMargin","armAngle","H","S","V","R","G","B","C","Hi","X","abs","parseInt","cross","topSideVisible","zAvg","transBottom","dist","sortDepth","aDiff","subtract","bDiff","crossproduct","crossProduct","radius","arc","PI","j","surface","corners","xWidth","yWidth","surfaces","center","avg","transCenter","diff","leftButtonDown","_onMouseUp","which","button","touchDown","startMouseX","getMouseX","startMouseY","getMouseY","startStart","startEnd","startArmRotation","cursor","onmousemove","_onMouseMove","onmouseup","diffX","diffY","horizontalNew","verticalNew","snapAngle","snapValue","round","parameters","emit","delay","mouseX","mouseY","tooltipTimeout","clearTimeout","_hideTooltip","dataPoint","_dataPointFromXY","_showTooltip","setTimeout","ontouchmove","_onTouchMove","ontouchend","_onTouchEnd","delta","wheelDelta","detail","oldLength","newLength","_insideTriangle","triangle","sign","as","bs","cs","distMax","closestDataPoint","closestDist","triangle1","triangle2","distX","distY","sqrt","content","line","dot","dom","borderRadius","boxShadow","borderLeft","contentWidth","offsetWidth","contentHeight","offsetHeight","lineHeight","dotWidth","dotHeight","clientX","targetTouches","clientY","armLocation","armRotation","armLength","cameraLocation","cameraRotation","calculateCameraOrientation","rot","graph","onLoadCallback","loadInBackground","isLoaded","getLoadedProgress","getColumn","getValues","dataView","progress","sub","sum","prev","bar","MozBorderRadius","slide","onclick","togglePlay","onChangeCallback","playTimeout","playInterval","playLoop","setIndex","playNext","interval","clearInterval","getPlayInterval","setPlayLoop","doLoop","onChange","indexToLeft","startClientX","startSlideX","leftToIndex","_start","_end","_step","precision","_current","setRange","setStep","calculatePrettyStep","log10","LN10","step1","pow","step2","step5","toPrecision","getStep","coreProp","Core","defaultOptions","autoResize","orientation","maxHeight","minHeight","_create","body","domProps","emitter","bind","snap","toScreen","_toScreen","toGlobalScreen","_toGlobalScreen","toTime","_toTime","toGlobalTime","_toGlobalTime","timeAxis","currentTime","customTime","itemSet","itemsData","groupsData","setItems","_initAutoResize","component","newDataSet","initialLoad","fit","setWindow","setGroups","groups","setSelection","getSelection","getItemRange","dataset","minItem","maxStartItem","maxEndItem","linegraph","getLegend","groupId","isGroupVisible","minimumStep","containerHeight","forcedStepSize","current","autoScale","stepIndex","marginStart","marginEnd","majorSteps","minorSteps","setMinimumStep","setFirst","safeSize","minimumStepValue","orderOfMagnitude","minorStepIdx","magnitudefactor","solutionFound","stepSize","first","niceStart","niceEnd","roundToMinor","marginRange","rounded","hasNext","previous","slice","isMajor","now","hours","minutes","seconds","milliseconds","clone","direction","moveable","zoomable","zoomMin","zoomMax","touch","_onDragStart","_onDrag","_onDragEnd","_onHold","_onMouseWheel","_onTouch","_onPinch","validateDirection","getPointer","pageX","pageY","hammerUtil","changed","_applyRange","newStart","newEnd","getRange","conversion","allowDragging","gesture","deltaX","deltaY","diffRange","fakeGesture","pointer","pointerDate","_pointerToDate","zoom","touches","initDate","move","EPSILON","orderByStart","orderByEnd","aTime","bTime","force","iMax","axis","collidingItem","jj","collision","nostack","SCALE","DAY","MILLISECOND","SECOND","MINUTE","HOUR","WEEKDAY","MONTH","YEAR","setFullYear","getFullYear","setMonth","setDate","setHours","setMinutes","setSeconds","setMilliseconds","getMilliseconds","getSeconds","getMinutes","getHours","getDate","getMonth","setScale","newScale","newStep","setAutoScale","enable","stepYear","stepMonth","stepDay","stepHour","stepMinute","stepSecond","stepMillisecond","date","year","getLabelMinor","format","getLabelMajor","destroy","_isResized","resized","_previousWidth","_previousHeight","showCurrentTime","parent","backgroundVertical","title","currentTimeTimer","showCustomTime","eventParams","Hammer","drag","prevent_default","setCustomTime","time","getCustomTime","dragging","stopPropagation","svg","showMinorLabels","showMajorLabels","icons","majorLinesOffset","minorLinesOffset","labelOffsetX","labelOffsetY","iconWidth","linegraphSVG","DOMelements","lines","labels","conversionFactor","minWidth","stepPixels","stepPixelsForced","lineOffset","master","svgElements","amountOfGroups","addGroup","graphOptions","updateGroup","removeGroup","hide","show","lineContainer","display","_redrawGroupIcons","iconHeight","iconOffset","drawIcon","backgroundHorizontal","changeCalled","activeGroups","_calculateCharSize","minorLabelHeight","minorCharHeight","majorLabelHeight","majorCharHeight","minorLineWidth","minorLineHeight","majorLineWidth","majorLineHeight","_redrawLabels","amountOfSteps","stepDifference","valueAtZero","marginStartPos","maxLabelSize","_redrawLabel","_redrawLine","characterHeight","largestWidth","majorCharWidth","minorCharWidth","convertValue","invertedValue","convertedValue","textMinor","createTextNode","measureCharMinor","textMajor","measureCharMajor","groupsUsingDefaultStyles","usingDefaultStyle","zeroPosition","setZeroPosition","catmullRom","parametrization","alpha","SVGcontainer","path","fillPath","fillHeight","outline","shaded","barWidth","bar1Height","bar2Height","icon","yAxisOrientation","visibleItems","byStart","byEnd","inner","foreground","marker","visibility","Element","getLabelWidth","restack","_updateVisibleItems","markerHeight","lastMarkerHeight","dirty","displayed","offsetTop","offsetLeft","ii","repositionY","labelSet","setParent","_checkIfVisible","removeFromDataSet","removeItem","_constructByEndArray","endArray","initialPosByStart","newVisibleItems","initialPosByEnd","_checkIfInvisible","repositionX","align","groupOrder","selectable","editable","updateTime","onAdd","onUpdate","onMove","onRemove","itemOptions","itemListeners","_onAdd","_onUpdate","_onRemove","groupListeners","_onAddGroups","_onUpdateGroups","_onRemoveGroups","groupIds","selection","stackDirty","touchParams","_moveToGroup","oldGroup","UNGROUPED","box","_updateUngrouped","centerContainer","_onSelectItem","_onMultiSelectItem","_onAddItem","addCallback","fn","Function","markDirty","unselect","select","getVisibleItems","rawVisibleItems","_deselect","_orderGroups","visibleInterval","zoomed","lastVisibleInterval","lastWidth","firstGroup","_firstGroup","firstMargin","nonFirstMargin","groupMargin","groupResized","firstGroupIndex","firstGroupId","ungrouped","getLabelSet","oldItemsData","getItems","_order","getGroups","itemData","_removeItem","groupData","groupOptions","oldGroupId","itemFromTarget","selected","dragLeftItem","dragRightItem","itemProps","groupFromTarget","changes","ctrlKey","srcEvent","shiftKey","oldSelection","newSelection","xAbs","newItem","itemSetFromTarget","side","iconSize","iconSpacing","textArea","drawLegendIcons","getComputedStyle","paddingTop","defaultGroup","sampling","graphHeight","barChart","allowOverlap","dataAxis","legend","lastStart","rangePerPixelInv","_updateGraph","yAxisLeft","yAxisRight","legendLeft","legendRight","_updateAllGroupData","_updateGroup","groupsContent","ungroupedCounter","preprocessedGroup","preprocessedGroupData","processedGroupData","groupRanges","minDate","maxDate","_preprocessData","_updateYAxis","_convertYvalues","_drawLineGraph","_drawBarGraph","minVal","maxVal","yAxisLeftUsed","yAxisRightUsed","minLeft","minRight","maxLeft","maxRight","_toggleAxisVisiblity","drawIcons","axisUsed","coreDistance","intersections","amount","resolved","drawData","_getSafeDrawData","nextKey","prevKey","slots","total","slot","svgHeight","_catmullRom","_linear","dFill","_drawPoints","datapoints","xValue","yValue","extractedData","increment","amountOfPoints","xDistance","pointsPerPixel","ceil","_catmullRomUniform","p0","p1","p2","p3","bp1","bp2","normalization","d1","d2","d3","A","N","M","d3powA","d2powA","d3pow2A","d2pow2A","d1pow2A","d1powA","majorLines","majorTexts","minorLines","minorTexts","lineTop","parentChanged","foregroundNextSibling","nextSibling","backgroundNextSibling","_repaintLabels","insertBefore","xFirstMajorLabel","cur","_repaintMinorText","_repaintMajorText","_repaintMajorLine","_repaintMinorLine","leftTime","leftText","widthText","arr","pop","childNodes","nodeValue","_repaintDeleteButton","anchor","deleteButton","itemSetHeight","marginLeft","baseClassName","_repaintDragLeft","_repaintDragRight","contentLeft","parentWidth","boxWidth","dragLeft","dragRight","_initializeMixinLoaders","renderRefreshRate","renderTimestep","renderTime","maxPhysicsTicksPerRender","physicsDiscreteStepsize","initializing","triggerFunctions","edit","editEdge","connect","del","nodes","mass","radiusMin","radiusMax","shape","image","fixed","fontColor","fontSize","fontFace","level","highlightColor","edges","widthSelectionMultiplier","hoverWidth","fontFill","arrowScaleFactor","dash","gap","altLength","inheritColor","configurePhysics","physics","barnesHut","theta","gravitationalConstant","centralGravity","springLength","springConstant","damping","repulsion","nodeDistance","hierarchicalRepulsion","clustering","initialMaxNodes","clusterThreshold","reduceToNodes","chainThreshold","clusterEdgeThreshold","sectorThreshold","screenSizeThreshold","fontSizeMultiplier","maxFontSize","forceAmplification","distanceAmplification","edgeGrowth","nodeScaling","maxNodeSizeIncrements","activeAreaBoxSize","clusterLevelDifference","navigation","keyboard","speed","dataManipulation","initiallyVisible","hierarchicalLayout","levelSeparation","nodeSpacing","freezeForStabilization","smoothCurves","dynamic","roundness","dynamicSmoothCurves","maxVelocity","minVelocity","stabilize","stabilizationIterations","link","editNode","back","addDescription","linkDescription","editEdgeDescription","addError","linkError","editError","editBoundError","deleteError","deleteClusterError","dragNetwork","dragNodes","hideEdgesOnDrag","hideNodesOnDrag","constants","hoverObj","controlNodesActive","images","setOnloadCallback","_redraw","xIncrement","yIncrement","zoomIncrement","_loadPhysicsSystem","_loadSectorSystem","_loadClusterSystem","_loadSelectionSystem","_loadHierarchySystem","_setTranslation","freezeSimulation","cachedFunctions","calculationNodes","calculationNodeIndices","nodeIndices","canvasTopLeft","canvasBottomRight","pointerPosition","areaCenter","previousScale","nodesData","edgesData","nodesListeners","_addNodes","_updateNodes","_removeNodes","edgesListeners","_addEdges","_updateEdges","_removeEdges","moving","timer","_setupHierarchicalLayout","zoomExtent","startWithClustering","mousetrap","MixinLoader","_getScriptPath","scripts","getElementsByTagName","src","_getRange","node","minY","maxY","minX","maxX","nodeId","_findCenter","_centerNetwork","initialZoom","disableStart","zoomLevel","numberOfNodes","factor","yDistance","xZoomLevel","yZoomLevel","_updateNodeIndexList","_clearNodeIndexList","idx","dotData","DOTToGraph","gephi","gephiData","parseGephi","_setNodes","_setEdges","_putDataInSector","_stabilize","onEdit","onEditEdge","onConnect","onDelete","editMode","newColorObj","groupname","_loadNavigationControls","_loadManipulationSystem","_configureSmoothCurves","_createKeyBinds","pinch","_onTap","_onDoubleTap","_onRelease","_onMouseMoveTitle","reset","_moveUp","_yStopMoving","_moveDown","_moveLeft","_xStopMoving","_moveRight","_zoomIn","_stopZoom","_zoomOut","_createManipulatorBar","_deleteSelected","_getPointer","pinched","_getScale","_handleTouch","_handleDragStart","_getNodeAt","_getTranslation","isSelected","_selectObject","objectId","selectionObj","xFixed","yFixed","_handleOnDrag","_XconvertDOMtoCanvas","_XconvertCanvasToDOM","_YconvertDOMtoCanvas","_YconvertCanvasToDOM","_handleTap","_handleDoubleTap","_handleOnHold","_handleOnRelease","_zoom","scaleOld","preScaleDragPointer","DOMtoCanvas","scaleFrac","tx","ty","updateClustersDefault","postScaleDragPointer","canvasToDOM","popupObj","_checkHidePopup","checkShow","_checkShowPopup","popupTimer","edgeId","_getEdgeAt","_hoverObject","_blurObject","lastPopupNode","getTitle","isOverlappingWith","edge","connected","popup","setPosition","setText","manipulationDiv","navigationDivs","oldNodesData","_updateSelection","angle","_resetLevels","_updateCalculationNodes","_reconnectEdges","_updateValueRange","updateLabels","setProperties","properties","oldEdgesData","oldEdge","disconnect","showInternalIds","_createBezierNodes","via","sectors","setValueRange","w","save","translate","_doInAllSectors","restore","offsetX","offsetY","_drawNodes","alwaysShow","setScaleAndPos","inArea","draw","sMax","_drawEdges","_drawControlNodes","_freezeDefinedNodes","_physicsTick","_restoreFrozenNodes","iterations","fixedData","_isMoving","vmin","isMoving","_discreteStepNodes","checkMovement","nodesPresent","discreteStepLimited","discreteStep","vminCorrected","_doInAllActiveSectors","_doInSupportSector","_animationStep","_handleNavigation","calculationTime","maxSteps","timeRequired","requestAnimationFrame","mozRequestAnimationFrame","webkitRequestAnimationFrame","msRequestAnimationFrame","ua","toLowerCase","requiresTimeout","toggleFreeze","parentEdgeId","internalMultiplier","positionBezierNode","mixin","storePosition","dataArray","allowedToMoveX","allowedToMoveY","focusOnNode","nodePosition","requiredScale","canvasCenter","distanceFromCenter","networkConstants","fromId","toId","widthSelected","originalFromId","originalToId","widthFixed","lengthFixed","controlNodesEnabled","controlNodes","positions","connectedNode","_drawLine","_drawArrow","_drawArrowCenter","_drawDashLine","attachEdge","detachEdge","xFrom","yFrom","xTo","yTo","xObj","yObj","_getDistanceToEdge","_getColor","colorObj","_getLineWidth","_line","midpointX","midpointY","_pointOnLine","_label","resize","_circle","_pointOnCircle","networkScaleInv","_getViaCoordinates","xVia","yVia","quadraticCurveTo","measureText","fillRect","mozDash","setLineDash","pattern","lineDashOffset","mozDashOffset","lineCap","dashedLine","percentage","atan2","arrow","edgeSegmentLength","fromBorderDist","distanceToBorder","fromBorderPoint","toBorderDist","toBorderPoint","x1","y1","x2","y2","x3","y3","lastX","lastY","minDistance","_getDistanceToLine","px","py","something","u","nodeIdFrom","nodeIdTo","getControlNodePositions","_enableControlNodes","_disableControlNodes","_getSelectedControlNode","fromDistance","toDistance","_restoreControlNodes","defaultIndex","DEFAULT","load","url","img","Image","onload","imagelist","grouplist","dynamicEdges","reroutedEdges","fontDrawThreshold","horizontalAlignLeft","verticalAlignTop","baseRadiusValue","radiusFixed","preassignedLevel","fx","fy","vx","vy","resetCluster","dynamicEdgesLength","clusterSession","clusterSizeWidthFactor","clusterSizeHeightFactor","clusterSizeRadiusFactor","growthIndicator","networkScale","formationScale","clusterSize","containedNodes","containedEdges","clusterSessions","originalLabel","triggerFunction","groupObj","imageObj","_drawDatabase","_resizeDatabase","_drawBox","_resizeBox","_drawCircle","_resizeCircle","_drawEllipse","_resizeEllipse","_drawImage","_resizeImage","_drawText","_resizeText","_drawDot","_resizeShape","_drawSquare","_drawTriangle","_drawTriangleDown","_drawStar","_reset","clearSizeCache","_setForce","_addForce","isFixed","velocity","getDistance","globalAlpha","drawImage","textSize","getTextSize","clusterLineWidth","selectionLineWidth","borderWidthSelected","roundRect","database","diameter","circle","defaultSize","ellipse","_drawShape","radiusMultiplier","baseline","labelUnderNode","lineCount","yLine","inView","clearVelocity","updateVelocity","massBeforeClustering","energyBefore","styleAttr","fontFamily","WebkitBorderRadius","whiteSpace","maxWidth","parseDOT","parseGraph","nextPreview","isAlphaNumeric","regexAlphaNumeric","merge","o","addNode","graphs","attr","addEdge","createEdge","getToken","tokenType","TOKENTYPE","NULL","token","isComment","DELIMITER","c2","DELIMITERS","IDENTIFIER","newSyntaxError","UNKNOWN","chop","strict","parseStatements","parseStatement","subgraph","parseSubgraph","parseEdge","parseAttributeStatement","parseNodeStatement","subgraphs","parseAttributeList","message","maxLength","forEach2","array1","array2","elem1","elem2","convertEdge","dotEdge","graphEdge","graphData","dotNode","graphNode","subEdge","{","}","[","]",";","=",",","->","--","gephiJSON","allowedToMove","gEdges","gNodes","gEdge","source","attributes","gNode","leftContainer","rightContainer","shadowTop","shadowBottom","shadowTopLeft","shadowBottomLeft","shadowTopRight","shadowBottomRight","listeners","events","args","scrollTop","scrollTopMin","_stopAutoResize","what","dataRange","getWindow","borderRootHeight","borderRootWidth","autoHeight","centerWidth","_updateScrollTop","visibilityTop","visibilityBottom","repaint","_startAutoResize","_onResize","lastHeight","watchTimer","setInterval","initialScrollTop","oldScrollTop","_getScrollTop","newScrollTop","_setScrollTop","eventType","getTouchList","collectEventData","CanvasRenderingContext2D","square","s2","ir","triangleDown","star","n","r2d","kappa","ox","oy","xe","ye","xm","ym","bezierCurveTo","wEllipse","hEllipse","ymb","yeb","xt","yt","xi","yi","xl","yl","xr","yr","dashArray","dashLength","dashCount","slope","distRemaining","dashIndex","PhysicsMixin","ClusterMixin","SectorsMixin","SelectionMixin","ManipulationMixin","NavigationMixin","HierarchicalLayoutMixin","_loadMixin","sourceVariable","mixinFunction","_clearMixin","_loadSelectedForceSolver","_loadPhysicsConfiguration","hubThreshold","activeSector","drawingNode","blockConnectingEdgeSelection","forceAppendSelection","editModeDiv","closeDiv","_cleanNavigation","_loadNavigationElements","_callbacks","once","self","removeListener","removeAllListeners","callbacks","cb","hasListeners","__WEBPACK_AMD_DEFINE_RESULT__","global","dfl","defaultParsingFlags","empty","unusedTokens","unusedInput","charsLeftOver","nullInput","invalidMonth","invalidFormat","userInvalidated","iso","deprecate","msg","printMsg","suppressDeprecationWarnings","warn","firstTime","padToken","func","leftZeroFill","ordinalizeToken","period","lang","ordinal","Language","Moment","config","checkOverflow","Duration","duration","normalizedInput","normalizeObjectUnits","years","quarters","quarter","months","month","weeks","week","days","day","hour","minute","second","millisecond","_milliseconds","_days","_months","_bubble","cloneMoment","momentProperties","absRound","number","targetLength","forceSign","output","addOrSubtractDurationFromMoment","mom","isAdding","updateOffset","_d","setTime","rawSetter","rawGetter","rawMonthSetter","input","compareArrays","dontConvert","lengthDiff","diffs","toInt","normalizeUnits","units","lowered","unitAliases","camelFunctions","inputObject","normalizedProp","makeList","setter","getter","method","_lang","results","utc","set","argumentForCoercion","coercedNumber","isFinite","daysInMonth","UTC","getUTCDate","weeksInYear","dow","doy","weekOfYear","daysInYear","isLeapYear","_a","_pf","DATE","_overflowDayOfYear","isValid","_isValid","getTime","_strict","normalizeLanguage","makeAs","model","_isUTC","zone","_offset","local","loadLang","abbr","languages","unloadLang","getLangDefinition","k","hasModule","removeFormattingTokens","makeFormatFunction","formattingTokens","formatTokenFunctions","formatMoment","expandFormat","formatFunctions","invalidDate","replaceLongDateFormatTokens","longDateFormat","localFormattingTokens","lastIndex","getParseRegexForToken","parseTokenOneDigit","parseTokenThreeDigits","parseTokenFourDigits","parseTokenOneToFourDigits","parseTokenSignedNumber","parseTokenSixDigits","parseTokenOneToSixDigits","parseTokenTwoDigits","parseTokenOneToThreeDigits","parseTokenWord","_l","_meridiemParse","parseTokenTimestampMs","parseTokenTimezone","parseTokenT","parseTokenDigits","parseTokenOneOrTwoDigits","parseTokenOrdinal","RegExp","regexpEscape","unescapeFormat","timezoneMinutesFromString","string","possibleTzMatches","tzChunk","parts","parseTimezoneChunker","addTimeToArrayFromToken","datePartArray","monthsParse","_dayOfYear","parseTwoDigitYear","_isPm","isPM","_useUTC","_tzm","weekdaysParse","_w","invalidWeekday","dayOfYearFromWeekInfo","weekYear","weekday","temp","GG","W","E","_week","gg","dayOfYearFromWeeks","dayOfYear","dateFromConfig","currentDate","yearToUse","currentDateArray","makeUTCDate","getUTCMonth","makeDate","setUTCMinutes","getUTCMinutes","dateFromObject","_i","getUTCFullYear","makeDateFromStringAndFormat","_f","ISO_8601","parseISO","parsedInput","tokens","skipped","stringLength","totalParsedInputLength","matched","p4","makeDateFromStringAndArray","tempConfig","bestMoment","scoreToBeat","currentScore","NaN","score","l","isoRegex","isoDates","isoTimes","makeDateFromString","createFromInputFallback","makeDateFromInput","aspNetJsonRegex","ms","setUTCFullYear","parseWeekday","language","substituteTimeAgo","withoutSuffix","isFuture","relativeTime","relativeTimeThresholds","dd","dm","firstDayOfWeek","firstDayOfWeekOfYear","adjustedMoment","daysToDayOfWeek","daysToAdd","getUTCDay","makeMoment","invalid","preparse","pickBy","moments","res","dayOfMonth","unit","makeAccessor","keepTime","makeDurationGetter","makeDurationAsGetter","makeGlobal","shouldDeprecate","ender","oldGlobalMoment","globalScope","VERSION","_isAMomentObject","aspNetTimeSpanJsonRegex","isoDurationRegex","isoFormat","unitMillisecondFactors","Milliseconds","Seconds","Minutes","Hours","Days","Months","Years","D","Q","DDD","dayofyear","isoweekday","isoweek","weekyear","isoweekyear","ordinalizeTokens","paddedTokens","MMM","monthsShort","MMMM","weekdaysMin","ddd","weekdaysShort","dddd","weekdays","isoWeek","YY","YYYY","YYYYY","YYYYYY","gggg","ggggg","isoWeekYear","GGGG","GGGGG","isoWeekday","meridiem","SS","SSS","SSSS","Z","ZZ","zoneAbbr","zz","zoneName","unix","lists","DDDD","_monthsShort","monthName","regex","_monthsParse","_weekdays","_weekdaysShort","_weekdaysMin","weekdayName","_weekdaysParse","_longDateFormat","LT","L","LL","LLL","LLLL","val","isLower","_calendar","sameDay","nextDay","nextWeek","lastDay","lastWeek","sameElse","calendar","_relativeTime","future","past","mm","hh","MM","yy","pastFuture","_ordinal","postformat","_invalidDate","ret","parseIso","isDuration","inp","version","defaultFormat","relativeTimeThreshold","threshold","limit","_abbr","langData","flags","parseZone","isDSTShifted","parsingFlags","invalidAt","inputString","dur","asFloat","that","zoneDiff","startOf","humanize","fromNow","sod","isDST","getDay","endOf","isAfter","isBefore","isSame","getTimezoneOffset","_changeInProgress","hasAlignedHourOffset","isoWeeksInYear","weekInfo","dates","isoWeeks","toJSON","withSuffix","difference","toIsoString","asSeconds","asMonths","require","noGlobal","setup","READY","Event","determineEventTypes","Utils","each","gestures","Detection","register","onTouch","DOCUMENT","EVENT_MOVE","detect","EVENT_END","Instance","defaults","behavior","userSelect","touchAction","touchCallout","contentZooming","userDrag","tapHighlightColor","HAS_POINTEREVENTS","pointerEnabled","msPointerEnabled","HAS_TOUCHEVENTS","IS_MOBILE","NO_MOUSEEVENTS","CALCULATE_INTERVAL","EVENT_TYPES","DIRECTION_DOWN","DIRECTION_LEFT","DIRECTION_UP","DIRECTION_RIGHT","POINTER_MOUSE","POINTER_TOUCH","POINTER_PEN","EVENT_START","EVENT_RELEASE","EVENT_TOUCH","plugins","utils","dest","handler","iterator","context","inStr","find","inArray","hasParent","getCenter","getVelocity","deltaTime","getAngle","touch1","touch2","getDirection","getScale","getRotation","isVertical","setPrefixedCss","toggle","prefixes","toCamelCase","toggleBehavior","falseFn","onselectstart","ondragstart","str","preventMouseEvents","started","shouldDetect","hook","onTouchHandler","ev","triggerType","srcType","isPointer","isMouse","buttons","PointerEvent","matchType","updatePointer","doDetect","touchList","touchListLength","triggerChange","trigger","changedLength","changedTouches","evData","identifiers","identifier","pointerType","timeStamp","preventManipulation","stopDetect","pointers","touchlist","pointerEvent","pointerId","pt","MSPOINTER_TYPE_MOUSE","MSPOINTER_TYPE_TOUCH","MSPOINTER_TYPE_PEN","detection","stopped","startDetect","inst","eventData","startEvent","lastEvent","lastCalcEvent","futureCalcEvent","lastCalcData","extendEventData","instOptions","getCalculatedData","recalc","calcEv","calcData","velocityX","velocityY","interimAngle","interimDirection","startEv","lastEv","rotation","eventStartHandler","eventHandlers","createEvent","initEvent","dispatchEvent","state","dispose","eh","dragGesture","dragMaxTouches","triggered","dragMinDistance","startCenter","dragDistanceCorrection","dragLockToAxis","dragLockMinDistance","lastDirection","dragBlockVertical","dragBlockHorizontal","Drag","Gesture","holdGesture","holdTimeout","holdThreshold","Hold","Release","Infinity","Swipe","swipeMinTouches","swipeMaxTouches","swipeVelocityX","swipeVelocityY","tapGesture","sincePrev","didDoubleTap","hasMoved","tapMaxDistance","tapMaxTime","doubleTapInterval","doubleTapDistance","tapAlways","Tap","Touch","preventMouse","transformGesture","scaleThreshold","rotationThreshold","transformMinScale","transformMinRotation","Transform","_addEvent","_characterFromEvent","fromCharCode","_MAP","_KEYCODE_MAP","_stop","tag_name","tagName","contentEditable","_modifiersMatch","modifiers1","modifiers2","_resetSequences","do_not_reset","active_sequences","_sequence_levels","_inside_sequence","_getMatches","character","modifiers","combination","matches","_isModifier","seq","combo","_eventModifiers","altKey","metaKey","_fireCallback","cancelBubble","_handleCharacter","processed_sequence_callback","_handleKey","keyCode","_ignore_next_keyup","_resetSequenceTimer","_reset_timer","_getReverseMap","_REVERSE_MAP","_pickBestAction","_bindSequence","_increaseSequence","_callbackAndReset","_bindSingle","sequence_name","sequence","_SPECIAL_ALIASES","_SHIFT_MAP","_bindMultiple","combinations",8,9,13,16,17,18,20,27,32,33,34,35,36,37,38,39,40,45,46,91,93,224,106,107,109,110,111,186,187,188,189,190,191,192,219,220,221,222,"~","!","@","#","$","%","^","&","*","(",")","_","+",":","\"","<",">","?","|","command","return","escape","_direct_map","unbind","clusterToFit","maxNumberOfNodes","reposition","maxLevels","forceAggregateHubs","normalizeClusterLevels","increaseClusterLevel","repositionNodes","openCluster","isMovingBeforeClustering","_nodeInActiveArea","_sector","_addSector","decreaseClusterLevel","_expandClusterNode","_updateDynamicEdges","updateClusters","zoomDirection","recursive","doNotStart","amountOfNodes","_collapseSector","_formClusters","_openClusters","_openClustersBySize","_aggregateHubs","handleChains","chainPercentage","_getChainFraction","_reduceAmountOfChains","_getHubSize","_formClustersByHub","openAll","containedNodeId","childNode","_expelChildFromParent","_unselectAll","_releaseContainedEdges","_connectEdgeBackToChild","_validateEdges","othersPresent","childNodeId","_repositionBezierNodes","_formClustersByZoom","_forceClustersByZoom","minLength","_addToCluster","_clusterToSmallestNeighbour","smallestNeighbour","smallestNeighbourNode","neighbour","onlyEqual","_formClusterFromHub","hubNode","absorptionSizeOffset","allowCluster","edgesIdarray","amountOfInitialEdges","_addToContainedEdges","_connectEdgeToCluster","_containCircularEdgesFromNode","massBefore","correction","edgeToId","edgeFromId","_addToReroutedEdges","maxLevel","minLevel","clusterLevel","targetLevel","average","averageSquared","hubCounter","largestHub","variance","standardDeviation","fraction","reduceAmount","chains","_switchToSector","sectorId","sectorType","_switchToActiveSector","_switchToFrozenSector","_switchToSupportSector","_loadLatestSector","_previousSector","_setActiveSector","newId","_forgetLastSector","_createNewSector","_deleteActiveSector","_deleteFrozenSector","_freezeSector","_activateSector","_mergeThisWithFrozen","_collapseThisToSingleCluster","sector","unqiueIdentifier","previousSector","runFunction","argument","_doInAllFrozenSectors","_drawSectorNodes","_drawAllSectorNodes","_getNodesOverlappingWith","overlappingNodes","_getAllNodesOverlappingWith","_pointerToPositionObject","positionObject","_getEdgesOverlappingWith","overlappingEdges","_getAllEdgesOverlappingWith","_addToSelection","_addToHover","_removeFromSelection","doNotTrigger","_unselectClusters","_getSelectedNodeCount","_getSelectedNode","_getSelectedEdge","_getSelectedEdgeCount","_getSelectedObjectCount","_selectionIsEmpty","_clusterInSelection","_selectConnectedEdges","_hoverConnectedEdges","_unselectConnectedEdges","append","highlightEdges","nodeIds","getSelectedNodes","edgeIds","getSelectedEdges","idArray","RangeError","selectNodes","selectEdges","_clearManipulatorBar","_restoreOverloadedFunctions","functionName","_toggleEditMode","toolbar","getElementById","boundFunction","edgeBeingEdited","selectedControlNode","addNodeButton","_createAddNodeToolbar","addEdgeButton","_createAddEdgeToolbar","editButton","_editNode","_createEditEdgeToolbar","editModeButton","backButton","_addNode","_handleConnect","_finishConnect","_selectControlNode","_controlNodeDrag","_releaseControlNode","newNode","_editEdge","alert","smooth","connectFromId","_createEdge","defaultData","finalizedData","sourceNodeId","targetNodeId","selectedNodes","selectedEdges","wrapper","navigationDivActions","_stopMovement","hubsize","definedLevel","undefinedLevel","_changeConstants","_determineLevels","distribution","_getDistribution","_placeNodesByHierarchy","minPos","_placeBranchNodes","maxCount","_setLevel","parentId","parentLevel","nodeMoved","_restoreNodes","graphToggleSmoothCurves","graph_toggleSmooth","graphRepositionNodes","showValueOfRange","graphGenerateOptions","optionsSpecific","radioButton1","radioButton2","checked","backupConstants","optionsDiv","switchConfigurations","radioButton","querySelector","tableId","table","constantsVariableName","valueId","rangeValue","_overWriteGraphConstants","RepulsionMixin","HierarchialRepulsionMixin","BarnesHutMixin","_toggleBarnesHut","barnesHutTree","_initializeForceCalculation","_calculateForces","_calculateGravitationalForces","_calculateNodeForces","_calculateSpringForcesWithSupport","_calculateHierarchicalSpringForces","_calculateSpringForces","supportNodes","supportNodeId","gravity","gravityForce","edgeLength","springForce","combinedClusterSize","node1","node2","node3","_calculateSpringForce","physicsConfiguration","hierarchicalLayoutDirections","parentElement","rangeElement","radioButton3","graph_repositionNodes","graph_generateOptions","nameArray","webpackContext","req","webpackContextResolve","resolve","repulsingForce","a_base","minimumDistance","steepness","springFx","springFy","totalFx","totalFy","correctionFx","correctionFy","nodeCount","_formBarnesHutTree","_getForceContribution","children","NW","NE","SW","SE","parentBranch","childrenCount","centerOfMass","calcSize","MAX_VALUE","sizeDiff","minimumTreeSize","rootSize","halfRootSize","centerX","centerY","_splitBranch","_placeInTree","_updateBranchMass","totalMass","totalMassInv","biggestSize","skipMassUpdate","_placeInRegion","region","containedNode","_insertRegion","childSize","_drawTree","_drawBranch","branch","webpackPolyfill","paths"],"mappings":"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"} \ No newline at end of file diff --git a/dist/vis.min.js b/dist/vis.min.js index 82096b01..7918d34c 100644 --- a/dist/vis.min.js +++ b/dist/vis.min.js @@ -5,7 +5,7 @@ * A dynamic, browser-based visualization library. * * @version 3.2.1-SNAPSHOT - * @date 2014-08-20 + * @date 2014-08-21 * * @license * Copyright (C) 2011-2014 Almende B.V, http://almende.com @@ -22,16 +22,16 @@ * License for the specific language governing permissions and limitations under * the License. */ -!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):"object"==typeof exports?exports.vis=e():t.vis=e()}(this,function(){return function(t){function e(s){if(i[s])return i[s].exports;var o=i[s]={exports:{},id:s,loaded:!1};return t[s].call(o.exports,o,o.exports,e),o.loaded=!0,o.exports}var i={};return e.m=t,e.c=i,e.p="",e(0)}([function(t,e,i){e.util=i(2),e.DOMutil=i(1),e.DataSet=i(3),e.DataView=i(4),e.Graph3d=i(5),e.graph3d={Camera:i(6),Filter:i(7),Point2d:i(8),Point3d:i(9),Slider:i(10),StepNumber:i(11)},e.Timeline=i(12),e.Graph2d=i(13),e.timeline={DataStep:i(14),Range:i(15),stack:i(16),TimeStep:i(17),components:{items:{Item:i(28),ItemBox:i(29),ItemPoint:i(30),ItemRange:i(31)},Component:i(19),CurrentTime:i(18),CustomTime:i(20),DataAxis:i(21),GraphGroup:i(22),Group:i(23),ItemSet:i(24),Legend:i(25),LineGraph:i(26),TimeAxis:i(27)}},e.Network=i(32),e.network={Edge:i(33),Groups:i(34),Images:i(35),Node:i(36),Popup:i(37),dotparser:i(38),gephiParser:i(39)},e.Graph=function(){throw new Error("Graph is renamed to Network. Please create a graph as new vis.Network(...)")},e.moment=i(41),e.hammer=i(40)},function(t,e){e.prepareElements=function(t){for(var e in t)t.hasOwnProperty(e)&&(t[e].redundant=t[e].used,t[e].used=[])},e.cleanupElements=function(t){for(var e in t)if(t.hasOwnProperty(e)&&t[e].redundant){for(var i=0;i0?(s=e[t].redundant[0],e[t].redundant.shift()):(s=document.createElementNS("http://www.w3.org/2000/svg",t),i.appendChild(s)):(s=document.createElementNS("http://www.w3.org/2000/svg",t),e[t]={used:[],redundant:[]},i.appendChild(s)),e[t].used.push(s),s},e.getDOMElement=function(t,e,i){var s;return e.hasOwnProperty(t)?e[t].redundant.length>0?(s=e[t].redundant[0],e[t].redundant.shift()):(s=document.createElement(t),i.appendChild(s)):(s=document.createElement(t),e[t]={used:[],redundant:[]},i.appendChild(s)),e[t].used.push(s),s},e.drawPoint=function(t,i,s,o,n){var r;return"circle"==s.options.drawPoints.style?(r=e.getSVGElement("circle",o,n),r.setAttributeNS(null,"cx",t),r.setAttributeNS(null,"cy",i),r.setAttributeNS(null,"r",.5*s.options.drawPoints.size),r.setAttributeNS(null,"class",s.className+" point")):(r=e.getSVGElement("rect",o,n),r.setAttributeNS(null,"x",t-.5*s.options.drawPoints.size),r.setAttributeNS(null,"y",i-.5*s.options.drawPoints.size),r.setAttributeNS(null,"width",s.options.drawPoints.size),r.setAttributeNS(null,"height",s.options.drawPoints.size),r.setAttributeNS(null,"class",s.className+" point")),r},e.drawBar=function(t,i,s,o,n,r,a){var h=e.getSVGElement("rect",r,a);h.setAttributeNS(null,"x",t-.5*s),h.setAttributeNS(null,"y",i),h.setAttributeNS(null,"width",s),h.setAttributeNS(null,"height",o),h.setAttributeNS(null,"class",n)}},function(module,exports,__webpack_require__){var moment=__webpack_require__(41);exports.isNumber=function(t){return t instanceof Number||"number"==typeof t},exports.isString=function(t){return t instanceof String||"string"==typeof t},exports.isDate=function(t){if(t instanceof Date)return!0;if(exports.isString(t)){var e=ASPDateRegex.exec(t);if(e)return!0;if(!isNaN(Date.parse(t)))return!0}return!1},exports.isDataTable=function(t){return"undefined"!=typeof google&&google.visualization&&google.visualization.DataTable&&t instanceof google.visualization.DataTable},exports.randomUUID=function(){var t=function(){return Math.floor(65536*Math.random()).toString(16)};return t()+t()+"-"+t()+"-"+t()+"-"+t()+"-"+t()+t()+t()},exports.extend=function(t){for(var e=1,i=arguments.length;i>e;e++){var s=arguments[e];for(var o in s)s.hasOwnProperty(o)&&(t[o]=s[o])}return t},exports.selectiveExtend=function(t,e){if(!Array.isArray(t))throw new Error("Array with property names expected as first argument");for(var i=2;ii;i++)if(t[i]!=e[i])return!1;return!0},exports.convert=function(t,e){var i;if(void 0===t)return void 0;if(null===t)return null;if(!e)return t;if("string"!=typeof e&&!(e instanceof String))throw new Error("Type must be a string");switch(e){case"boolean":case"Boolean":return Boolean(t);case"number":case"Number":return Number(t.valueOf());case"string":case"String":return String(t);case"Date":if(exports.isNumber(t))return new Date(t);if(t instanceof Date)return new Date(t.valueOf());if(moment.isMoment(t))return new Date(t.valueOf());if(exports.isString(t))return i=ASPDateRegex.exec(t),i?new Date(Number(i[1])):moment(t).toDate();throw new Error("Cannot convert object of type "+exports.getType(t)+" to type Date");case"Moment":if(exports.isNumber(t))return moment(t);if(t instanceof Date)return moment(t.valueOf());if(moment.isMoment(t))return moment(t);if(exports.isString(t))return i=ASPDateRegex.exec(t),moment(i?Number(i[1]):t);throw new Error("Cannot convert object of type "+exports.getType(t)+" to type Date");case"ISODate":if(exports.isNumber(t))return new Date(t);if(t instanceof Date)return t.toISOString();if(moment.isMoment(t))return t.toDate().toISOString();if(exports.isString(t))return i=ASPDateRegex.exec(t),i?new Date(Number(i[1])).toISOString():new Date(t).toISOString();throw new Error("Cannot convert object of type "+exports.getType(t)+" to type ISODate");case"ASPDate":if(exports.isNumber(t))return"/Date("+t+")/";if(t instanceof Date)return"/Date("+t.valueOf()+")/";if(exports.isString(t)){i=ASPDateRegex.exec(t);var s;return s=i?new Date(Number(i[1])).valueOf():new Date(t).valueOf(),"/Date("+s+")/"}throw new Error("Cannot convert object of type "+exports.getType(t)+" to type ASPDate");default:throw new Error('Unknown type "'+e+'"')}};var ASPDateRegex=/^\/?Date\((\-?\d+)/i;exports.getType=function(t){var e=typeof t;return"object"==e?null==t?"null":t instanceof Boolean?"Boolean":t instanceof Number?"Number":t instanceof String?"String":t instanceof Array?"Array":t instanceof Date?"Date":"Object":"number"==e?"Number":"boolean"==e?"Boolean":"string"==e?"String":e},exports.getAbsoluteLeft=function(t){return t.getBoundingClientRect().left+window.pageXOffset},exports.getAbsoluteTop=function(t){return t.getBoundingClientRect().top+window.pageYOffset},exports.addClassName=function(t,e){var i=t.className.split(" ");-1==i.indexOf(e)&&(i.push(e),t.className=i.join(" "))},exports.removeClassName=function(t,e){var i=t.className.split(" "),s=i.indexOf(e);-1!=s&&(i.splice(s,1),t.className=i.join(" "))},exports.forEach=function(t,e){var i,s;if(t instanceof Array)for(i=0,s=t.length;s>i;i++)e(t[i],i,t);else for(i in t)t.hasOwnProperty(i)&&e(t[i],i,t)},exports.toArray=function(t){var e=[];for(var i in t)t.hasOwnProperty(i)&&e.push(t[i]);return e},exports.updateProperty=function(t,e,i){return t[e]!==i?(t[e]=i,!0):!1},exports.addEventListener=function(t,e,i,s){t.addEventListener?(void 0===s&&(s=!1),"mousewheel"===e&&navigator.userAgent.indexOf("Firefox")>=0&&(e="DOMMouseScroll"),t.addEventListener(e,i,s)):t.attachEvent("on"+e,i)},exports.removeEventListener=function(t,e,i,s){t.removeEventListener?(void 0===s&&(s=!1),"mousewheel"===e&&navigator.userAgent.indexOf("Firefox")>=0&&(e="DOMMouseScroll"),t.removeEventListener(e,i,s)):t.detachEvent("on"+e,i)},exports.preventDefault=function(t){t||(t=window.event),t.preventDefault?t.preventDefault():t.returnValue=!1},exports.getTarget=function(t){t||(t=window.event);var e;return t.target?e=t.target:t.srcElement&&(e=t.srcElement),void 0!=e.nodeType&&3==e.nodeType&&(e=e.parentNode),e},exports.option={},exports.option.asBoolean=function(t,e){return"function"==typeof t&&(t=t()),null!=t?0!=t:e||null},exports.option.asNumber=function(t,e){return"function"==typeof t&&(t=t()),null!=t?Number(t)||e||null:e||null},exports.option.asString=function(t,e){return"function"==typeof t&&(t=t()),null!=t?String(t):e||null},exports.option.asSize=function(t,e){return"function"==typeof t&&(t=t()),exports.isString(t)?t:exports.isNumber(t)?t+"px":e||null},exports.option.asElement=function(t,e){return"function"==typeof t&&(t=t()),t||e||null},exports.GiveDec=function(Hex){var Value;return Value="A"==Hex?10:"B"==Hex?11:"C"==Hex?12:"D"==Hex?13:"E"==Hex?14:"F"==Hex?15:eval(Hex)},exports.GiveHex=function(t){var e;return e=10==t?"A":11==t?"B":12==t?"C":13==t?"D":14==t?"E":15==t?"F":""+t},exports.parseColor=function(t){var e;if(exports.isString(t)){if(exports.isValidRGB(t)){var i=t.substr(4).substr(0,t.length-5).split(",");t=exports.RGBToHex(i[0],i[1],i[2])}if(exports.isValidHex(t)){var s=exports.hexToHSV(t),o={h:s.h,s:.45*s.s,v:Math.min(1,1.05*s.v)},n={h:s.h,s:Math.min(1,1.25*s.v),v:.6*s.v},r=exports.HSVToHex(n.h,n.h,n.v),a=exports.HSVToHex(o.h,o.s,o.v);e={background:t,border:r,highlight:{background:a,border:r},hover:{background:a,border:r}}}else e={background:t,border:t,highlight:{background:t,border:t},hover:{background:t,border:t}}}else e={},e.background=t.background||"white",e.border=t.border||e.background,exports.isString(t.highlight)?e.highlight={border:t.highlight,background:t.highlight}:(e.highlight={},e.highlight.background=t.highlight&&t.highlight.background||e.background,e.highlight.border=t.highlight&&t.highlight.border||e.border),exports.isString(t.hover)?e.hover={border:t.hover,background:t.hover}:(e.hover={},e.hover.background=t.hover&&t.hover.background||e.background,e.hover.border=t.hover&&t.hover.border||e.border);return e},exports.hexToRGB=function(t){t=t.replace("#","").toUpperCase();var e=exports.GiveDec(t.substring(0,1)),i=exports.GiveDec(t.substring(1,2)),s=exports.GiveDec(t.substring(2,3)),o=exports.GiveDec(t.substring(3,4)),n=exports.GiveDec(t.substring(4,5)),r=exports.GiveDec(t.substring(5,6)),a=16*e+i,h=16*s+o,i=16*n+r;return{r:a,g:h,b:i}},exports.RGBToHex=function(t,e,i){var s=exports.GiveHex(Math.floor(t/16)),o=exports.GiveHex(t%16),n=exports.GiveHex(Math.floor(e/16)),r=exports.GiveHex(e%16),a=exports.GiveHex(Math.floor(i/16)),h=exports.GiveHex(i%16),d=s+o+n+r+a+h;return"#"+d},exports.RGBToHSV=function(t,e,i){t/=255,e/=255,i/=255;var s=Math.min(t,Math.min(e,i)),o=Math.max(t,Math.max(e,i));if(s==o)return{h:0,s:0,v:s};var n=t==s?e-i:i==s?t-e:i-t,r=t==s?3:i==s?1:5,a=60*(r-n/(o-s))/360,h=(o-s)/o,d=o;return{h:a,s:h,v:d}},exports.HSVToRGB=function(t,e,i){var s,o,n,r=Math.floor(6*t),a=6*t-r,h=i*(1-e),d=i*(1-a*e),l=i*(1-(1-a)*e);switch(r%6){case 0:s=i,o=l,n=h;break;case 1:s=d,o=i,n=h;break;case 2:s=h,o=i,n=l;break;case 3:s=h,o=d,n=i;break;case 4:s=l,o=h,n=i;break;case 5:s=i,o=h,n=d}return{r:Math.floor(255*s),g:Math.floor(255*o),b:Math.floor(255*n)}},exports.HSVToHex=function(t,e,i){var s=exports.HSVToRGB(t,e,i);return exports.RGBToHex(s.r,s.g,s.b)},exports.hexToHSV=function(t){var e=exports.hexToRGB(t);return exports.RGBToHSV(e.r,e.g,e.b)},exports.isValidHex=function(t){var e=/(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test(t);return e},exports.isValidRGB=function(t){t=t.replace(" ","");var e=/rgb\((\d{1,3}),(\d{1,3}),(\d{1,3})\)/i.test(t);return e},exports.selectiveBridgeObject=function(t,e){if("object"==typeof e){for(var i=Object.create(e),s=0;sa;)o=void 0===s?n[u][i]:n[u][i][s],n[u].isVisible(e)?h=!0:(o=r&&console.log("BinarySearch too many iterations. Aborting.")}return u},exports.binarySearchGeneric=function(t,e,i,s){var o,n,r,a,h=1e4,d=0,l=t,c=!1,p=0,u=l.length,f=p,m=u,g=Math.floor(.5*(u+p));if(0==u)g=-1;else if(1==u)r=l[g][i],g=r==e?0:-1;else{for(u-=1;0==c&&h>d;)n=l[Math.max(0,g-1)][i],r=l[g][i],a=l[Math.min(l.length-1,g+1)][i],r==e||e>n&&r>e||e>r&&a>e?(c=!0,r!=e&&("before"==s?e>n&&r>e&&(g=Math.max(0,g-1)):e>r&&a>e&&(g=Math.min(l.length-1,g+1)))):(e>r?f=Math.floor(.5*(u+p)):m=Math.floor(.5*(u+p)),o=Math.floor(.5*(u+p)),p==f&&u==m?(g=-1,c=!0):(u=m,p=f,g=Math.floor(.5*(u+p)))),d++;d>=h&&console.log("BinarySearch too many iterations. Aborting.")}return g}},function(t,e,i){function s(t,e){if(!t||Array.isArray(t)||o.isDataTable(t)||(e=t,t=null),this._options=e||{},this._data={},this._fieldId=this._options.fieldId||"id",this._type={},this._options.type)for(var i in this._options.type)if(this._options.type.hasOwnProperty(i)){var s=this._options.type[i];this._type[i]="Date"==s||"ISODate"==s||"ASPDate"==s?"Date":s}if(this._options.convert)throw new Error('Option "convert" is deprecated. Use "type" instead.');this._subscribers={},t&&this.add(t)}var o=i(2);s.prototype.on=function(t,e){var i=this._subscribers[t];i||(i=[],this._subscribers[t]=i),i.push({callback:e})},s.prototype.subscribe=s.prototype.on,s.prototype.off=function(t,e){var i=this._subscribers[t];i&&(this._subscribers[t]=i.filter(function(t){return t.callback!=e}))},s.prototype.unsubscribe=s.prototype.off,s.prototype._trigger=function(t,e,i){if("*"==t)throw new Error("Cannot trigger event *");var s=[];t in this._subscribers&&(s=s.concat(this._subscribers[t])),"*"in this._subscribers&&(s=s.concat(this._subscribers["*"]));for(var o=0;or;r++)i=n._addItem(t[r]),s.push(i);else if(o.isDataTable(t))for(var h=this._getColumnNames(t),d=0,l=t.getNumberOfRows();l>d;d++){for(var c={},p=0,u=h.length;u>p;p++){var f=h[p];c[f]=t.getValue(d,p)}i=n._addItem(c),s.push(i)}else{if(!(t instanceof Object))throw new Error("Unknown dataType");i=n._addItem(t),s.push(i)}return s.length&&this._trigger("add",{items:s},e),s},s.prototype.update=function(t,e){var i=[],s=[],n=this,r=n._fieldId,a=function(t){var e=t[r];n._data[e]?(e=n._updateItem(t),s.push(e)):(e=n._addItem(t),i.push(e))};if(Array.isArray(t))for(var h=0,d=t.length;d>h;h++)a(t[h]);else if(o.isDataTable(t))for(var l=this._getColumnNames(t),c=0,p=t.getNumberOfRows();p>c;c++){for(var u={},f=0,m=l.length;m>f;f++){var g=l[f];u[g]=t.getValue(c,f)}a(u)}else{if(!(t instanceof Object))throw new Error("Unknown dataType");a(t)}return i.length&&this._trigger("add",{items:i},e),s.length&&this._trigger("update",{items:s},e),i.concat(s)},s.prototype.get=function(){var t,e,i,s,n=this,r=o.getType(arguments[0]);"String"==r||"Number"==r?(t=arguments[0],i=arguments[1],s=arguments[2]):"Array"==r?(e=arguments[0],i=arguments[1],s=arguments[2]):(i=arguments[0],s=arguments[1]);var a;if(i&&i.returnType){var h=["DataTable","Array","Object"];if(a=-1==h.indexOf(i.returnType)?"Array":i.returnType,s&&a!=o.getType(s))throw new Error('Type of parameter "data" ('+o.getType(s)+") does not correspond with specified options.type ("+i.type+")");if("DataTable"==a&&!o.isDataTable(s))throw new Error('Parameter "data" must be a DataTable when options.type is "DataTable"')}else a=s&&"DataTable"==o.getType(s)?"DataTable":"Array";var d,l,c,p,u=i&&i.type||this._options.type,f=i&&i.filter,m=[];if(void 0!=t)d=n._getItem(t,u),f&&!f(d)&&(d=null);else if(void 0!=e)for(c=0,p=e.length;p>c;c++)d=n._getItem(e[c],u),(!f||f(d))&&m.push(d);else for(l in this._data)this._data.hasOwnProperty(l)&&(d=n._getItem(l,u),(!f||f(d))&&m.push(d));if(i&&i.order&&void 0==t&&this._sort(m,i.order),i&&i.fields){var g=i.fields;if(void 0!=t)d=this._filterFields(d,g);else for(c=0,p=m.length;p>c;c++)m[c]=this._filterFields(m[c],g)}if("DataTable"==a){var v=this._getColumnNames(s);if(void 0!=t)n._appendRow(s,v,d);else for(c=0;cc;c++)s.push(m[c]);return s}return m},s.prototype.getIds=function(t){var e,i,s,o,n,r=this._data,a=t&&t.filter,h=t&&t.order,d=t&&t.type||this._options.type,l=[];if(a)if(h){n=[];for(s in r)r.hasOwnProperty(s)&&(o=this._getItem(s,d),a(o)&&n.push(o));for(this._sort(n,h),e=0,i=n.length;i>e;e++)l[e]=n[e][this._fieldId]}else for(s in r)r.hasOwnProperty(s)&&(o=this._getItem(s,d),a(o)&&l.push(o[this._fieldId]));else if(h){n=[];for(s in r)r.hasOwnProperty(s)&&n.push(r[s]);for(this._sort(n,h),e=0,i=n.length;i>e;e++)l[e]=n[e][this._fieldId]}else for(s in r)r.hasOwnProperty(s)&&(o=r[s],l.push(o[this._fieldId]));return l},s.prototype.getDataSet=function(){return this},s.prototype.forEach=function(t,e){var i,s,o=e&&e.filter,n=e&&e.type||this._options.type,r=this._data;if(e&&e.order)for(var a=this.get(e),h=0,d=a.length;d>h;h++)i=a[h],s=i[this._fieldId],t(i,s);else for(s in r)r.hasOwnProperty(s)&&(i=this._getItem(s,n),(!o||o(i))&&t(i,s))},s.prototype.map=function(t,e){var i,s=e&&e.filter,o=e&&e.type||this._options.type,n=[],r=this._data;for(var a in r)r.hasOwnProperty(a)&&(i=this._getItem(a,o),(!s||s(i))&&n.push(t(i,a)));return e&&e.order&&this._sort(n,e.order),n},s.prototype._filterFields=function(t,e){var i={};for(var s in t)t.hasOwnProperty(s)&&-1!=e.indexOf(s)&&(i[s]=t[s]);return i},s.prototype._sort=function(t,e){if(o.isString(e)){var i=e;t.sort(function(t,e){var s=t[i],o=e[i];return s>o?1:o>s?-1:0})}else{if("function"!=typeof e)throw new TypeError("Order must be a function or a string");t.sort(e)}},s.prototype.remove=function(t,e){var i,s,o,n=[];if(Array.isArray(t))for(i=0,s=t.length;s>i;i++)o=this._remove(t[i]),null!=o&&n.push(o);else o=this._remove(t),null!=o&&n.push(o);return n.length&&this._trigger("remove",{items:n},e),n},s.prototype._remove=function(t){if(o.isNumber(t)||o.isString(t)){if(this._data[t])return delete this._data[t],t}else if(t instanceof Object){var e=t[this._fieldId];if(e&&this._data[e])return delete this._data[e],e}return null},s.prototype.clear=function(t){var e=Object.keys(this._data);return this._data={},this._trigger("remove",{items:e},t),e},s.prototype.max=function(t){var e=this._data,i=null,s=null;for(var o in e)if(e.hasOwnProperty(o)){var n=e[o],r=n[t];null!=r&&(!i||r>s)&&(i=n,s=r)}return i},s.prototype.min=function(t){var e=this._data,i=null,s=null;for(var o in e)if(e.hasOwnProperty(o)){var n=e[o],r=n[t];null!=r&&(!i||s>r)&&(i=n,s=r)}return i},s.prototype.distinct=function(t){var e,i=this._data,s=[],n=this._options.type&&this._options.type[t]||null,r=0;for(var a in i)if(i.hasOwnProperty(a)){var h=i[a],d=h[t],l=!1;for(e=0;r>e;e++)if(s[e]==d){l=!0;break}l||void 0===d||(s[r]=d,r++)}if(n)for(e=0;ei;i++)e[i]=t.getColumnId(i)||t.getColumnLabel(i);return e},s.prototype._appendRow=function(t,e,i){for(var s=t.addRow(),o=0,n=e.length;n>o;o++){var r=e[o];t.setValue(s,o,i[r])}},t.exports=s},function(t,e,i){function s(t,e){this._data=null,this._ids={},this._options=e||{},this._fieldId="id",this._subscribers={};var i=this;this.listener=function(){i._onEvent.apply(i,arguments)},this.setData(t)}var o=i(2),n=i(3);s.prototype.setData=function(t){var e,i,s;if(this._data){this._data.unsubscribe&&this._data.unsubscribe("*",this.listener),e=[];for(var o in this._ids)this._ids.hasOwnProperty(o)&&e.push(o);this._ids={},this._trigger("remove",{items:e})}if(this._data=t,this._data){for(this._fieldId=this._options.fieldId||this._data&&this._data.options&&this._data.options.fieldId||"id",e=this._data.getIds({filter:this._options&&this._options.filter}),i=0,s=e.length;s>i;i++)o=e[i],this._ids[o]=!0;this._trigger("add",{items:e}),this._data.on&&this._data.on("*",this.listener)}},s.prototype.get=function(){var t,e,i,s=this,n=o.getType(arguments[0]);"String"==n||"Number"==n||"Array"==n?(t=arguments[0],e=arguments[1],i=arguments[2]):(e=arguments[0],i=arguments[1]);var r=o.extend({},this._options,e);this._options.filter&&e&&e.filter&&(r.filter=function(t){return s._options.filter(t)&&e.filter(t)});var a=[];return void 0!=t&&a.push(t),a.push(r),a.push(i),this._data&&this._data.get.apply(this._data,a)},s.prototype.getIds=function(t){var e;if(this._data){var i,s=this._options.filter;i=t&&t.filter?s?function(e){return s(e)&&t.filter(e)}:t.filter:s,e=this._data.getIds({filter:i,order:t&&t.order})}else e=[];return e},s.prototype.getDataSet=function(){for(var t=this;t instanceof s;)t=t._data;return t||null},s.prototype._onEvent=function(t,e,i){var s,o,n,r,a=e&&e.items,h=this._data,d=[],l=[],c=[];if(a&&h){switch(t){case"add":for(s=0,o=a.length;o>s;s++)n=a[s],r=this.get(n),r&&(this._ids[n]=!0,d.push(n));break;case"update":for(s=0,o=a.length;o>s;s++)n=a[s],r=this.get(n),r?this._ids[n]?l.push(n):(this._ids[n]=!0,d.push(n)):this._ids[n]&&(delete this._ids[n],c.push(n));break;case"remove":for(s=0,o=a.length;o>s;s++)n=a[s],this._ids[n]&&(delete this._ids[n],c.push(n))}d.length&&this._trigger("add",{items:d},i),l.length&&this._trigger("update",{items:l},i),c.length&&this._trigger("remove",{items:c},i)}},s.prototype.on=n.prototype.on,s.prototype.off=n.prototype.off,s.prototype._trigger=n.prototype._trigger,s.prototype.subscribe=s.prototype.on,s.prototype.unsubscribe=s.prototype.off,t.exports=s},function(t,e,i){function s(t,e,i){if(!(this instanceof s))throw new SyntaxError("Constructor must be called with the new operator");this.containerElement=t,this.width="400px",this.height="400px",this.margin=10,this.defaultXCenter="55%",this.defaultYCenter="50%",this.xLabel="x",this.yLabel="y",this.zLabel="z",this.filterLabel="time",this.legendLabel="value",this.style=s.STYLE.DOT,this.showPerspective=!0,this.showGrid=!0,this.keepAspectRatio=!0,this.showShadow=!1,this.showGrayBottom=!1,this.showTooltip=!1,this.verticalRatio=.5,this.animationInterval=1e3,this.animationPreload=!1,this.camera=new l,this.eye=new h(0,0,-1),this.dataTable=null,this.dataPoints=null,this.colX=void 0,this.colY=void 0,this.colZ=void 0,this.colValue=void 0,this.colFilter=void 0,this.xMin=0,this.xStep=void 0,this.xMax=1,this.yMin=0,this.yStep=void 0,this.yMax=1,this.zMin=0,this.zStep=void 0,this.zMax=1,this.valueMin=0,this.valueMax=1,this.xBarWidth=1,this.yBarWidth=1,this.colorAxis="#4D4D4D",this.colorGrid="#D3D3D3",this.colorDot="#7DC1FF",this.colorDotBorder="#3267D2",this.create(),this.setOptions(i),e&&this.setData(e)}var o=i(46),n=i(3),r=i(4),a=i(2),h=i(9),d=i(8),l=i(6),c=i(7),p=i(10),u=i(11);o(s.prototype),s.prototype._setScale=function(){this.scale=new h(1/(this.xMax-this.xMin),1/(this.yMax-this.yMin),1/(this.zMax-this.zMin)),this.keepAspectRatio&&(this.scale.x3&&(this.colFilter=3);else{if(this.style!==s.STYLE.DOTCOLOR&&this.style!==s.STYLE.DOTSIZE&&this.style!==s.STYLE.BARCOLOR&&this.style!==s.STYLE.BARSIZE)throw'Unknown style "'+this.style+'"';this.colX=0,this.colY=1,this.colZ=2,this.colValue=3,t.getNumberOfColumns()>4&&(this.colFilter=4)}},s.prototype.getNumberOfRows=function(t){return t.length},s.prototype.getNumberOfColumns=function(t){var e=0;for(var i in t[0])t[0].hasOwnProperty(i)&&e++;return e},s.prototype.getDistinctValues=function(t,e){for(var i=[],s=0;st[s][e]&&(i.min=t[s][e]),i.maxe;e++){var s=arguments[e];for(var o in s)s.hasOwnProperty(o)&&(t[o]=s[o])}return t},exports.selectiveExtend=function(t,e){if(!Array.isArray(t))throw new Error("Array with property names expected as first argument");for(var i=2;ii;i++)if(t[i]!=e[i])return!1;return!0},exports.convert=function(t,e){var i;if(void 0===t)return void 0;if(null===t)return null;if(!e)return t;if("string"!=typeof e&&!(e instanceof String))throw new Error("Type must be a string");switch(e){case"boolean":case"Boolean":return Boolean(t);case"number":case"Number":return Number(t.valueOf());case"string":case"String":return String(t);case"Date":if(exports.isNumber(t))return new Date(t);if(t instanceof Date)return new Date(t.valueOf());if(moment.isMoment(t))return new Date(t.valueOf());if(exports.isString(t))return i=ASPDateRegex.exec(t),i?new Date(Number(i[1])):moment(t).toDate();throw new Error("Cannot convert object of type "+exports.getType(t)+" to type Date");case"Moment":if(exports.isNumber(t))return moment(t);if(t instanceof Date)return moment(t.valueOf());if(moment.isMoment(t))return moment(t);if(exports.isString(t))return i=ASPDateRegex.exec(t),moment(i?Number(i[1]):t);throw new Error("Cannot convert object of type "+exports.getType(t)+" to type Date");case"ISODate":if(exports.isNumber(t))return new Date(t);if(t instanceof Date)return t.toISOString();if(moment.isMoment(t))return t.toDate().toISOString();if(exports.isString(t))return i=ASPDateRegex.exec(t),i?new Date(Number(i[1])).toISOString():new Date(t).toISOString();throw new Error("Cannot convert object of type "+exports.getType(t)+" to type ISODate");case"ASPDate":if(exports.isNumber(t))return"/Date("+t+")/";if(t instanceof Date)return"/Date("+t.valueOf()+")/";if(exports.isString(t)){i=ASPDateRegex.exec(t);var s;return s=i?new Date(Number(i[1])).valueOf():new Date(t).valueOf(),"/Date("+s+")/"}throw new Error("Cannot convert object of type "+exports.getType(t)+" to type ASPDate");default:throw new Error('Unknown type "'+e+'"')}};var ASPDateRegex=/^\/?Date\((\-?\d+)/i;exports.getType=function(t){var e=typeof t;return"object"==e?null==t?"null":t instanceof Boolean?"Boolean":t instanceof Number?"Number":t instanceof String?"String":t instanceof Array?"Array":t instanceof Date?"Date":"Object":"number"==e?"Number":"boolean"==e?"Boolean":"string"==e?"String":e},exports.getAbsoluteLeft=function(t){return t.getBoundingClientRect().left+window.pageXOffset},exports.getAbsoluteTop=function(t){return t.getBoundingClientRect().top+window.pageYOffset},exports.addClassName=function(t,e){var i=t.className.split(" ");-1==i.indexOf(e)&&(i.push(e),t.className=i.join(" "))},exports.removeClassName=function(t,e){var i=t.className.split(" "),s=i.indexOf(e);-1!=s&&(i.splice(s,1),t.className=i.join(" "))},exports.forEach=function(t,e){var i,s;if(t instanceof Array)for(i=0,s=t.length;s>i;i++)e(t[i],i,t);else for(i in t)t.hasOwnProperty(i)&&e(t[i],i,t)},exports.toArray=function(t){var e=[];for(var i in t)t.hasOwnProperty(i)&&e.push(t[i]);return e},exports.updateProperty=function(t,e,i){return t[e]!==i?(t[e]=i,!0):!1},exports.addEventListener=function(t,e,i,s){t.addEventListener?(void 0===s&&(s=!1),"mousewheel"===e&&navigator.userAgent.indexOf("Firefox")>=0&&(e="DOMMouseScroll"),t.addEventListener(e,i,s)):t.attachEvent("on"+e,i)},exports.removeEventListener=function(t,e,i,s){t.removeEventListener?(void 0===s&&(s=!1),"mousewheel"===e&&navigator.userAgent.indexOf("Firefox")>=0&&(e="DOMMouseScroll"),t.removeEventListener(e,i,s)):t.detachEvent("on"+e,i)},exports.preventDefault=function(t){t||(t=window.event),t.preventDefault?t.preventDefault():t.returnValue=!1},exports.getTarget=function(t){t||(t=window.event);var e;return t.target?e=t.target:t.srcElement&&(e=t.srcElement),void 0!=e.nodeType&&3==e.nodeType&&(e=e.parentNode),e},exports.option={},exports.option.asBoolean=function(t,e){return"function"==typeof t&&(t=t()),null!=t?0!=t:e||null},exports.option.asNumber=function(t,e){return"function"==typeof t&&(t=t()),null!=t?Number(t)||e||null:e||null},exports.option.asString=function(t,e){return"function"==typeof t&&(t=t()),null!=t?String(t):e||null},exports.option.asSize=function(t,e){return"function"==typeof t&&(t=t()),exports.isString(t)?t:exports.isNumber(t)?t+"px":e||null},exports.option.asElement=function(t,e){return"function"==typeof t&&(t=t()),t||e||null},exports.GiveDec=function(Hex){var Value;return Value="A"==Hex?10:"B"==Hex?11:"C"==Hex?12:"D"==Hex?13:"E"==Hex?14:"F"==Hex?15:eval(Hex)},exports.GiveHex=function(t){var e;return e=10==t?"A":11==t?"B":12==t?"C":13==t?"D":14==t?"E":15==t?"F":""+t},exports.parseColor=function(t){var e;if(exports.isString(t)){if(exports.isValidRGB(t)){var i=t.substr(4).substr(0,t.length-5).split(",");t=exports.RGBToHex(i[0],i[1],i[2])}if(exports.isValidHex(t)){var s=exports.hexToHSV(t),o={h:s.h,s:.45*s.s,v:Math.min(1,1.05*s.v)},n={h:s.h,s:Math.min(1,1.25*s.v),v:.6*s.v},r=exports.HSVToHex(n.h,n.h,n.v),a=exports.HSVToHex(o.h,o.s,o.v);e={background:t,border:r,highlight:{background:a,border:r},hover:{background:a,border:r}}}else e={background:t,border:t,highlight:{background:t,border:t},hover:{background:t,border:t}}}else e={},e.background=t.background||"white",e.border=t.border||e.background,exports.isString(t.highlight)?e.highlight={border:t.highlight,background:t.highlight}:(e.highlight={},e.highlight.background=t.highlight&&t.highlight.background||e.background,e.highlight.border=t.highlight&&t.highlight.border||e.border),exports.isString(t.hover)?e.hover={border:t.hover,background:t.hover}:(e.hover={},e.hover.background=t.hover&&t.hover.background||e.background,e.hover.border=t.hover&&t.hover.border||e.border);return e},exports.hexToRGB=function(t){t=t.replace("#","").toUpperCase();var e=exports.GiveDec(t.substring(0,1)),i=exports.GiveDec(t.substring(1,2)),s=exports.GiveDec(t.substring(2,3)),o=exports.GiveDec(t.substring(3,4)),n=exports.GiveDec(t.substring(4,5)),r=exports.GiveDec(t.substring(5,6)),a=16*e+i,h=16*s+o,i=16*n+r;return{r:a,g:h,b:i}},exports.RGBToHex=function(t,e,i){var s=exports.GiveHex(Math.floor(t/16)),o=exports.GiveHex(t%16),n=exports.GiveHex(Math.floor(e/16)),r=exports.GiveHex(e%16),a=exports.GiveHex(Math.floor(i/16)),h=exports.GiveHex(i%16),d=s+o+n+r+a+h;return"#"+d},exports.RGBToHSV=function(t,e,i){t/=255,e/=255,i/=255;var s=Math.min(t,Math.min(e,i)),o=Math.max(t,Math.max(e,i));if(s==o)return{h:0,s:0,v:s};var n=t==s?e-i:i==s?t-e:i-t,r=t==s?3:i==s?1:5,a=60*(r-n/(o-s))/360,h=(o-s)/o,d=o;return{h:a,s:h,v:d}},exports.HSVToRGB=function(t,e,i){var s,o,n,r=Math.floor(6*t),a=6*t-r,h=i*(1-e),d=i*(1-a*e),l=i*(1-(1-a)*e);switch(r%6){case 0:s=i,o=l,n=h;break;case 1:s=d,o=i,n=h;break;case 2:s=h,o=i,n=l;break;case 3:s=h,o=d,n=i;break;case 4:s=l,o=h,n=i;break;case 5:s=i,o=h,n=d}return{r:Math.floor(255*s),g:Math.floor(255*o),b:Math.floor(255*n)}},exports.HSVToHex=function(t,e,i){var s=exports.HSVToRGB(t,e,i);return exports.RGBToHex(s.r,s.g,s.b)},exports.hexToHSV=function(t){var e=exports.hexToRGB(t);return exports.RGBToHSV(e.r,e.g,e.b)},exports.isValidHex=function(t){var e=/(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test(t);return e},exports.isValidRGB=function(t){t=t.replace(" ","");var e=/rgb\((\d{1,3}),(\d{1,3}),(\d{1,3})\)/i.test(t);return e},exports.selectiveBridgeObject=function(t,e){if("object"==typeof e){for(var i=Object.create(e),s=0;sa;)o=void 0===s?n[u][i]:n[u][i][s],n[u].isVisible(e)?h=!0:(o=r&&console.log("BinarySearch too many iterations. Aborting.")}return u},exports.binarySearchGeneric=function(t,e,i,s){var o,n,r,a,h=1e4,d=0,l=t,c=!1,p=0,u=l.length,f=p,m=u,g=Math.floor(.5*(u+p));if(0==u)g=-1;else if(1==u)r=l[g][i],g=r==e?0:-1;else{for(u-=1;0==c&&h>d;)n=l[Math.max(0,g-1)][i],r=l[g][i],a=l[Math.min(l.length-1,g+1)][i],r==e||e>n&&r>e||e>r&&a>e?(c=!0,r!=e&&("before"==s?e>n&&r>e&&(g=Math.max(0,g-1)):e>r&&a>e&&(g=Math.min(l.length-1,g+1)))):(e>r?f=Math.floor(.5*(u+p)):m=Math.floor(.5*(u+p)),o=Math.floor(.5*(u+p)),p==f&&u==m?(g=-1,c=!0):(u=m,p=f,g=Math.floor(.5*(u+p)))),d++;d>=h&&console.log("BinarySearch too many iterations. Aborting.")}return g}},function(t,e){e.prepareElements=function(t){for(var e in t)t.hasOwnProperty(e)&&(t[e].redundant=t[e].used,t[e].used=[])},e.cleanupElements=function(t){for(var e in t)if(t.hasOwnProperty(e)&&t[e].redundant){for(var i=0;i0?(s=e[t].redundant[0],e[t].redundant.shift()):(s=document.createElementNS("http://www.w3.org/2000/svg",t),i.appendChild(s)):(s=document.createElementNS("http://www.w3.org/2000/svg",t),e[t]={used:[],redundant:[]},i.appendChild(s)),e[t].used.push(s),s},e.getDOMElement=function(t,e,i){var s;return e.hasOwnProperty(t)?e[t].redundant.length>0?(s=e[t].redundant[0],e[t].redundant.shift()):(s=document.createElement(t),i.appendChild(s)):(s=document.createElement(t),e[t]={used:[],redundant:[]},i.appendChild(s)),e[t].used.push(s),s},e.drawPoint=function(t,i,s,o,n){var r;return"circle"==s.options.drawPoints.style?(r=e.getSVGElement("circle",o,n),r.setAttributeNS(null,"cx",t),r.setAttributeNS(null,"cy",i),r.setAttributeNS(null,"r",.5*s.options.drawPoints.size),r.setAttributeNS(null,"class",s.className+" point")):(r=e.getSVGElement("rect",o,n),r.setAttributeNS(null,"x",t-.5*s.options.drawPoints.size),r.setAttributeNS(null,"y",i-.5*s.options.drawPoints.size),r.setAttributeNS(null,"width",s.options.drawPoints.size),r.setAttributeNS(null,"height",s.options.drawPoints.size),r.setAttributeNS(null,"class",s.className+" point")),r},e.drawBar=function(t,i,s,o,n,r,a){var h=e.getSVGElement("rect",r,a);h.setAttributeNS(null,"x",t-.5*s),h.setAttributeNS(null,"y",i),h.setAttributeNS(null,"width",s),h.setAttributeNS(null,"height",o),h.setAttributeNS(null,"class",n)}},function(t,e,i){function s(t,e){if(!t||Array.isArray(t)||o.isDataTable(t)||(e=t,t=null),this._options=e||{},this._data={},this._fieldId=this._options.fieldId||"id",this._type={},this._options.type)for(var i in this._options.type)if(this._options.type.hasOwnProperty(i)){var s=this._options.type[i];this._type[i]="Date"==s||"ISODate"==s||"ASPDate"==s?"Date":s}if(this._options.convert)throw new Error('Option "convert" is deprecated. Use "type" instead.');this._subscribers={},t&&this.add(t)}var o=i(1);s.prototype.on=function(t,e){var i=this._subscribers[t];i||(i=[],this._subscribers[t]=i),i.push({callback:e})},s.prototype.subscribe=s.prototype.on,s.prototype.off=function(t,e){var i=this._subscribers[t];i&&(this._subscribers[t]=i.filter(function(t){return t.callback!=e}))},s.prototype.unsubscribe=s.prototype.off,s.prototype._trigger=function(t,e,i){if("*"==t)throw new Error("Cannot trigger event *");var s=[];t in this._subscribers&&(s=s.concat(this._subscribers[t])),"*"in this._subscribers&&(s=s.concat(this._subscribers["*"]));for(var o=0;or;r++)i=n._addItem(t[r]),s.push(i);else if(o.isDataTable(t))for(var h=this._getColumnNames(t),d=0,l=t.getNumberOfRows();l>d;d++){for(var c={},p=0,u=h.length;u>p;p++){var f=h[p];c[f]=t.getValue(d,p)}i=n._addItem(c),s.push(i)}else{if(!(t instanceof Object))throw new Error("Unknown dataType");i=n._addItem(t),s.push(i)}return s.length&&this._trigger("add",{items:s},e),s},s.prototype.update=function(t,e){var i=[],s=[],n=this,r=n._fieldId,a=function(t){var e=t[r];n._data[e]?(e=n._updateItem(t),s.push(e)):(e=n._addItem(t),i.push(e))};if(Array.isArray(t))for(var h=0,d=t.length;d>h;h++)a(t[h]);else if(o.isDataTable(t))for(var l=this._getColumnNames(t),c=0,p=t.getNumberOfRows();p>c;c++){for(var u={},f=0,m=l.length;m>f;f++){var g=l[f];u[g]=t.getValue(c,f)}a(u)}else{if(!(t instanceof Object))throw new Error("Unknown dataType");a(t)}return i.length&&this._trigger("add",{items:i},e),s.length&&this._trigger("update",{items:s},e),i.concat(s)},s.prototype.get=function(){var t,e,i,s,n=this,r=o.getType(arguments[0]);"String"==r||"Number"==r?(t=arguments[0],i=arguments[1],s=arguments[2]):"Array"==r?(e=arguments[0],i=arguments[1],s=arguments[2]):(i=arguments[0],s=arguments[1]);var a;if(i&&i.returnType){var h=["DataTable","Array","Object"];if(a=-1==h.indexOf(i.returnType)?"Array":i.returnType,s&&a!=o.getType(s))throw new Error('Type of parameter "data" ('+o.getType(s)+") does not correspond with specified options.type ("+i.type+")");if("DataTable"==a&&!o.isDataTable(s))throw new Error('Parameter "data" must be a DataTable when options.type is "DataTable"')}else a=s&&"DataTable"==o.getType(s)?"DataTable":"Array";var d,l,c,p,u=i&&i.type||this._options.type,f=i&&i.filter,m=[];if(void 0!=t)d=n._getItem(t,u),f&&!f(d)&&(d=null);else if(void 0!=e)for(c=0,p=e.length;p>c;c++)d=n._getItem(e[c],u),(!f||f(d))&&m.push(d);else for(l in this._data)this._data.hasOwnProperty(l)&&(d=n._getItem(l,u),(!f||f(d))&&m.push(d));if(i&&i.order&&void 0==t&&this._sort(m,i.order),i&&i.fields){var g=i.fields;if(void 0!=t)d=this._filterFields(d,g);else for(c=0,p=m.length;p>c;c++)m[c]=this._filterFields(m[c],g)}if("DataTable"==a){var v=this._getColumnNames(s);if(void 0!=t)n._appendRow(s,v,d);else for(c=0;cc;c++)s.push(m[c]);return s}return m},s.prototype.getIds=function(t){var e,i,s,o,n,r=this._data,a=t&&t.filter,h=t&&t.order,d=t&&t.type||this._options.type,l=[];if(a)if(h){n=[];for(s in r)r.hasOwnProperty(s)&&(o=this._getItem(s,d),a(o)&&n.push(o));for(this._sort(n,h),e=0,i=n.length;i>e;e++)l[e]=n[e][this._fieldId]}else for(s in r)r.hasOwnProperty(s)&&(o=this._getItem(s,d),a(o)&&l.push(o[this._fieldId]));else if(h){n=[];for(s in r)r.hasOwnProperty(s)&&n.push(r[s]);for(this._sort(n,h),e=0,i=n.length;i>e;e++)l[e]=n[e][this._fieldId]}else for(s in r)r.hasOwnProperty(s)&&(o=r[s],l.push(o[this._fieldId]));return l},s.prototype.getDataSet=function(){return this},s.prototype.forEach=function(t,e){var i,s,o=e&&e.filter,n=e&&e.type||this._options.type,r=this._data;if(e&&e.order)for(var a=this.get(e),h=0,d=a.length;d>h;h++)i=a[h],s=i[this._fieldId],t(i,s);else for(s in r)r.hasOwnProperty(s)&&(i=this._getItem(s,n),(!o||o(i))&&t(i,s))},s.prototype.map=function(t,e){var i,s=e&&e.filter,o=e&&e.type||this._options.type,n=[],r=this._data;for(var a in r)r.hasOwnProperty(a)&&(i=this._getItem(a,o),(!s||s(i))&&n.push(t(i,a)));return e&&e.order&&this._sort(n,e.order),n},s.prototype._filterFields=function(t,e){var i={};for(var s in t)t.hasOwnProperty(s)&&-1!=e.indexOf(s)&&(i[s]=t[s]);return i},s.prototype._sort=function(t,e){if(o.isString(e)){var i=e;t.sort(function(t,e){var s=t[i],o=e[i];return s>o?1:o>s?-1:0})}else{if("function"!=typeof e)throw new TypeError("Order must be a function or a string");t.sort(e)}},s.prototype.remove=function(t,e){var i,s,o,n=[];if(Array.isArray(t))for(i=0,s=t.length;s>i;i++)o=this._remove(t[i]),null!=o&&n.push(o);else o=this._remove(t),null!=o&&n.push(o);return n.length&&this._trigger("remove",{items:n},e),n},s.prototype._remove=function(t){if(o.isNumber(t)||o.isString(t)){if(this._data[t])return delete this._data[t],t}else if(t instanceof Object){var e=t[this._fieldId];if(e&&this._data[e])return delete this._data[e],e}return null},s.prototype.clear=function(t){var e=Object.keys(this._data);return this._data={},this._trigger("remove",{items:e},t),e},s.prototype.max=function(t){var e=this._data,i=null,s=null;for(var o in e)if(e.hasOwnProperty(o)){var n=e[o],r=n[t];null!=r&&(!i||r>s)&&(i=n,s=r)}return i},s.prototype.min=function(t){var e=this._data,i=null,s=null;for(var o in e)if(e.hasOwnProperty(o)){var n=e[o],r=n[t];null!=r&&(!i||s>r)&&(i=n,s=r)}return i},s.prototype.distinct=function(t){var e,i=this._data,s=[],n=this._options.type&&this._options.type[t]||null,r=0;for(var a in i)if(i.hasOwnProperty(a)){var h=i[a],d=h[t],l=!1;for(e=0;r>e;e++)if(s[e]==d){l=!0;break}l||void 0===d||(s[r]=d,r++)}if(n)for(e=0;ei;i++)e[i]=t.getColumnId(i)||t.getColumnLabel(i);return e},s.prototype._appendRow=function(t,e,i){for(var s=t.addRow(),o=0,n=e.length;n>o;o++){var r=e[o];t.setValue(s,o,i[r])}},t.exports=s},function(t,e,i){function s(t,e){this._data=null,this._ids={},this._options=e||{},this._fieldId="id",this._subscribers={};var i=this;this.listener=function(){i._onEvent.apply(i,arguments)},this.setData(t)}var o=i(1),n=i(3);s.prototype.setData=function(t){var e,i,s;if(this._data){this._data.unsubscribe&&this._data.unsubscribe("*",this.listener),e=[];for(var o in this._ids)this._ids.hasOwnProperty(o)&&e.push(o);this._ids={},this._trigger("remove",{items:e})}if(this._data=t,this._data){for(this._fieldId=this._options.fieldId||this._data&&this._data.options&&this._data.options.fieldId||"id",e=this._data.getIds({filter:this._options&&this._options.filter}),i=0,s=e.length;s>i;i++)o=e[i],this._ids[o]=!0;this._trigger("add",{items:e}),this._data.on&&this._data.on("*",this.listener)}},s.prototype.get=function(){var t,e,i,s=this,n=o.getType(arguments[0]);"String"==n||"Number"==n||"Array"==n?(t=arguments[0],e=arguments[1],i=arguments[2]):(e=arguments[0],i=arguments[1]);var r=o.extend({},this._options,e);this._options.filter&&e&&e.filter&&(r.filter=function(t){return s._options.filter(t)&&e.filter(t)});var a=[];return void 0!=t&&a.push(t),a.push(r),a.push(i),this._data&&this._data.get.apply(this._data,a)},s.prototype.getIds=function(t){var e;if(this._data){var i,s=this._options.filter;i=t&&t.filter?s?function(e){return s(e)&&t.filter(e)}:t.filter:s,e=this._data.getIds({filter:i,order:t&&t.order})}else e=[];return e},s.prototype.getDataSet=function(){for(var t=this;t instanceof s;)t=t._data;return t||null},s.prototype._onEvent=function(t,e,i){var s,o,n,r,a=e&&e.items,h=this._data,d=[],l=[],c=[];if(a&&h){switch(t){case"add":for(s=0,o=a.length;o>s;s++)n=a[s],r=this.get(n),r&&(this._ids[n]=!0,d.push(n));break;case"update":for(s=0,o=a.length;o>s;s++)n=a[s],r=this.get(n),r?this._ids[n]?l.push(n):(this._ids[n]=!0,d.push(n)):this._ids[n]&&(delete this._ids[n],c.push(n));break;case"remove":for(s=0,o=a.length;o>s;s++)n=a[s],this._ids[n]&&(delete this._ids[n],c.push(n))}d.length&&this._trigger("add",{items:d},i),l.length&&this._trigger("update",{items:l},i),c.length&&this._trigger("remove",{items:c},i)}},s.prototype.on=n.prototype.on,s.prototype.off=n.prototype.off,s.prototype._trigger=n.prototype._trigger,s.prototype.subscribe=s.prototype.on,s.prototype.unsubscribe=s.prototype.off,t.exports=s},function(t,e,i){function s(t,e,i){if(!(this instanceof s))throw new SyntaxError("Constructor must be called with the new operator");this.containerElement=t,this.width="400px",this.height="400px",this.margin=10,this.defaultXCenter="55%",this.defaultYCenter="50%",this.xLabel="x",this.yLabel="y",this.zLabel="z",this.filterLabel="time",this.legendLabel="value",this.style=s.STYLE.DOT,this.showPerspective=!0,this.showGrid=!0,this.keepAspectRatio=!0,this.showShadow=!1,this.showGrayBottom=!1,this.showTooltip=!1,this.verticalRatio=.5,this.animationInterval=1e3,this.animationPreload=!1,this.camera=new l,this.eye=new h(0,0,-1),this.dataTable=null,this.dataPoints=null,this.colX=void 0,this.colY=void 0,this.colZ=void 0,this.colValue=void 0,this.colFilter=void 0,this.xMin=0,this.xStep=void 0,this.xMax=1,this.yMin=0,this.yStep=void 0,this.yMax=1,this.zMin=0,this.zStep=void 0,this.zMax=1,this.valueMin=0,this.valueMax=1,this.xBarWidth=1,this.yBarWidth=1,this.colorAxis="#4D4D4D",this.colorGrid="#D3D3D3",this.colorDot="#7DC1FF",this.colorDotBorder="#3267D2",this.create(),this.setOptions(i),e&&this.setData(e)}var o=i(46),n=i(3),r=i(4),a=i(1),h=i(9),d=i(8),l=i(6),c=i(7),p=i(10),u=i(11);o(s.prototype),s.prototype._setScale=function(){this.scale=new h(1/(this.xMax-this.xMin),1/(this.yMax-this.yMin),1/(this.zMax-this.zMin)),this.keepAspectRatio&&(this.scale.x3&&(this.colFilter=3);else{if(this.style!==s.STYLE.DOTCOLOR&&this.style!==s.STYLE.DOTSIZE&&this.style!==s.STYLE.BARCOLOR&&this.style!==s.STYLE.BARSIZE)throw'Unknown style "'+this.style+'"';this.colX=0,this.colY=1,this.colZ=2,this.colValue=3,t.getNumberOfColumns()>4&&(this.colFilter=4)}},s.prototype.getNumberOfRows=function(t){return t.length},s.prototype.getNumberOfColumns=function(t){var e=0;for(var i in t[0])t[0].hasOwnProperty(i)&&e++;return e},s.prototype.getDistinctValues=function(t,e){for(var i=[],s=0;st[s][e]&&(i.min=t[s][e]),i.maxt;t++){var m=(t-p)/(f-p),g=240*m,v=this._hsv2rgb(g,1,1);c.strokeStyle=v,c.beginPath(),c.moveTo(h,r+t),c.lineTo(a,r+t),c.stroke()}c.strokeStyle=this.colorAxis,c.strokeRect(h,r,i,n)}if(this.style===s.STYLE.DOTSIZE&&(c.strokeStyle=this.colorAxis,c.fillStyle=this.colorDot,c.beginPath(),c.moveTo(h,r),c.lineTo(a,r),c.lineTo(a-i+e,d),c.lineTo(h,d),c.closePath(),c.fill(),c.stroke()),this.style===s.STYLE.DOTCOLOR||this.style===s.STYLE.DOTSIZE){var y=5,b=new u(this.valueMin,this.valueMax,(this.valueMax-this.valueMin)/5,!0);for(b.start(),b.getCurrent()0?this.yMin:this.yMax,o=this._convert3Dto2D(new h(x,r,this.zMin)),Math.cos(2*_)>0?(g.textAlign="center",g.textBaseline="top",o.y+=b):Math.sin(2*_)<0?(g.textAlign="right",g.textBaseline="middle"):(g.textAlign="left",g.textBaseline="middle"),g.fillStyle=this.colorAxis,g.fillText(" "+i.getCurrent()+" ",o.x,o.y),i.next()}for(g.lineWidth=1,s=void 0===this.defaultYStep,i=new u(this.yMin,this.yMax,this.yStep,s),i.start(),i.getCurrent()0?this.xMin:this.xMax,o=this._convert3Dto2D(new h(n,i.getCurrent(),this.zMin)),Math.cos(2*_)<0?(g.textAlign="center",g.textBaseline="top",o.y+=b):Math.sin(2*_)>0?(g.textAlign="right",g.textBaseline="middle"):(g.textAlign="left",g.textBaseline="middle"),g.fillStyle=this.colorAxis,g.fillText(" "+i.getCurrent()+" ",o.x,o.y),i.next();for(g.lineWidth=1,s=void 0===this.defaultZStep,i=new u(this.zMin,this.zMax,this.zStep,s),i.start(),i.getCurrent()0?this.xMin:this.xMax,r=Math.sin(_)<0?this.yMin:this.yMax;!i.end();)t=this._convert3Dto2D(new h(n,r,i.getCurrent())),g.strokeStyle=this.colorAxis,g.beginPath(),g.moveTo(t.x,t.y),g.lineTo(t.x-b,t.y),g.stroke(),g.textAlign="right",g.textBaseline="middle",g.fillStyle=this.colorAxis,g.fillText(i.getCurrent()+" ",t.x-5,t.y),i.next();g.lineWidth=1,t=this._convert3Dto2D(new h(n,r,this.zMin)),e=this._convert3Dto2D(new h(n,r,this.zMax)),g.strokeStyle=this.colorAxis,g.beginPath(),g.moveTo(t.x,t.y),g.lineTo(e.x,e.y),g.stroke(),g.lineWidth=1,p=this._convert3Dto2D(new h(this.xMin,this.yMin,this.zMin)),f=this._convert3Dto2D(new h(this.xMax,this.yMin,this.zMin)),g.strokeStyle=this.colorAxis,g.beginPath(),g.moveTo(p.x,p.y),g.lineTo(f.x,f.y),g.stroke(),p=this._convert3Dto2D(new h(this.xMin,this.yMax,this.zMin)),f=this._convert3Dto2D(new h(this.xMax,this.yMax,this.zMin)),g.strokeStyle=this.colorAxis,g.beginPath(),g.moveTo(p.x,p.y),g.lineTo(f.x,f.y),g.stroke(),g.lineWidth=1,t=this._convert3Dto2D(new h(this.xMin,this.yMin,this.zMin)),e=this._convert3Dto2D(new h(this.xMin,this.yMax,this.zMin)),g.strokeStyle=this.colorAxis,g.beginPath(),g.moveTo(t.x,t.y),g.lineTo(e.x,e.y),g.stroke(),t=this._convert3Dto2D(new h(this.xMax,this.yMin,this.zMin)),e=this._convert3Dto2D(new h(this.xMax,this.yMax,this.zMin)),g.strokeStyle=this.colorAxis,g.beginPath(),g.moveTo(t.x,t.y),g.lineTo(e.x,e.y),g.stroke();var w=this.xLabel;w.length>0&&(c=.1/this.scale.y,n=(this.xMin+this.xMax)/2,r=Math.cos(_)>0?this.yMin-c:this.yMax+c,o=this._convert3Dto2D(new h(n,r,this.zMin)),Math.cos(2*_)>0?(g.textAlign="center",g.textBaseline="top"):Math.sin(2*_)<0?(g.textAlign="right",g.textBaseline="middle"):(g.textAlign="left",g.textBaseline="middle"),g.fillStyle=this.colorAxis,g.fillText(w,o.x,o.y));var S=this.yLabel;S.length>0&&(l=.1/this.scale.x,n=Math.sin(_)>0?this.xMin-l:this.xMax+l,r=(this.yMin+this.yMax)/2,o=this._convert3Dto2D(new h(n,r,this.zMin)),Math.cos(2*_)<0?(g.textAlign="center",g.textBaseline="top"):Math.sin(2*_)>0?(g.textAlign="right",g.textBaseline="middle"):(g.textAlign="left",g.textBaseline="middle"),g.fillStyle=this.colorAxis,g.fillText(S,o.x,o.y));var M=this.zLabel;M.length>0&&(d=30,n=Math.cos(_)>0?this.xMin:this.xMax,r=Math.sin(_)<0?this.yMin:this.yMax,a=(this.zMin+this.zMax)/2,o=this._convert3Dto2D(new h(n,r,a)),g.textAlign="right",g.textBaseline="middle",g.fillStyle=this.colorAxis,g.fillText(M,o.x-d,o.y))},s.prototype._hsv2rgb=function(t,e,i){var s,o,n,r,a,h;switch(r=i*e,a=Math.floor(t/60),h=r*(1-Math.abs(t/60%2-1)),a){case 0:s=r,o=h,n=0;break;case 1:s=h,o=r,n=0;break;case 2:s=0,o=r,n=h;break;case 3:s=0,o=h,n=r;break;case 4:s=h,o=0,n=r;break;case 5:s=r,o=0,n=h;break;default:s=0,o=0,n=0}return"RGB("+parseInt(255*s)+","+parseInt(255*o)+","+parseInt(255*n)+")"},s.prototype._redrawDataGrid=function(){var t,e,i,o,n,r,a,d,l,c,p,u,f,m=this.frame.canvas,g=m.getContext("2d");if(!(void 0===this.dataPoints||this.dataPoints.length<=0)){for(n=0;n0}else r=!0;r?(f=(t.point.z+e.point.z+i.point.z+o.point.z)/4,c=240*(1-(f-this.zMin)*this.scale.z/this.verticalRatio),p=1,this.showShadow?(u=Math.min(1+S.x/M/2,1),a=this._hsv2rgb(c,p,u),d=a):(u=1,a=this._hsv2rgb(c,p,u),d=this.colorAxis)):(a="gray",d=this.colorAxis),l=.5,g.lineWidth=l,g.fillStyle=a,g.strokeStyle=d,g.beginPath(),g.moveTo(t.screen.x,t.screen.y),g.lineTo(e.screen.x,e.screen.y),g.lineTo(o.screen.x,o.screen.y),g.lineTo(i.screen.x,i.screen.y),g.closePath(),g.fill(),g.stroke()}}else for(n=0;np&&(p=0);var u,f,m;this.style===s.STYLE.DOTCOLOR?(u=240*(1-(d.point.value-this.valueMin)*this.scale.value),f=this._hsv2rgb(u,1,1),m=this._hsv2rgb(u,1,.8)):this.style===s.STYLE.DOTSIZE?(f=this.colorDot,m=this.colorDotBorder):(u=240*(1-(d.point.z-this.zMin)*this.scale.z/this.verticalRatio),f=this._hsv2rgb(u,1,1),m=this._hsv2rgb(u,1,.8)),i.lineWidth=1,i.strokeStyle=m,i.fillStyle=f,i.beginPath(),i.arc(d.screen.x,d.screen.y,p,0,2*Math.PI,!0),i.fill(),i.stroke()}}},s.prototype._redrawDataBar=function(){var t,e,i,o,n=this.frame.canvas,r=n.getContext("2d");if(!(void 0===this.dataPoints||this.dataPoints.length<=0)){for(t=0;t0&&(t=this.dataPoints[0],s.lineWidth=1,s.strokeStyle="blue",s.beginPath(),s.moveTo(t.screen.x,t.screen.y)),e=1;e0&&s.stroke()}},s.prototype._onMouseDown=function(t){if(t=t||window.event,this.leftButtonDown&&this._onMouseUp(t),this.leftButtonDown=t.which?1===t.which:1===t.button,this.leftButtonDown||this.touchDown){this.startMouseX=getMouseX(t),this.startMouseY=getMouseY(t),this.startStart=new Date(this.start),this.startEnd=new Date(this.end),this.startArmRotation=this.camera.getArmRotation(),this.frame.style.cursor="move";var e=this;this.onmousemove=function(t){e._onMouseMove(t)},this.onmouseup=function(t){e._onMouseUp(t)},a.addEventListener(document,"mousemove",e.onmousemove),a.addEventListener(document,"mouseup",e.onmouseup),a.preventDefault(t)}},s.prototype._onMouseMove=function(t){t=t||window.event;var e=parseFloat(getMouseX(t))-this.startMouseX,i=parseFloat(getMouseY(t))-this.startMouseY,s=this.startArmRotation.horizontal+e/200,o=this.startArmRotation.vertical+i/200,n=4,r=Math.sin(n/360*2*Math.PI);Math.abs(Math.sin(s))0?1:0>t?-1:0}var s=e[0],o=e[1],n=e[2],r=i((o.x-s.x)*(t.y-s.y)-(o.y-s.y)*(t.x-s.x)),a=i((n.x-o.x)*(t.y-o.y)-(n.y-o.y)*(t.x-o.x)),h=i((s.x-n.x)*(t.y-n.y)-(s.y-n.y)*(t.x-n.x));return!(0!=r&&0!=a&&r!=a||0!=a&&0!=h&&a!=h||0!=r&&0!=h&&r!=h)},s.prototype._dataPointFromXY=function(t,e){var i,o=100,n=null,r=null,a=null,h=new d(t,e);if(this.style===s.STYLE.BAR||this.style===s.STYLE.BARCOLOR||this.style===s.STYLE.BARSIZE)for(i=this.dataPoints.length-1;i>=0;i--){n=this.dataPoints[i];var l=n.surfaces;if(l)for(var c=l.length-1;c>=0;c--){var p=l[c],u=p.corners,f=[u[0].screen,u[1].screen,u[2].screen],m=[u[2].screen,u[3].screen,u[0].screen];if(this._insideTriangle(h,f)||this._insideTriangle(h,m))return n}}else for(i=0;ib)&&o>b&&(a=b,r=n)}}return r},s.prototype._showTooltip=function(t){var e,i,s;this.tooltip?(e=this.tooltip.dom.content,i=this.tooltip.dom.line,s=this.tooltip.dom.dot):(e=document.createElement("div"),e.style.position="absolute",e.style.padding="10px",e.style.border="1px solid #4d4d4d",e.style.color="#1a1a1a",e.style.background="rgba(255,255,255,0.7)",e.style.borderRadius="2px",e.style.boxShadow="5px 5px 10px rgba(128,128,128,0.5)",i=document.createElement("div"),i.style.position="absolute",i.style.height="40px",i.style.width="0",i.style.borderLeft="1px solid #4d4d4d",s=document.createElement("div"),s.style.position="absolute",s.style.height="0",s.style.width="0",s.style.border="5px solid #4d4d4d",s.style.borderRadius="5px",this.tooltip={dataPoint:null,dom:{content:e,line:i,dot:s}}),this._hideTooltip(),this.tooltip.dataPoint=t,e.innerHTML="function"==typeof this.showTooltip?this.showTooltip(t.point):"
x:"+t.point.x+"
y:"+t.point.y+"
z:"+t.point.z+"
",e.style.left="0",e.style.top="0",this.frame.appendChild(e),this.frame.appendChild(i),this.frame.appendChild(s);var o=e.offsetWidth,n=e.offsetHeight,r=i.offsetHeight,a=s.offsetWidth,h=s.offsetHeight,d=t.screen.x-o/2;d=Math.min(Math.max(d,10),this.frame.clientWidth-10-o),i.style.left=t.screen.x+"px",i.style.top=t.screen.y-r+"px",e.style.left=d+"px",e.style.top=t.screen.y-r-n+"px",s.style.left=t.screen.x-a/2+"px",s.style.top=t.screen.y-h/2+"px"},s.prototype._hideTooltip=function(){if(this.tooltip){this.tooltip.dataPoint=null;for(var t in this.tooltip.dom)if(this.tooltip.dom.hasOwnProperty(t)){var e=this.tooltip.dom[t];e&&e.parentNode&&e.parentNode.removeChild(e)}}},getMouseX=function(t){return"clientX"in t?t.clientX:t.targetTouches[0]&&t.targetTouches[0].clientX||0},getMouseY=function(t){return"clientY"in t?t.clientY:t.targetTouches[0]&&t.targetTouches[0].clientY||0},t.exports=s},function(t,e,i){var s=i(9);Camera=function(){this.armLocation=new s,this.armRotation={},this.armRotation.horizontal=0,this.armRotation.vertical=0,this.armLength=1.7,this.cameraLocation=new s,this.cameraRotation=new s(.5*Math.PI,0,0),this.calculateCameraOrientation()},Camera.prototype.setArmLocation=function(t,e,i){this.armLocation.x=t,this.armLocation.y=e,this.armLocation.z=i,this.calculateCameraOrientation()},Camera.prototype.setArmRotation=function(t,e){void 0!==t&&(this.armRotation.horizontal=t),void 0!==e&&(this.armRotation.vertical=e,this.armRotation.vertical<0&&(this.armRotation.vertical=0),this.armRotation.vertical>.5*Math.PI&&(this.armRotation.vertical=.5*Math.PI)),(void 0!==t||void 0!==e)&&this.calculateCameraOrientation()},Camera.prototype.getArmRotation=function(){var t={};return t.horizontal=this.armRotation.horizontal,t.vertical=this.armRotation.vertical,t},Camera.prototype.setArmLength=function(t){void 0!==t&&(this.armLength=t,this.armLength<.71&&(this.armLength=.71),this.armLength>5&&(this.armLength=5),this.calculateCameraOrientation())},Camera.prototype.getArmLength=function(){return this.armLength},Camera.prototype.getCameraLocation=function(){return this.cameraLocation},Camera.prototype.getCameraRotation=function(){return this.cameraRotation},Camera.prototype.calculateCameraOrientation=function(){this.cameraLocation.x=this.armLocation.x-this.armLength*Math.sin(this.armRotation.horizontal)*Math.cos(this.armRotation.vertical),this.cameraLocation.y=this.armLocation.y-this.armLength*Math.cos(this.armRotation.horizontal)*Math.cos(this.armRotation.vertical),this.cameraLocation.z=this.armLocation.z+this.armLength*Math.sin(this.armRotation.vertical),this.cameraRotation.x=Math.PI/2-this.armRotation.vertical,this.cameraRotation.y=0,this.cameraRotation.z=-this.armRotation.horizontal},t.exports=Camera},function(t,e,i){function s(t,e,i){this.data=t,this.column=e,this.graph=i,this.index=void 0,this.value=void 0,this.values=i.getDistinctValues(t.get(),this.column),this.values.sort(function(t,e){return t>e?1:e>t?-1:0}),this.values.length>0&&this.selectValue(0),this.dataPoints=[],this.loaded=!1,this.onLoadCallback=void 0,i.animationPreload?(this.loaded=!1,this.loadInBackground()):this.loaded=!0}var o=i(4);s.prototype.isLoaded=function(){return this.loaded},s.prototype.getLoadedProgress=function(){for(var t=this.values.length,e=0;this.dataPoints[e];)e++;return Math.round(e/t*100)},s.prototype.getLabel=function(){return this.graph.filterLabel},s.prototype.getColumn=function(){return this.column},s.prototype.getSelectedValue=function(){return void 0===this.index?void 0:this.values[this.index]},s.prototype.getValues=function(){return this.values},s.prototype.getValue=function(t){if(t>=this.values.length)throw"Error: index out of range";return this.values[t]},s.prototype._getDataPoints=function(t){if(void 0===t&&(t=this.index),void 0===t)return[];var e;if(this.dataPoints[t])e=this.dataPoints[t];else{var i={};i.column=this.column,i.value=this.values[t];var s=new o(this.data,{filter:function(t){return t[i.column]==i.value}}).get();e=this.graph._getDataPoints(s),this.dataPoints[t]=e}return e},s.prototype.setOnLoadCallback=function(t){this.onLoadCallback=t},s.prototype.selectValue=function(t){if(t>=this.values.length)throw"Error: index out of range";this.index=t,this.value=this.values[t]},s.prototype.loadInBackground=function(t){void 0===t&&(t=0);var e=this.graph.frame;if(t0&&(t--,this.setIndex(t))},s.prototype.next=function(){var t=this.getIndex();t0?this.setIndex(0):this.index=void 0},s.prototype.setIndex=function(t){if(!(ts&&(s=0),s>this.values.length-1&&(s=this.values.length-1),s},s.prototype.indexToLeft=function(t){var e=parseFloat(this.frame.bar.style.width)-this.frame.slide.clientWidth-10,i=t/(this.values.length-1)*e,s=i+3;return s},s.prototype._onMouseMove=function(t){var e=t.clientX-this.startClientX,i=this.startSlideX+e,s=this.leftToIndex(i);this.setIndex(s),o.preventDefault()},s.prototype._onMouseUp=function(){this.frame.style.cursor="auto",o.removeEventListener(document,"mousemove",this.onmousemove),o.removeEventListener(document,"mouseup",this.onmouseup),o.preventDefault()},t.exports=s},function(t){function e(t,e,i,s){this._start=0,this._end=0,this._step=1,this.prettyStep=!0,this.precision=5,this._current=0,this.setRange(t,e,i,s)}e.prototype.setRange=function(t,e,i,s){this._start=t?t:0,this._end=e?e:0,this.setStep(i,s)},e.prototype.setStep=function(t,i){void 0===t||0>=t||(void 0!==i&&(this.prettyStep=i),this._step=this.prettyStep===!0?e.calculatePrettyStep(t):t)},e.calculatePrettyStep=function(t){var e=function(t){return Math.log(t)/Math.LN10},i=Math.pow(10,Math.round(e(t))),s=2*Math.pow(10,Math.round(e(t/2))),o=5*Math.pow(10,Math.round(e(t/5))),n=i;return Math.abs(s-t)<=Math.abs(n-t)&&(n=s),Math.abs(o-t)<=Math.abs(n-t)&&(n=o),0>=n&&(n=1),n},e.prototype.getCurrent=function(){return parseFloat(this._current.toPrecision(this.precision))},e.prototype.getStep=function(){return this._step},e.prototype.start=function(){this._current=this._start-this._start%this._step},e.prototype.next=function(){this._current+=this._step},e.prototype.end=function(){return this._current>this._end},t.exports=e},function(t,e,i){function s(t,e,i){for(var n in h.prototype)h.prototype.hasOwnProperty(n)&&!s.prototype.hasOwnProperty(n)&&(s.prototype[n]=h.prototype[n]);if(!(this instanceof s))throw new SyntaxError("Constructor must be called with the new operator");var r=this;this.defaultOptions={start:null,end:null,autoResize:!0,orientation:"bottom",width:null,height:null,maxHeight:null,minHeight:null},this.options=o.deepExtend({},this.defaultOptions),this._create(t),this.components=[],this.body={dom:this.dom,domProps:this.props,emitter:{on:this.on.bind(this),off:this.off.bind(this),emit:this.emit.bind(this)},util:{snap:null,toScreen:r._toScreen.bind(r),toGlobalScreen:r._toGlobalScreen.bind(r),toTime:r._toTime.bind(r),toGlobalTime:r._toGlobalTime.bind(r)}},this.range=new a(this.body),this.components.push(this.range),this.body.range=this.range,this.timeAxis=new d(this.body),this.components.push(this.timeAxis),this.body.util.snap=this.timeAxis.snap.bind(this.timeAxis),this.currentTime=new l(this.body),this.components.push(this.currentTime),this.customTime=new c(this.body),this.components.push(this.customTime),this.itemSet=new p(this.body),this.components.push(this.itemSet),this.itemsData=null,this.groupsData=null,i&&this.setOptions(i),e?this.setItems(e):this.redraw()}var o=(i(46),i(40),i(2)),n=i(3),r=i(4),a=i(15),h=i(42),d=i(27),l=i(18),c=i(20),p=i(24);s.prototype.setOptions=function(t){if(t){var e=["width","height","minHeight","maxHeight","autoResize","start","end","orientation"];o.selectiveExtend(e,this.options,t),this._initAutoResize()}if(this.components.forEach(function(e){e.setOptions(t)}),t&&t.order)throw new Error("Option order is deprecated. There is no replacement for this feature.");this.redraw()},s.prototype.setItems=function(t){var e,i=null==this.itemsData;if(e=t?t instanceof n||t instanceof r?t:new n(t,{type:{start:"Date",end:"Date"}}):null,this.itemsData=e,this.itemSet&&this.itemSet.setItems(e),i&&("start"in this.options||"end"in this.options)){this.fit();var s="start"in this.options?o.convert(this.options.start,"Date"):null,a="end"in this.options?o.convert(this.options.end,"Date"):null;this.setWindow(s,a)}},s.prototype.setGroups=function(t){var e;e=t?t instanceof n||t instanceof r?t:new n(t):null,this.groupsData=e,this.itemSet.setGroups(e)},s.prototype.setSelection=function(t){this.itemSet&&this.itemSet.setSelection(t)},s.prototype.getSelection=function(){return this.itemSet&&this.itemSet.getSelection()||[]},s.prototype.getItemRange=function(){var t=this.itemsData.getDataSet(),e=null,i=null;if(t){var s=t.min("start");e=s?o.convert(s.start,"Date").valueOf():null;var n=t.max("start");n&&(i=o.convert(n.start,"Date").valueOf());var r=t.max("end");r&&(i=null==i?o.convert(r.end,"Date").valueOf():Math.max(i,o.convert(r.end,"Date").valueOf()))}return{min:null!=e?new Date(e):null,max:null!=i?new Date(i):null}},t.exports=s},function(t,e,i){function s(t,e,i,n){for(var r in h.prototype)h.prototype.hasOwnProperty(r)&&!s.prototype.hasOwnProperty(r)&&(s.prototype[r]=h.prototype[r]);var u=this;this.defaultOptions={start:null,end:null,autoResize:!0,orientation:"bottom",width:null,height:null,maxHeight:null,minHeight:null},this.options=o.deepExtend({},this.defaultOptions),this._create(t),this.components=[],this.body={dom:this.dom,domProps:this.props,emitter:{on:this.on.bind(this),off:this.off.bind(this),emit:this.emit.bind(this)},util:{snap:null,toScreen:u._toScreen.bind(u),toGlobalScreen:u._toGlobalScreen.bind(u),toTime:u._toTime.bind(u),toGlobalTime:u._toGlobalTime.bind(u)}},this.range=new a(this.body),this.components.push(this.range),this.body.range=this.range,this.timeAxis=new d(this.body),this.components.push(this.timeAxis),this.body.util.snap=this.timeAxis.snap.bind(this.timeAxis),this.currentTime=new l(this.body),this.components.push(this.currentTime),this.customTime=new c(this.body),this.components.push(this.customTime),this.linegraph=new p(this.body),this.components.push(this.linegraph),this.itemsData=null,this.groupsData=null,i&&this.setOptions(i),n&&this.setGroups(n),e?this.setItems(e):this.redraw()}var o=(i(46),i(40),i(2)),n=i(3),r=i(4),a=i(15),h=i(42),d=i(27),l=i(18),c=i(20),p=i(26);s.prototype.setOptions=function(t){if(t){var e=["width","height","minHeight","maxHeight","autoResize","start","end","orientation"];o.selectiveExtend(e,this.options,t),this._initAutoResize()}if(this.components.forEach(function(e){e.setOptions(t)}),t&&t.order)throw new Error("Option order is deprecated. There is no replacement for this feature.");this.redraw()},s.prototype.setItems=function(t){var e,i=null==this.itemsData;if(e=t?t instanceof n||t instanceof r?t:new n(t,{type:{start:"Date",end:"Date"}}):null,this.itemsData=e,this.linegraph&&this.linegraph.setItems(e),i&&("start"in this.options||"end"in this.options)){this.fit();var s="start"in this.options?o.convert(this.options.start,"Date"):null,a="end"in this.options?o.convert(this.options.end,"Date"):null;this.setWindow(s,a)}},s.prototype.setGroups=function(t){var e;e=t?t instanceof n||t instanceof r?t:new n(t):null,this.groupsData=e,this.linegraph.setGroups(e)},s.prototype.getLegend=function(t,e,i){return void 0===e&&(e=15),void 0===i&&(i=15),void 0!==this.linegraph.groups[t]?this.linegraph.groups[t].getLegend(e,i):"cannot find group:"+t},s.prototype.isGroupVisible=function(t){return void 0!==this.linegraph.groups[t]?this.linegraph.groups[t].visible:!1},s.prototype.getItemRange=function(){var t=null,e=null;for(var i in this.linegraph.groups)if(this.linegraph.groups.hasOwnProperty(i)&&1==this.linegraph.groups[i].visible)for(var s=0;sr?r:t,e=null==e?r:r>e?r:e}return{min:null!=t?new Date(t):null,max:null!=e?new Date(e):null}},t.exports=s},function(t){function e(t,e,i,s,o){this.current=0,this.autoScale=!0,this.stepIndex=0,this.step=1,this.scale=1,this.marginStart,this.marginEnd,this.majorSteps=[1,2,5,10],this.minorSteps=[.25,.5,1,2],this.setRange(t,e,i,s,o)}e.prototype.setRange=function(t,e,i,s,o){this._start=t,this._end=e,t==e&&(this._start=t-.75,this._end=e+1),this.autoScale&&this.setMinimumStep(i,s,o),this.setFirst()},e.prototype.setMinimumStep=function(t,e){var i=this._end-this._start,s=1.1*i,o=t*(s/e),n=Math.round(Math.log(s)/Math.LN10),r=-1,a=Math.pow(10,n),h=0;0>n&&(h=n);for(var d=!1,l=h;Math.abs(l)<=Math.abs(n);l++){a=Math.pow(10,l);for(var c=0;c=o){d=!0,r=c;break}}if(1==d)break}this.stepIndex=r,this.scale=a,this.step=a*this.minorSteps[r]},e.prototype.first=function(){this.setFirst()},e.prototype.setFirst=function(){var t=this._start-this.scale*this.minorSteps[this.stepIndex],e=this._end+this.scale*this.minorSteps[this.stepIndex];this.marginEnd=this.roundToMinor(e),this.marginStart=this.roundToMinor(t),this.marginRange=this.marginEnd-this.marginStart,this.current=this.marginEnd},e.prototype.roundToMinor=function(t){var e=t-t%(this.scale*this.minorSteps[this.stepIndex]);return t%(this.scale*this.minorSteps[this.stepIndex])>.5*this.scale*this.minorSteps[this.stepIndex]?e+this.scale*this.minorSteps[this.stepIndex]:e},e.prototype.hasNext=function(){return this.current>=this.marginStart},e.prototype.next=function(){var t=this.current;this.current-=this.step,this.current==t&&(this.current=this._end)},e.prototype.previous=function(){this.current+=this.step,this.marginEnd+=this.step,this.marginRange=this.marginEnd-this.marginStart},e.prototype.getCurrent=function(){for(var t=""+Number(this.current).toPrecision(5),e=t.length-1;e>0;e--){if("0"!=t[e]){if("."==t[e]||","==t[e]){t=t.slice(0,e);break}break}t=t.slice(0,e)}return t},e.prototype.snap=function(){},e.prototype.isMajor=function(){return this.current%(this.scale*this.majorSteps[this.stepIndex])==0},t.exports=e},function(t,e,i){function s(t,e){var i=h().hours(0).minutes(0).seconds(0).milliseconds(0);this.start=i.clone().add("days",-3).valueOf(),this.end=i.clone().add("days",4).valueOf(),this.body=t,this.defaultOptions={start:null,end:null,direction:"horizontal",moveable:!0,zoomable:!0,min:null,max:null,zoomMin:10,zoomMax:31536e10},this.options=r.extend({},this.defaultOptions),this.props={touch:{}},this.body.emitter.on("dragstart",this._onDragStart.bind(this)),this.body.emitter.on("drag",this._onDrag.bind(this)),this.body.emitter.on("dragend",this._onDragEnd.bind(this)),this.body.emitter.on("hold",this._onHold.bind(this)),this.body.emitter.on("mousewheel",this._onMouseWheel.bind(this)),this.body.emitter.on("DOMMouseScroll",this._onMouseWheel.bind(this)),this.body.emitter.on("touch",this._onTouch.bind(this)),this.body.emitter.on("pinch",this._onPinch.bind(this)),this.setOptions(e)}function o(t){if("horizontal"!=t&&"vertical"!=t)throw new TypeError('Unknown direction "'+t+'". Choose "horizontal" or "vertical".')}function n(t,e){return{x:t.pageX-r.getAbsoluteLeft(e),y:t.pageY-r.getAbsoluteTop(e)}}var r=i(2),a=i(43),h=i(41),d=i(19);s.prototype=new d,s.prototype.setOptions=function(t){if(t){var e=["direction","min","max","zoomMin","zoomMax","moveable","zoomable"];r.selectiveExtend(e,this.options,t),("start"in t||"end"in t)&&this.setRange(t.start,t.end)}},s.prototype.setRange=function(t,e){var i=this._applyRange(t,e);if(i){var s={start:new Date(this.start),end:new Date(this.end)};this.body.emitter.emit("rangechange",s),this.body.emitter.emit("rangechanged",s)}},s.prototype._applyRange=function(t,e){var i,s=null!=t?r.convert(t,"Date").valueOf():this.start,o=null!=e?r.convert(e,"Date").valueOf():this.end,n=null!=this.options.max?r.convert(this.options.max,"Date").valueOf():null,a=null!=this.options.min?r.convert(this.options.min,"Date").valueOf():null;if(isNaN(s)||null===s)throw new Error('Invalid start "'+t+'"');if(isNaN(o)||null===o)throw new Error('Invalid end "'+e+'"');if(s>o&&(o=s),null!==a&&a>s&&(i=a-s,s+=i,o+=i,null!=n&&o>n&&(o=n)),null!==n&&o>n&&(i=o-n,s-=i,o-=i,null!=a&&a>s&&(s=a)),null!==this.options.zoomMin){var h=parseFloat(this.options.zoomMin);0>h&&(h=0),h>o-s&&(this.end-this.start===h?(s=this.start,o=this.end):(i=h-(o-s),s-=i/2,o+=i/2))}if(null!==this.options.zoomMax){var d=parseFloat(this.options.zoomMax);0>d&&(d=0),o-s>d&&(this.end-this.start===d?(s=this.start,o=this.end):(i=o-s-d,s+=i/2,o-=i/2))}var l=this.start!=s||this.end!=o;return this.start=s,this.end=o,l},s.prototype.getRange=function(){return{start:this.start,end:this.end}},s.prototype.conversion=function(t){return s.conversion(this.start,this.end,t)},s.conversion=function(t,e,i){return 0!=i&&e-t!=0?{offset:t,scale:i/(e-t)}:{offset:0,scale:1}},s.prototype._onDragStart=function(){this.options.moveable&&this.props.touch.allowDragging&&(this.props.touch.start=this.start,this.props.touch.end=this.end,this.body.dom.root&&(this.body.dom.root.style.cursor="move"))},s.prototype._onDrag=function(t){if(this.options.moveable){var e=this.options.direction;if(o(e),this.props.touch.allowDragging){var i="horizontal"==e?t.gesture.deltaX:t.gesture.deltaY,s=this.props.touch.end-this.props.touch.start,n="horizontal"==e?this.body.domProps.center.width:this.body.domProps.center.height,r=-i/n*s;this._applyRange(this.props.touch.start+r,this.props.touch.end+r),this.body.emitter.emit("rangechange",{start:new Date(this.start),end:new Date(this.end)})}}},s.prototype._onDragEnd=function(){this.options.moveable&&this.props.touch.allowDragging&&(this.body.dom.root&&(this.body.dom.root.style.cursor="auto"),this.body.emitter.emit("rangechanged",{start:new Date(this.start),end:new Date(this.end)}))},s.prototype._onMouseWheel=function(t){if(this.options.zoomable&&this.options.moveable){var e=0;if(t.wheelDelta?e=t.wheelDelta/120:t.detail&&(e=-t.detail/3),e){var i;i=0>e?1-e/5:1/(1+e/5);var s=a.fakeGesture(this,t),o=n(s.center,this.body.dom.center),r=this._pointerToDate(o);this.zoom(i,r)}t.preventDefault()}},s.prototype._onTouch=function(){this.props.touch.start=this.start,this.props.touch.end=this.end,this.props.touch.allowDragging=!0,this.props.touch.center=null},s.prototype._onHold=function(){this.props.touch.allowDragging=!1},s.prototype._onPinch=function(t){if(this.options.zoomable&&this.options.moveable&&(this.props.touch.allowDragging=!1,t.gesture.touches.length>1)){this.props.touch.center||(this.props.touch.center=n(t.gesture.center,this.body.dom.center));var e=1/t.gesture.scale,i=this._pointerToDate(this.props.touch.center),s=parseInt(i+(this.props.touch.start-i)*e),o=parseInt(i+(this.props.touch.end-i)*e);this.setRange(s,o)}},s.prototype._pointerToDate=function(t){var e,i=this.options.direction;if(o(i),"horizontal"==i){var s=this.body.domProps.center.width;return e=this.conversion(s),t.x/e.scale+e.offset}var n=this.body.domProps.center.height;return e=this.conversion(n),t.y/e.scale+e.offset},s.prototype.zoom=function(t,e){null==e&&(e=(this.start+this.end)/2);var i=e+(this.start-e)*t,s=e+(this.end-e)*t;this.setRange(i,s)},s.prototype.move=function(t){var e=this.end-this.start,i=this.start+e*t,s=this.end+e*t;this.start=i,this.end=s},s.prototype.moveTo=function(t){var e=(this.start+this.end)/2,i=e-t,s=this.start-i,o=this.end-i;this.setRange(s,o)},t.exports=s},function(t,e){var i=.001;e.orderByStart=function(t){t.sort(function(t,e){return t.data.start-e.data.start})},e.orderByEnd=function(t){t.sort(function(t,e){var i="end"in t.data?t.data.end:t.data.start,s="end"in e.data?e.data.end:e.data.start;return i-s})},e.stack=function(t,i,s){var o,n;if(s)for(o=0,n=t.length;n>o;o++)t[o].top=null;for(o=0,n=t.length;n>o;o++){var r=t[o];if(null===r.top){r.top=i.axis;do{for(var a=null,h=0,d=t.length;d>h;h++){var l=t[h];if(null!==l.top&&l!==r&&e.collision(r,l,i.item)){a=l;break}}null!=a&&(r.top=a.top+a.height+i.item.vertical)}while(a)}}},e.nostack=function(t,e){var i,s;for(i=0,s=t.length;s>i;i++)t[i].top=e.axis},e.collision=function(t,e,s){return t.left-s.horizontal+ie.left&&t.top-s.vertical+ie.top}},function(t,e,i){function s(t,e,i){this.current=new Date,this._start=new Date,this._end=new Date,this.autoScale=!0,this.scale=s.SCALE.DAY,this.step=1,this.setRange(t,e,i)}var o=i(41);s.SCALE={MILLISECOND:1,SECOND:2,MINUTE:3,HOUR:4,DAY:5,WEEKDAY:6,MONTH:7,YEAR:8},s.prototype.setRange=function(t,e,i){if(!(t instanceof Date&&e instanceof Date))throw"No legal start or end date in method setRange";this._start=void 0!=t?new Date(t.valueOf()):new Date,this._end=void 0!=e?new Date(e.valueOf()):new Date,this.autoScale&&this.setMinimumStep(i)},s.prototype.first=function(){this.current=new Date(this._start.valueOf()),this.roundToMinor()},s.prototype.roundToMinor=function(){switch(this.scale){case s.SCALE.YEAR:this.current.setFullYear(this.step*Math.floor(this.current.getFullYear()/this.step)),this.current.setMonth(0);case s.SCALE.MONTH:this.current.setDate(1);case s.SCALE.DAY:case s.SCALE.WEEKDAY:this.current.setHours(0);case s.SCALE.HOUR:this.current.setMinutes(0);case s.SCALE.MINUTE:this.current.setSeconds(0);case s.SCALE.SECOND:this.current.setMilliseconds(0)}if(1!=this.step)switch(this.scale){case s.SCALE.MILLISECOND:this.current.setMilliseconds(this.current.getMilliseconds()-this.current.getMilliseconds()%this.step);break;case s.SCALE.SECOND:this.current.setSeconds(this.current.getSeconds()-this.current.getSeconds()%this.step);break;case s.SCALE.MINUTE:this.current.setMinutes(this.current.getMinutes()-this.current.getMinutes()%this.step);break;case s.SCALE.HOUR:this.current.setHours(this.current.getHours()-this.current.getHours()%this.step);break;case s.SCALE.WEEKDAY:case s.SCALE.DAY:this.current.setDate(this.current.getDate()-1-(this.current.getDate()-1)%this.step+1);break;case s.SCALE.MONTH:this.current.setMonth(this.current.getMonth()-this.current.getMonth()%this.step);break;case s.SCALE.YEAR:this.current.setFullYear(this.current.getFullYear()-this.current.getFullYear()%this.step)}},s.prototype.hasNext=function(){return this.current.valueOf()<=this._end.valueOf()},s.prototype.next=function(){var t=this.current.valueOf();if(this.current.getMonth()<6)switch(this.scale){case s.SCALE.MILLISECOND:this.current=new Date(this.current.valueOf()+this.step);break;case s.SCALE.SECOND:this.current=new Date(this.current.valueOf()+1e3*this.step);break;case s.SCALE.MINUTE:this.current=new Date(this.current.valueOf()+1e3*this.step*60);break;case s.SCALE.HOUR:this.current=new Date(this.current.valueOf()+1e3*this.step*60*60);var e=this.current.getHours();this.current.setHours(e-e%this.step);break;case s.SCALE.WEEKDAY:case s.SCALE.DAY:this.current.setDate(this.current.getDate()+this.step);break;case s.SCALE.MONTH:this.current.setMonth(this.current.getMonth()+this.step);break;case s.SCALE.YEAR:this.current.setFullYear(this.current.getFullYear()+this.step)}else switch(this.scale){case s.SCALE.MILLISECOND:this.current=new Date(this.current.valueOf()+this.step);break;case s.SCALE.SECOND:this.current.setSeconds(this.current.getSeconds()+this.step);break;case s.SCALE.MINUTE:this.current.setMinutes(this.current.getMinutes()+this.step);break;case s.SCALE.HOUR:this.current.setHours(this.current.getHours()+this.step);break;case s.SCALE.WEEKDAY:case s.SCALE.DAY:this.current.setDate(this.current.getDate()+this.step);break;case s.SCALE.MONTH:this.current.setMonth(this.current.getMonth()+this.step);break;case s.SCALE.YEAR:this.current.setFullYear(this.current.getFullYear()+this.step)}if(1!=this.step)switch(this.scale){case s.SCALE.MILLISECOND:this.current.getMilliseconds()0&&(this.step=e),this.autoScale=!1},s.prototype.setAutoScale=function(t){this.autoScale=t},s.prototype.setMinimumStep=function(t){if(void 0!=t){var e=31104e6,i=2592e6,o=864e5,n=36e5,r=6e4,a=1e3,h=1;1e3*e>t&&(this.scale=s.SCALE.YEAR,this.step=1e3),500*e>t&&(this.scale=s.SCALE.YEAR,this.step=500),100*e>t&&(this.scale=s.SCALE.YEAR,this.step=100),50*e>t&&(this.scale=s.SCALE.YEAR,this.step=50),10*e>t&&(this.scale=s.SCALE.YEAR,this.step=10),5*e>t&&(this.scale=s.SCALE.YEAR,this.step=5),e>t&&(this.scale=s.SCALE.YEAR,this.step=1),3*i>t&&(this.scale=s.SCALE.MONTH,this.step=3),i>t&&(this.scale=s.SCALE.MONTH,this.step=1),5*o>t&&(this.scale=s.SCALE.DAY,this.step=5),2*o>t&&(this.scale=s.SCALE.DAY,this.step=2),o>t&&(this.scale=s.SCALE.DAY,this.step=1),o/2>t&&(this.scale=s.SCALE.WEEKDAY,this.step=1),4*n>t&&(this.scale=s.SCALE.HOUR,this.step=4),n>t&&(this.scale=s.SCALE.HOUR,this.step=1),15*r>t&&(this.scale=s.SCALE.MINUTE,this.step=15),10*r>t&&(this.scale=s.SCALE.MINUTE,this.step=10),5*r>t&&(this.scale=s.SCALE.MINUTE,this.step=5),r>t&&(this.scale=s.SCALE.MINUTE,this.step=1),15*a>t&&(this.scale=s.SCALE.SECOND,this.step=15),10*a>t&&(this.scale=s.SCALE.SECOND,this.step=10),5*a>t&&(this.scale=s.SCALE.SECOND,this.step=5),a>t&&(this.scale=s.SCALE.SECOND,this.step=1),200*h>t&&(this.scale=s.SCALE.MILLISECOND,this.step=200),100*h>t&&(this.scale=s.SCALE.MILLISECOND,this.step=100),50*h>t&&(this.scale=s.SCALE.MILLISECOND,this.step=50),10*h>t&&(this.scale=s.SCALE.MILLISECOND,this.step=10),5*h>t&&(this.scale=s.SCALE.MILLISECOND,this.step=5),h>t&&(this.scale=s.SCALE.MILLISECOND,this.step=1)}},s.prototype.snap=function(t){var e=new Date(t.valueOf());if(this.scale==s.SCALE.YEAR){var i=e.getFullYear()+Math.round(e.getMonth()/12);e.setFullYear(Math.round(i/this.step)*this.step),e.setMonth(0),e.setDate(0),e.setHours(0),e.setMinutes(0),e.setSeconds(0),e.setMilliseconds(0)}else if(this.scale==s.SCALE.MONTH)e.getDate()>15?(e.setDate(1),e.setMonth(e.getMonth()+1)):e.setDate(1),e.setHours(0),e.setMinutes(0),e.setSeconds(0),e.setMilliseconds(0);else if(this.scale==s.SCALE.DAY){switch(this.step){case 5:case 2:e.setHours(24*Math.round(e.getHours()/24));break;default:e.setHours(12*Math.round(e.getHours()/12))}e.setMinutes(0),e.setSeconds(0),e.setMilliseconds(0)}else if(this.scale==s.SCALE.WEEKDAY){switch(this.step){case 5:case 2:e.setHours(12*Math.round(e.getHours()/12));break;default:e.setHours(6*Math.round(e.getHours()/6))}e.setMinutes(0),e.setSeconds(0),e.setMilliseconds(0)}else if(this.scale==s.SCALE.HOUR){switch(this.step){case 4:e.setMinutes(60*Math.round(e.getMinutes()/60));break;default:e.setMinutes(30*Math.round(e.getMinutes()/30))}e.setSeconds(0),e.setMilliseconds(0)}else if(this.scale==s.SCALE.MINUTE){switch(this.step){case 15:case 10:e.setMinutes(5*Math.round(e.getMinutes()/5)),e.setSeconds(0);break;case 5:e.setSeconds(60*Math.round(e.getSeconds()/60));break;default:e.setSeconds(30*Math.round(e.getSeconds()/30))}e.setMilliseconds(0)}else if(this.scale==s.SCALE.SECOND)switch(this.step){case 15:case 10:e.setSeconds(5*Math.round(e.getSeconds()/5)),e.setMilliseconds(0);break;case 5:e.setMilliseconds(1e3*Math.round(e.getMilliseconds()/1e3));break;default:e.setMilliseconds(500*Math.round(e.getMilliseconds()/500))}else if(this.scale==s.SCALE.MILLISECOND){var o=this.step>5?this.step/2:1;e.setMilliseconds(Math.round(e.getMilliseconds()/o)*o)}return e},s.prototype.isMajor=function(){switch(this.scale){case s.SCALE.MILLISECOND:return 0==this.current.getMilliseconds();case s.SCALE.SECOND:return 0==this.current.getSeconds();case s.SCALE.MINUTE:return 0==this.current.getHours()&&0==this.current.getMinutes();case s.SCALE.HOUR:return 0==this.current.getHours();case s.SCALE.WEEKDAY:case s.SCALE.DAY:return 1==this.current.getDate();case s.SCALE.MONTH:return 0==this.current.getMonth();case s.SCALE.YEAR:return!1;default:return!1}},s.prototype.getLabelMinor=function(t){switch(void 0==t&&(t=this.current),this.scale){case s.SCALE.MILLISECOND:return o(t).format("SSS");case s.SCALE.SECOND:return o(t).format("s");case s.SCALE.MINUTE:return o(t).format("HH:mm");case s.SCALE.HOUR:return o(t).format("HH:mm");case s.SCALE.WEEKDAY:return o(t).format("ddd D");case s.SCALE.DAY:return o(t).format("D");case s.SCALE.MONTH:return o(t).format("MMM");case s.SCALE.YEAR:return o(t).format("YYYY");default:return""}},s.prototype.getLabelMajor=function(t){switch(void 0==t&&(t=this.current),this.scale){case s.SCALE.MILLISECOND:return o(t).format("HH:mm:ss");case s.SCALE.SECOND:return o(t).format("D MMMM HH:mm");case s.SCALE.MINUTE:case s.SCALE.HOUR:return o(t).format("ddd D MMMM");case s.SCALE.WEEKDAY:case s.SCALE.DAY:return o(t).format("MMMM YYYY");case s.SCALE.MONTH:return o(t).format("YYYY");case s.SCALE.YEAR:return"";default:return""}},t.exports=s},function(t,e,i){function s(t,e){this.body=t,this.defaultOptions={showCurrentTime:!0},this.options=o.extend({},this.defaultOptions),this._create(),this.setOptions(e)}var o=i(2),n=i(19);s.prototype=new n,s.prototype._create=function(){var t=document.createElement("div");t.className="currenttime",t.style.position="absolute",t.style.top="0px",t.style.height="100%",this.bar=t},s.prototype.destroy=function(){this.options.showCurrentTime=!1,this.redraw(),this.body=null},s.prototype.setOptions=function(t){t&&o.selectiveExtend(["showCurrentTime"],this.options,t)},s.prototype.redraw=function(){if(this.options.showCurrentTime){var t=this.body.dom.backgroundVertical;this.bar.parentNode!=t&&(this.bar.parentNode&&this.bar.parentNode.removeChild(this.bar),t.appendChild(this.bar),this.start());var e=new Date,i=this.body.util.toScreen(e);this.bar.style.left=i+"px",this.bar.title="Current time: "+e}else this.bar.parentNode&&this.bar.parentNode.removeChild(this.bar),this.stop();return!1},s.prototype.start=function(){function t(){e.stop();var i=e.body.range.conversion(e.body.domProps.center.width).scale,s=1/i/10;30>s&&(s=30),s>1e3&&(s=1e3),e.redraw(),e.currentTimeTimer=setTimeout(t,s)}var e=this;t()},s.prototype.stop=function(){void 0!==this.currentTimeTimer&&(clearTimeout(this.currentTimeTimer),delete this.currentTimeTimer)},t.exports=s},function(t){function e(){this.options=null,this.props=null}e.prototype.setOptions=function(t){t&&util.extend(this.options,t)},e.prototype.redraw=function(){return!1},e.prototype.destroy=function(){},e.prototype._isResized=function(){var t=this.props._previousWidth!==this.props.width||this.props._previousHeight!==this.props.height;return this.props._previousWidth=this.props.width,this.props._previousHeight=this.props.height,t},t.exports=e},function(t,e,i){function s(t,e){this.body=t,this.defaultOptions={showCustomTime:!1},this.options=n.extend({},this.defaultOptions),this.customTime=new Date,this.eventParams={},this._create(),this.setOptions(e)}var o=i(40),n=i(2),r=i(19);s.prototype=new r,s.prototype.setOptions=function(t){t&&n.selectiveExtend(["showCustomTime"],this.options,t)},s.prototype._create=function(){var t=document.createElement("div");t.className="customtime",t.style.position="absolute",t.style.top="0px",t.style.height="100%",this.bar=t;var e=document.createElement("div");e.style.position="relative",e.style.top="0px",e.style.left="-10px",e.style.height="100%",e.style.width="20px",t.appendChild(e),this.hammer=o(t,{prevent_default:!0}),this.hammer.on("dragstart",this._onDragStart.bind(this)),this.hammer.on("drag",this._onDrag.bind(this)),this.hammer.on("dragend",this._onDragEnd.bind(this))},s.prototype.destroy=function(){this.options.showCustomTime=!1,this.redraw(),this.hammer.enable(!1),this.hammer=null,this.body=null},s.prototype.redraw=function(){if(this.options.showCustomTime){var t=this.body.dom.backgroundVertical;this.bar.parentNode!=t&&(this.bar.parentNode&&this.bar.parentNode.removeChild(this.bar),t.appendChild(this.bar));var e=this.body.util.toScreen(this.customTime);this.bar.style.left=e+"px",this.bar.title="Time: "+this.customTime}else this.bar.parentNode&&this.bar.parentNode.removeChild(this.bar);return!1},s.prototype.setCustomTime=function(t){this.customTime=new Date(t.valueOf()),this.redraw()},s.prototype.getCustomTime=function(){return new Date(this.customTime.valueOf())},s.prototype._onDragStart=function(t){this.eventParams.dragging=!0,this.eventParams.customTime=this.customTime,t.stopPropagation(),t.preventDefault()},s.prototype._onDrag=function(t){if(this.eventParams.dragging){var e=t.gesture.deltaX,i=this.body.util.toScreen(this.eventParams.customTime)+e,s=this.body.util.toTime(i);this.setCustomTime(s),this.body.emitter.emit("timechange",{time:new Date(this.customTime.valueOf())}),t.stopPropagation(),t.preventDefault()}},s.prototype._onDragEnd=function(t){this.eventParams.dragging&&(this.body.emitter.emit("timechanged",{time:new Date(this.customTime.valueOf())}),t.stopPropagation(),t.preventDefault())},t.exports=s},function(t,e,i){function s(t,e,i){this.id=o.randomUUID(),this.body=t,this.defaultOptions={orientation:"left",showMinorLabels:!0,showMajorLabels:!0,icons:!0,majorLinesOffset:7,minorLinesOffset:4,labelOffsetX:10,labelOffsetY:2,iconWidth:20,width:"40px",visible:!0},this.linegraphSVG=i,this.props={},this.DOMelements={lines:{},labels:{}},this.dom={},this.range={start:0,end:0},this.options=o.extend({},this.defaultOptions),this.conversionFactor=1,this.setOptions(e),this.width=Number((""+this.options.width).replace("px","")),this.minWidth=this.width,this.height=this.linegraphSVG.offsetHeight,this.stepPixels=25,this.stepPixelsForced=25,this.lineOffset=0,this.master=!0,this.svgElements={},this.groups={},this.amountOfGroups=0,this._create() -}var o=i(2),n=i(1),r=i(19),a=i(14);s.prototype=new r,s.prototype.addGroup=function(t,e){this.groups.hasOwnProperty(t)||(this.groups[t]=e),this.amountOfGroups+=1},s.prototype.updateGroup=function(t,e){this.groups[t]=e},s.prototype.removeGroup=function(t){this.groups.hasOwnProperty(t)&&(delete this.groups[t],this.amountOfGroups-=1)},s.prototype.setOptions=function(t){if(t){var e=!1;this.options.orientation!=t.orientation&&void 0!==t.orientation&&(e=!0);var i=["orientation","showMinorLabels","showMajorLabels","icons","majorLinesOffset","minorLinesOffset","labelOffsetX","labelOffsetY","iconWidth","width","visible"];o.selectiveExtend(i,this.options,t),this.minWidth=Number((""+this.options.width).replace("px","")),1==e&&this.dom.frame&&(this.hide(),this.show())}},s.prototype._create=function(){this.dom.frame=document.createElement("div"),this.dom.frame.style.width=this.options.width,this.dom.frame.style.height=this.height,this.dom.lineContainer=document.createElement("div"),this.dom.lineContainer.style.width="100%",this.dom.lineContainer.style.height=this.height,this.svg=document.createElementNS("http://www.w3.org/2000/svg","svg"),this.svg.style.position="absolute",this.svg.style.top="0px",this.svg.style.height="100%",this.svg.style.width="100%",this.svg.style.display="block",this.dom.frame.appendChild(this.svg)},s.prototype._redrawGroupIcons=function(){n.prepareElements(this.svgElements);var t,e=this.options.iconWidth,i=15,s=4,o=s+.5*i;t="left"==this.options.orientation?s:this.width-e-s;for(var r in this.groups)this.groups.hasOwnProperty(r)&&1==this.groups[r].visible&&(this.groups[r].drawIcon(t,o,this.svgElements,this.svg,e,i),o+=i+s);n.cleanupElements(this.svgElements)},s.prototype.show=function(){this.dom.frame.parentNode||("left"==this.options.orientation?this.body.dom.left.appendChild(this.dom.frame):this.body.dom.right.appendChild(this.dom.frame)),this.dom.lineContainer.parentNode||this.body.dom.backgroundHorizontal.appendChild(this.dom.lineContainer)},s.prototype.hide=function(){this.dom.frame.parentNode&&this.dom.frame.parentNode.removeChild(this.dom.frame),this.dom.lineContainer.parentNode&&this.dom.lineContainer.parentNode.removeChild(this.dom.lineContainer)},s.prototype.setRange=function(t,e){this.range.start=t,this.range.end=e},s.prototype.redraw=function(){var t=!1,e=0;for(var i in this.groups)this.groups.hasOwnProperty(i)&&1==this.groups[i].visible&&e++;if(0==this.amountOfGroups||0==e)this.hide();else{this.show(),this.height=Number(this.linegraphSVG.style.height.replace("px","")),this.dom.lineContainer.style.height=this.height+"px",this.width=1==this.options.visible?Number((""+this.options.width).replace("px","")):0;var s=this.props,o=this.dom.frame;o.className="dataaxis",this._calculateCharSize();var n=this.options.orientation,r=this.options.showMinorLabels,a=this.options.showMajorLabels;s.minorLabelHeight=r?s.minorCharHeight:0,s.majorLabelHeight=a?s.majorCharHeight:0,s.minorLineWidth=this.body.dom.backgroundHorizontal.offsetWidth-this.lineOffset-this.width+2*this.options.minorLinesOffset,s.minorLineHeight=1,s.majorLineWidth=this.body.dom.backgroundHorizontal.offsetWidth-this.lineOffset-this.width+2*this.options.majorLinesOffset,s.majorLineHeight=1,"left"==n?(o.style.top="0",o.style.left="0",o.style.bottom="",o.style.width=this.width+"px",o.style.height=this.height+"px"):(o.style.top="",o.style.bottom="0",o.style.left="0",o.style.width=this.width+"px",o.style.height=this.height+"px"),t=this._redrawLabels(),1==this.options.icons&&this._redrawGroupIcons()}return t},s.prototype._redrawLabels=function(){n.prepareElements(this.DOMelements.lines),n.prepareElements(this.DOMelements.labels);var t=this.options.orientation,e=this.master?this.props.majorCharHeight||10:this.stepPixelsForced,i=new a(this.range.start,this.range.end,e,this.dom.frame.offsetHeight);this.step=i,i.first();var s=this.dom.frame.offsetHeight/(i.marginRange/i.step+1);this.stepPixels=s;var o=this.height/s,r=0;if(0==this.master){s=this.stepPixelsForced,r=Math.round(this.height/s-o);for(var h=0;.5*r>h;h++)i.previous();o=this.height/s}this.valueAtZero=i.marginEnd;var d=0,l=1;i.next(),this.maxLabelSize=0;for(var c=0;l=0&&this._redrawLabel(c-2,i.getCurrent(),t,"yAxis major",this.props.majorCharHeight),this._redrawLine(c,t,"grid horizontal major",this.options.majorLinesOffset,this.props.majorLineWidth)):this._redrawLine(c,t,"grid horizontal minor",this.options.minorLinesOffset,this.props.minorLineWidth),i.next(),l++}this.conversionFactor=d/((o-1)*i.step);var u=1==this.options.icons?this.options.iconWidth+this.options.labelOffsetX+15:this.options.labelOffsetX+15;return this.maxLabelSize>this.width-u&&1==this.options.visible?(this.width=this.maxLabelSize+u,this.options.width=this.width+"px",n.cleanupElements(this.DOMelements.lines),n.cleanupElements(this.DOMelements.labels),this.redraw(),!0):this.maxLabelSizethis.minWidth?(this.width=Math.max(this.minWidth,this.maxLabelSize+u),this.options.width=this.width+"px",n.cleanupElements(this.DOMelements.lines),n.cleanupElements(this.DOMelements.labels),this.redraw(),!0):(n.cleanupElements(this.DOMelements.lines),n.cleanupElements(this.DOMelements.labels),!1)},s.prototype._redrawLabel=function(t,e,i,s,o){var r=n.getDOMElement("div",this.DOMelements.labels,this.dom.frame);r.className=s,r.innerHTML=e,"left"==i?(r.style.left="-"+this.options.labelOffsetX+"px",r.style.textAlign="right"):(r.style.right="-"+this.options.labelOffsetX+"px",r.style.textAlign="left"),r.style.top=t-.5*o+this.options.labelOffsetY+"px",e+="";var a=Math.max(this.props.majorCharWidth,this.props.minorCharWidth);this.maxLabelSizee.axis){var c=d-e.axis;l-=c,o.forEach(h,function(t){t.top-=c})}a=l+e.item.vertical/2}else a=e.axis+e.item.vertical;a=Math.max(a,this.props.label.height);var p=this.dom.foreground;this.top=p.offsetTop,this.left=p.offsetLeft,this.width=p.offsetWidth,s=o.updateProperty(this,"height",a)||s,s=o.updateProperty(this.props.label,"width",this.dom.inner.clientWidth)||s,s=o.updateProperty(this.props.label,"height",this.dom.inner.clientHeight)||s,this.dom.background.style.height=a+"px",this.dom.foreground.style.height=a+"px",this.dom.label.style.height=a+"px";for(var u=0,f=this.visibleItems.length;f>u;u++){var m=this.visibleItems[u];m.repositionY()}return s},s.prototype.show=function(){this.dom.label.parentNode||this.itemSet.dom.labelSet.appendChild(this.dom.label),this.dom.foreground.parentNode||this.itemSet.dom.foreground.appendChild(this.dom.foreground),this.dom.background.parentNode||this.itemSet.dom.background.appendChild(this.dom.background),this.dom.axis.parentNode||this.itemSet.dom.axis.appendChild(this.dom.axis)},s.prototype.hide=function(){var t=this.dom.label;t.parentNode&&t.parentNode.removeChild(t);var e=this.dom.foreground;e.parentNode&&e.parentNode.removeChild(e);var i=this.dom.background;i.parentNode&&i.parentNode.removeChild(i);var s=this.dom.axis;s.parentNode&&s.parentNode.removeChild(s)},s.prototype.add=function(t){if(this.items[t.id]=t,t.setParent(this),-1==this.visibleItems.indexOf(t)){var e=this.itemSet.body.range;this._checkIfVisible(t,this.visibleItems,e)}},s.prototype.remove=function(t){delete this.items[t.id],t.setParent(this.itemSet);var e=this.visibleItems.indexOf(t);-1!=e&&this.visibleItems.splice(e,1)},s.prototype.removeFromDataSet=function(t){this.itemSet.removeItem(t.id)},s.prototype.order=function(){var t=o.toArray(this.items);this.orderedItems.byStart=t,this.orderedItems.byEnd=this._constructByEndArray(t),n.orderByStart(this.orderedItems.byStart),n.orderByEnd(this.orderedItems.byEnd)},s.prototype._constructByEndArray=function(t){for(var e=[],i=0;i0)for(n=0;n=0&&!this._checkIfInvisible(t.byStart[n],r,i);n--);for(n=s+1;n=0&&!this._checkIfInvisible(t.byEnd[n],r,i);n--);for(n=a+1;ne;e++)s=this.selection[e],o=this.items[s],o&&o.unselect();for(this.selection=[],e=0,i=t.length;i>e;e++)s=t[e],o=this.items[s],o&&(this.selection.push(s),o.select())}},s.prototype.getSelection=function(){return this.selection.concat([])},s.prototype.getVisibleItems=function(){var t=this.body.range.getRange(),e=this.body.util.toScreen(t.start),i=this.body.util.toScreen(t.end),s=[];for(var o in this.groups)if(this.groups.hasOwnProperty(o))for(var n=this.groups[o],r=n.visibleItems,a=0;ae&&s.push(h.id)}return s},s.prototype._deselect=function(t){for(var e=this.selection,i=0,s=e.length;s>i;i++)if(e[i]==t){e.splice(i,1);break}},s.prototype.redraw=function(){var t=this.options.margin,e=this.body.range,i=r.option.asSize,s=this.options,o=s.orientation,n=!1,a=this.dom.frame,h=s.editable.updateTime||s.editable.updateGroup;a.className="itemset"+(h?" editable":""),n=this._orderGroups()||n;var d=e.end-e.start,l=d!=this.lastVisibleInterval||this.props.width!=this.props.lastWidth;l&&(this.stackDirty=!0),this.lastVisibleInterval=d,this.props.lastWidth=this.props.width;var c=this.stackDirty,p=this._firstGroup(),u={item:t.item,axis:t.axis},f={item:t.item,axis:t.item.vertical/2},m=0,g=t.axis+t.item.vertical;return r.forEach(this.groups,function(t){var i=t==p?u:f,s=t.redraw(e,i,c);n=s||n,m+=t.height}),m=Math.max(m,g),this.stackDirty=!1,a.style.height=i(m),this.props.top=a.offsetTop,this.props.left=a.offsetLeft,this.props.width=a.offsetWidth,this.props.height=m,this.dom.axis.style.top=i("top"==o?this.body.domProps.top.height+this.body.domProps.border.top:this.body.domProps.top.height+this.body.domProps.centerContainer.height),this.dom.axis.style.left=this.body.domProps.border.left+"px",n=this._isResized()||n},s.prototype._firstGroup=function(){var t="top"==this.options.orientation?0:this.groupIds.length-1,e=this.groupIds[t],i=this.groups[e]||this.groups[f];return i||null},s.prototype._updateUngrouped=function(){var t=this.groups[f];if(this.groupsData)t&&(t.hide(),delete this.groups[f]);else if(!t){var e=null,i=null;t=new l(e,i,this),this.groups[f]=t;for(var s in this.items)this.items.hasOwnProperty(s)&&t.add(this.items[s]);t.show()}},s.prototype.getLabelSet=function(){return this.dom.labelSet},s.prototype.setItems=function(t){var e,i=this,s=this.itemsData;if(t){if(!(t instanceof a||t instanceof h))throw new TypeError("Data must be an instance of DataSet or DataView");this.itemsData=t}else this.itemsData=null;if(s&&(r.forEach(this.itemListeners,function(t,e){s.off(e,t)}),e=s.getIds(),this._onRemove(e)),this.itemsData){var o=this.id;r.forEach(this.itemListeners,function(t,e){i.itemsData.on(e,t,o)}),e=this.itemsData.getIds(),this._onAdd(e),this._updateUngrouped()}},s.prototype.getItems=function(){return this.itemsData},s.prototype.setGroups=function(t){var e,i=this;if(this.groupsData&&(r.forEach(this.groupListeners,function(t,e){i.groupsData.unsubscribe(e,t)}),e=this.groupsData.getIds(),this.groupsData=null,this._onRemoveGroups(e)),t){if(!(t instanceof a||t instanceof h))throw new TypeError("Data must be an instance of DataSet or DataView");this.groupsData=t}else this.groupsData=null;if(this.groupsData){var s=this.id;r.forEach(this.groupListeners,function(t,e){i.groupsData.on(e,t,s)}),e=this.groupsData.getIds(),this._onAddGroups(e)}this._updateUngrouped(),this._order(),this.body.emitter.emit("change")},s.prototype.getGroups=function(){return this.groupsData},s.prototype.removeItem=function(t){var e=this.itemsData.get(t),i=this.itemsData.getDataSet();e&&this.options.onRemove(e,function(e){e&&i.remove(t)})},s.prototype._onUpdate=function(t){var e=this;t.forEach(function(t){var i=e.itemsData.get(t,e.itemOptions),o=e.items[t],n=i.type||e.options.type||(i.end?"range":"box"),r=s.types[n];if(o&&(r&&o instanceof r?e._updateItem(o,i):(e._removeItem(o),o=null)),!o){if(!r)throw new TypeError("rangeoverflow"==n?'Item type "rangeoverflow" is deprecated. Use css styling instead: .vis.timeline .item.range .content {overflow: visible;}':'Unknown item type "'+n+'"');o=new r(i,e.conversion,e.options),o.id=t,e._addItem(o)}}),this._order(),this.stackDirty=!0,this.body.emitter.emit("change")},s.prototype._onAdd=s.prototype._onUpdate,s.prototype._onRemove=function(t){var e=0,i=this;t.forEach(function(t){var s=i.items[t];s&&(e++,i._removeItem(s))}),e&&(this._order(),this.stackDirty=!0,this.body.emitter.emit("change"))},s.prototype._order=function(){r.forEach(this.groups,function(t){t.order()})},s.prototype._onUpdateGroups=function(t){this._onAddGroups(t)},s.prototype._onAddGroups=function(t){var e=this;t.forEach(function(t){var i=e.groupsData.get(t),s=e.groups[t];if(s)s.setData(i);else{if(t==f)throw new Error("Illegal group id. "+t+" is a reserved id.");var o=Object.create(e.options);r.extend(o,{height:null}),s=new l(t,i,e),e.groups[t]=s;for(var n in e.items)if(e.items.hasOwnProperty(n)){var a=e.items[n];a.data.group==t&&s.add(a)}s.order(),s.show()}}),this.body.emitter.emit("change")},s.prototype._onRemoveGroups=function(t){var e=this.groups;t.forEach(function(t){var i=e[t];i&&(i.hide(),delete e[t])}),this.markDirty(),this.body.emitter.emit("change")},s.prototype._orderGroups=function(){if(this.groupsData){var t=this.groupsData.getIds({order:this.options.groupOrder}),e=!r.equalArray(t,this.groupIds);if(e){var i=this.groups;t.forEach(function(t){i[t].hide()}),t.forEach(function(t){i[t].show()}),this.groupIds=t}return e}return!1},s.prototype._addItem=function(t){this.items[t.id]=t;var e=this.groupsData?t.data.group:f,i=this.groups[e];i&&i.add(t)},s.prototype._updateItem=function(t,e){var i=t.data.group;if(t.data=e,t.displayed&&t.redraw(),i!=t.data.group){var s=this.groups[i];s&&s.remove(t);var o=this.groupsData?t.data.group:f,n=this.groups[o];n&&n.add(t)}},s.prototype._removeItem=function(t){t.hide(),delete this.items[t.id];var e=this.selection.indexOf(t.id);-1!=e&&this.selection.splice(e,1);var i=this.groupsData?t.data.group:f,s=this.groups[i];s&&s.remove(t)},s.prototype._constructByEndArray=function(t){for(var e=[],i=0;i0||o.length>0)&&this.body.emitter.emit("select",{items:this.getSelection()}),t.stopPropagation()}},s.prototype._onAddItem=function(t){if(this.options.selectable&&this.options.editable.add){var e=this,i=this.body.util.snap||null,o=s.itemFromTarget(t);if(o){var n=e.itemsData.get(o.id);this.options.onUpdate(n,function(t){t&&e.itemsData.update(t)})}else{var a=r.getAbsoluteLeft(this.dom.frame),h=t.gesture.center.pageX-a,d=this.body.util.toTime(h),l={start:i?i(d):d,content:"new item"};if("range"===this.options.type){var c=this.body.util.toTime(h+this.props.width/5);l.end=i?i(c):c}l[this.itemsData.fieldId]=r.randomUUID();var p=s.groupFromTarget(t);p&&(l.group=p.groupId),this.options.onAdd(l,function(t){t&&e.itemsData.add(l)})}}},s.prototype._onMultiSelectItem=function(t){if(this.options.selectable){var e,i=s.itemFromTarget(t);if(i){e=this.getSelection();var o=e.indexOf(i.id);-1==o?e.push(i.id):e.splice(o,1),this.setSelection(e),this.body.emitter.emit("select",{items:this.getSelection()}),t.stopPropagation()}}},s.itemFromTarget=function(t){for(var e=t.target;e;){if(e.hasOwnProperty("timeline-item"))return e["timeline-item"];e=e.parentNode}return null},s.groupFromTarget=function(t){for(var e=t.target;e;){if(e.hasOwnProperty("timeline-group"))return e["timeline-group"];e=e.parentNode}return null},s.itemSetFromTarget=function(t){for(var e=t.target;e;){if(e.hasOwnProperty("timeline-itemset"))return e["timeline-itemset"];e=e.parentNode}return null},t.exports=s},function(t,e,i){function s(t,e,i){this.body=t,this.defaultOptions={enabled:!0,icons:!0,iconSize:20,iconSpacing:6,left:{visible:!0,position:"top-left"},right:{visible:!0,position:"top-left"}},this.side=i,this.options=o.extend({},this.defaultOptions),this.svgElements={},this.dom={},this.groups={},this.amountOfGroups=0,this._create(),this.setOptions(e)}var o=i(2),n=i(1),r=i(19);s.prototype=new r,s.prototype.addGroup=function(t,e){this.groups.hasOwnProperty(t)||(this.groups[t]=e),this.amountOfGroups+=1},s.prototype.updateGroup=function(t,e){this.groups[t]=e},s.prototype.removeGroup=function(t){this.groups.hasOwnProperty(t)&&(delete this.groups[t],this.amountOfGroups-=1)},s.prototype._create=function(){this.dom.frame=document.createElement("div"),this.dom.frame.className="legend",this.dom.frame.style.position="absolute",this.dom.frame.style.top="10px",this.dom.frame.style.display="block",this.dom.textArea=document.createElement("div"),this.dom.textArea.className="legendText",this.dom.textArea.style.position="relative",this.dom.textArea.style.top="0px",this.svg=document.createElementNS("http://www.w3.org/2000/svg","svg"),this.svg.style.position="absolute",this.svg.style.top="0px",this.svg.style.width=this.options.iconSize+5+"px",this.dom.frame.appendChild(this.svg),this.dom.frame.appendChild(this.dom.textArea)},s.prototype.hide=function(){this.dom.frame.parentNode&&this.dom.frame.parentNode.removeChild(this.dom.frame)},s.prototype.show=function(){this.dom.frame.parentNode||this.body.dom.center.appendChild(this.dom.frame)},s.prototype.setOptions=function(t){var e=["enabled","orientation","icons","left","right"];o.selectiveDeepExtend(e,this.options,t)},s.prototype.redraw=function(){var t=0;for(var e in this.groups)this.groups.hasOwnProperty(e)&&1==this.groups[e].visible&&t++;if(0==this.options[this.side].visible||0==this.amountOfGroups||0==this.options.enabled||0==t)this.hide();else{this.show(),"top-left"==this.options[this.side].position||"bottom-left"==this.options[this.side].position?(this.dom.frame.style.left="4px",this.dom.frame.style.textAlign="left",this.dom.textArea.style.textAlign="left",this.dom.textArea.style.left=this.options.iconSize+15+"px",this.dom.textArea.style.right="",this.svg.style.left="0px",this.svg.style.right=""):(this.dom.frame.style.right="4px",this.dom.frame.style.textAlign="right",this.dom.textArea.style.textAlign="right",this.dom.textArea.style.right=this.options.iconSize+15+"px",this.dom.textArea.style.left="",this.svg.style.right="0px",this.svg.style.left=""),"top-left"==this.options[this.side].position||"top-right"==this.options[this.side].position?(this.dom.frame.style.top=4-Number(this.body.dom.center.style.top.replace("px",""))+"px",this.dom.frame.style.bottom=""):(this.dom.frame.style.bottom=4-Number(this.body.dom.center.style.top.replace("px",""))+"px",this.dom.frame.style.top=""),0==this.options.icons?(this.dom.frame.style.width=this.dom.textArea.offsetWidth+10+"px",this.dom.textArea.style.right="",this.dom.textArea.style.left="",this.svg.style.width="0px"):(this.dom.frame.style.width=this.options.iconSize+15+this.dom.textArea.offsetWidth+10+"px",this.drawLegendIcons()); -var i="";for(var e in this.groups)this.groups.hasOwnProperty(e)&&1==this.groups[e].visible&&(i+=this.groups[e].content+"
");this.dom.textArea.innerHTML=i,this.dom.textArea.style.lineHeight=.75*this.options.iconSize+this.options.iconSpacing+"px"}},s.prototype.drawLegendIcons=function(){if(this.dom.frame.parentNode){n.prepareElements(this.svgElements);var t=window.getComputedStyle(this.dom.frame).paddingTop,e=Number(t.replace("px","")),i=e,s=this.options.iconSize,o=.75*this.options.iconSize,r=e+.5*o+3;this.svg.style.width=s+5+e+"px";for(var a in this.groups)this.groups.hasOwnProperty(a)&&1==this.groups[a].visible&&(this.groups[a].drawIcon(i,r,this.svgElements,this.svg,s,o),r+=o+this.options.iconSpacing);n.cleanupElements(this.svgElements)}},t.exports=s},function(t,e,i){function s(t,e){this.id=o.randomUUID(),this.body=t,this.defaultOptions={yAxisOrientation:"left",defaultGroup:"default",sort:!0,sampling:!0,graphHeight:"400px",shaded:{enabled:!1,orientation:"bottom"},style:"line",barChart:{width:50,allowOverlap:!0,align:"center"},catmullRom:{enabled:!0,parametrization:"centripetal",alpha:.5},drawPoints:{enabled:!0,size:6,style:"square"},dataAxis:{showMinorLabels:!0,showMajorLabels:!0,icons:!1,width:"40px",visible:!0},legend:{enabled:!1,icons:!0,left:{visible:!0,position:"top-left"},right:{visible:!0,position:"top-right"}}},this.options=o.extend({},this.defaultOptions),this.dom={},this.props={},this.hammer=null,this.groups={};var i=this;this.itemsData=null,this.groupsData=null,this.itemListeners={add:function(t,e){i._onAdd(e.items)},update:function(t,e){i._onUpdate(e.items)},remove:function(t,e){i._onRemove(e.items)}},this.groupListeners={add:function(t,e){i._onAddGroups(e.items)},update:function(t,e){i._onUpdateGroups(e.items)},remove:function(t,e){i._onRemoveGroups(e.items)}},this.items={},this.selection=[],this.lastStart=this.body.range.start,this.touchParams={},this.svgElements={},this.setOptions(e),this.groupsUsingDefaultStyles=[0],this.body.emitter.on("rangechange",function(){if(0!=i.lastStart){var t=i.body.range.start-i.lastStart,e=i.body.range.end-i.body.range.start;if(0!=i.width){var s=i.width/e,o=t*s;i.svg.style.left=-i.width-o+"px"}}}),this.body.emitter.on("rangechanged",function(){i.lastStart=i.body.range.start,i.svg.style.left=o.option.asSize(-i.width),i._updateGraph.apply(i)}),this._create(),this.body.emitter.emit("change")}var o=i(2),n=i(1),r=i(3),a=i(4),h=i(19),d=i(21),l=i(22),c=i(25),p="__ungrouped__";s.prototype=new h,s.prototype._create=function(){var t=document.createElement("div");t.className="LineGraph",this.dom.frame=t,this.svg=document.createElementNS("http://www.w3.org/2000/svg","svg"),this.svg.style.position="relative",this.svg.style.height=(""+this.options.graphHeight).replace("px","")+"px",this.svg.style.display="block",t.appendChild(this.svg),this.options.dataAxis.orientation="left",this.yAxisLeft=new d(this.body,this.options.dataAxis,this.svg),this.options.dataAxis.orientation="right",this.yAxisRight=new d(this.body,this.options.dataAxis,this.svg),delete this.options.dataAxis.orientation,this.legendLeft=new c(this.body,this.options.legend,"left"),this.legendRight=new c(this.body,this.options.legend,"right"),this.show()},s.prototype.setOptions=function(t){if(t){var e=["sampling","defaultGroup","graphHeight","yAxisOrientation","style","barChart","dataAxis","sort"];o.selectiveDeepExtend(e,this.options,t),o.mergeOptions(this.options,t,"catmullRom"),o.mergeOptions(this.options,t,"drawPoints"),o.mergeOptions(this.options,t,"shaded"),o.mergeOptions(this.options,t,"legend"),t.catmullRom&&"object"==typeof t.catmullRom&&t.catmullRom.parametrization&&("uniform"==t.catmullRom.parametrization?this.options.catmullRom.alpha=0:"chordal"==t.catmullRom.parametrization?this.options.catmullRom.alpha=1:(this.options.catmullRom.parametrization="centripetal",this.options.catmullRom.alpha=.5)),this.yAxisLeft&&void 0!==t.dataAxis&&(this.yAxisLeft.setOptions(this.options.dataAxis),this.yAxisRight.setOptions(this.options.dataAxis)),this.legendLeft&&void 0!==t.legend&&(this.legendLeft.setOptions(this.options.legend),this.legendRight.setOptions(this.options.legend)),this.groups.hasOwnProperty(p)&&this.groups[p].setOptions(t)}this.dom.frame&&this._updateGraph()},s.prototype.hide=function(){this.dom.frame.parentNode&&this.dom.frame.parentNode.removeChild(this.dom.frame)},s.prototype.show=function(){this.dom.frame.parentNode||this.body.dom.center.appendChild(this.dom.frame)},s.prototype.setItems=function(t){var e,i=this,s=this.itemsData;if(t){if(!(t instanceof r||t instanceof a))throw new TypeError("Data must be an instance of DataSet or DataView");this.itemsData=t}else this.itemsData=null;if(s&&(o.forEach(this.itemListeners,function(t,e){s.off(e,t)}),e=s.getIds(),this._onRemove(e)),this.itemsData){var n=this.id;o.forEach(this.itemListeners,function(t,e){i.itemsData.on(e,t,n)}),e=this.itemsData.getIds(),this._onAdd(e)}this._updateUngrouped(),this._updateGraph(),this.redraw()},s.prototype.setGroups=function(t){var e,i=this;if(this.groupsData&&(o.forEach(this.groupListeners,function(t,e){i.groupsData.unsubscribe(e,t)}),e=this.groupsData.getIds(),this.groupsData=null,this._onRemoveGroups(e)),t){if(!(t instanceof r||t instanceof a))throw new TypeError("Data must be an instance of DataSet or DataView");this.groupsData=t}else this.groupsData=null;if(this.groupsData){var s=this.id;o.forEach(this.groupListeners,function(t,e){i.groupsData.on(e,t,s)}),e=this.groupsData.getIds(),this._onAddGroups(e)}this._onUpdate()},s.prototype._onUpdate=function(){this._updateUngrouped(),this._updateAllGroupData(),this._updateGraph(),this.redraw()},s.prototype._onAdd=function(t){this._onUpdate(t)},s.prototype._onRemove=function(t){this._onUpdate(t)},s.prototype._onUpdateGroups=function(t){for(var e=0;e0){for(s=0;su){e.push(g);break}e.push(g)}}else for(var m=0;mp&&g.x0?(i=this._preprocessData(e,t),h.push({min:i.min,max:i.max}),r.push(i.data)):(h.push({}),r.push([]))}else h.push({}),r.push([]);if(d=this._updateYAxis(l,h),1==d)return n.cleanupElements(this.svgElements),void this.body.emitter.emit("change");for(s=0;s0){for(var p=0;pi?i:a,d=s>d?s:d):(r=!0,h=h>i?i:h,l=s>l?s:l))}1==n&&this.yAxisLeft.setRange(a,d),1==r&&this.yAxisRight.setRange(h,l)}return o=this._toggleAxisVisiblity(n,this.yAxisLeft)||o,o=this._toggleAxisVisiblity(r,this.yAxisRight)||o,1==r&&1==n?(this.yAxisLeft.drawIcons=!0,this.yAxisRight.drawIcons=!0):(this.yAxisLeft.drawIcons=!1,this.yAxisRight.drawIcons=!1),this.yAxisRight.master=!n,0==this.yAxisRight.master?(this.yAxisLeft.lineOffset=1==r?this.yAxisRight.width:0,o=this.yAxisLeft.redraw()||o,this.yAxisRight.stepPixelsForced=this.yAxisLeft.stepPixels,o=this.yAxisRight.redraw()||o):o=this.yAxisRight.redraw()||o,o},s.prototype._toggleAxisVisiblity=function(t,e){var i=!1;return 0==t?e.dom.frame.parentNode&&(e.hide(),i=!0):e.dom.frame.parentNode||(e.show(),i=!0),i},s.prototype._drawBarGraph=function(t,e){if(null!=t&&t.length>0){for(var i,s=.1*e.options.barChart.width,o=0,r={},a=0;a0&&(i=Math.min(i,Math.abs(t[a-1].x-t[a].x))),0==i&&(void 0===r[t[a].x]&&(r[t[a].x]={amount:0,resolved:0}),r[t[a].x].amount+=1);for(var h,a=0;a0&&(i=Math.min(i,Math.abs(t[a-1].x-h)));var d=this._getSafeDrawData(i,e,s)}else{var l=a+(r[h].amount-r[h].resolved),c=a-(r[h].resolved+1);l0&&(i=Math.min(i,Math.abs(t[c].x-h)));var d=this._getSafeDrawData(i,e,s);r[h].resolved+=1,0==e.options.barChart.allowOverlap&&(d.width=d.width/r[h].amount,d.offset+=r[h].resolved*d.width-.5*d.width*(r[h].amount+1),"left"==e.options.barChart.align?o-=.5*d.width:"right"==e.options.barChart.align&&(o+=.5*d.width))}n.drawBar(t[a].x+d.offset,t[a].y,d.width,e.zeroPosition-t[a].y,e.className+" bar",this.svgElements,this.svg)}1==e.options.drawPoints.enabled&&this._drawPoints(t,e,this.svgElements,this.svg,o)}},s.prototype._getSafeDrawData=function(t,e,i){var s,o;return t0?(s=i>t?i:t,o=0,e.options.slots&&(s/=e.options.slots.total,o=e.options.slots.slot*s-.5*s*(e.options.slots.total+1)),"left"==e.options.barChart.align?o-=.5*t:"right"==e.options.barChart.align&&(o+=.5*t)):(s=e.options.barChart.width,o=0,e.options.slots&&(s/=e.options.slots.total,o=e.options.slots.slot*s-.5*s*(e.options.slots.total+1)),"left"==e.options.barChart.align?o-=.5*e.options.barChart.width:"right"==e.options.barChart.align&&(o+=.5*e.options.barChart.width)),{width:s,offset:o}},s.prototype._drawLineGraph=function(t,e){if(null!=t&&t.length>0){var i,s,o=Number(this.svg.style.height.replace("px",""));if(i=n.getSVGElement("path",this.svgElements,this.svg),i.setAttributeNS(null,"class",e.className),s=1==e.options.catmullRom.enabled?this._catmullRom(t,e):this._linear(t),1==e.options.shaded.enabled){var r,a=n.getSVGElement("path",this.svgElements,this.svg);r="top"==e.options.shaded.orientation?"M"+t[0].x+",0 "+s+"L"+t[t.length-1].x+",0":"M"+t[0].x+","+o+" "+s+"L"+t[t.length-1].x+","+o,a.setAttributeNS(null,"class",e.className+" fill"),a.setAttributeNS(null,"d",r)}i.setAttributeNS(null,"d","M"+s),1==e.options.drawPoints.enabled&&this._drawPoints(t,e,this.svgElements,this.svg)}},s.prototype._drawPoints=function(t,e,i,s,o){void 0===o&&(o=0);for(var r=0;rp;p+=r)i=n(t[p].x)+this.width-1,s=t[p].y,o.push({x:i,y:s}),h=h>s?s:h,d=s>d?s:d;return{min:h,max:d,data:o}},s.prototype._convertYvalues=function(t,e){var i,s,o=[],n=this.yAxisLeft,r=Number(this.svg.style.height.replace("px",""));"right"==e.options.yAxisOrientation&&(n=this.yAxisRight);for(var a=0;al;l++)e=0==l?t[0]:t[l-1],i=t[l],s=t[l+1],o=d>l+2?t[l+2]:s,n={x:(-e.x+6*i.x+s.x)*h,y:(-e.y+6*i.y+s.y)*h},r={x:(i.x+6*s.x-o.x)*h,y:(i.y+6*s.y-o.y)*h},a+="C"+n.x+","+n.y+" "+r.x+","+r.y+" "+s.x+","+s.y+" ";return a},s.prototype._catmullRom=function(t,e){var i=e.options.catmullRom.alpha;if(0==i||void 0===i)return this._catmullRomUniform(t);for(var s,o,n,r,a,h,d,l,c,p,u,f,m,g,v,y,b,_,x,w=Math.round(t[0].x)+","+Math.round(t[0].y)+" ",S=t.length,M=0;S-1>M;M++)s=0==M?t[0]:t[M-1],o=t[M],n=t[M+1],r=S>M+2?t[M+2]:n,d=Math.sqrt(Math.pow(s.x-o.x,2)+Math.pow(s.y-o.y,2)),l=Math.sqrt(Math.pow(o.x-n.x,2)+Math.pow(o.y-n.y,2)),c=Math.sqrt(Math.pow(n.x-r.x,2)+Math.pow(n.y-r.y,2)),g=Math.pow(c,i),y=Math.pow(c,2*i),v=Math.pow(l,i),b=Math.pow(l,2*i),x=Math.pow(d,i),_=Math.pow(d,2*i),p=2*_+3*x*v+b,u=2*y+3*g*v+b,f=3*x*(x+v),f>0&&(f=1/f),m=3*g*(g+v),m>0&&(m=1/m),a={x:(-b*s.x+p*o.x+_*n.x)*f,y:(-b*s.y+p*o.y+_*n.y)*f},h={x:(y*o.x+u*n.x-b*r.x)*m,y:(y*o.y+u*n.y-b*r.y)*m},0==a.x&&0==a.y&&(a=o),0==h.x&&0==h.y&&(h=n),w+="C"+a.x+","+a.y+" "+h.x+","+h.y+" "+n.x+","+n.y+" ";return w},s.prototype._linear=function(t){for(var e="",i=0;id;){d++;var l=n.getCurrent(),c=this.body.util.toScreen(l),p=n.isMajor();this.options.showMinorLabels&&this._repaintMinorText(c,n.getLabelMinor(),t),p&&this.options.showMajorLabels?(c>0&&(void 0==h&&(h=c),this._repaintMajorText(c,n.getLabelMajor(),t)),this._repaintMajorLine(c,t)):this._repaintMinorLine(c,t),n.next()}if(this.options.showMajorLabels){var u=this.body.util.toTime(0),f=n.getLabelMajor(u),m=f.length*(this.props.majorCharWidth||10)+10;(void 0==h||h>m)&&this._repaintMajorText(0,f,t)}o.forEach(this.dom.redundant,function(t){for(;t.length;){var e=t.pop();e&&e.parentNode&&e.parentNode.removeChild(e)}})},s.prototype._repaintMinorText=function(t,e,i){var s=this.dom.redundant.minorTexts.shift();if(!s){var o=document.createTextNode("");s=document.createElement("div"),s.appendChild(o),s.className="text minor",this.dom.foreground.appendChild(s)}this.dom.minorTexts.push(s),s.childNodes[0].nodeValue=e,s.style.top="top"==i?this.props.majorLabelHeight+"px":"0",s.style.left=t+"px"},s.prototype._repaintMajorText=function(t,e,i){var s=this.dom.redundant.majorTexts.shift();if(!s){var o=document.createTextNode(e);s=document.createElement("div"),s.className="text major",s.appendChild(o),this.dom.foreground.appendChild(s)}this.dom.majorTexts.push(s),s.childNodes[0].nodeValue=e,s.style.top="top"==i?"0":this.props.minorLabelHeight+"px",s.style.left=t+"px"},s.prototype._repaintMinorLine=function(t,e){var i=this.dom.redundant.minorLines.shift();i||(i=document.createElement("div"),i.className="grid vertical minor",this.dom.background.appendChild(i)),this.dom.minorLines.push(i);var s=this.props;i.style.top="top"==e?s.majorLabelHeight+"px":this.body.domProps.top.height+"px",i.style.height=s.minorLineHeight+"px",i.style.left=t-s.minorLineWidth/2+"px"},s.prototype._repaintMajorLine=function(t,e){var i=this.dom.redundant.majorLines.shift();i||(i=document.createElement("DIV"),i.className="grid vertical major",this.dom.background.appendChild(i)),this.dom.majorLines.push(i);var s=this.props;i.style.top="top"==e?"0":this.body.domProps.top.height+"px",i.style.left=t-s.majorLineWidth/2+"px",i.style.height=s.majorLineHeight+"px"},s.prototype._calculateCharSize=function(){this.dom.measureCharMinor||(this.dom.measureCharMinor=document.createElement("DIV"),this.dom.measureCharMinor.className="text minor measure",this.dom.measureCharMinor.style.position="absolute",this.dom.measureCharMinor.appendChild(document.createTextNode("0")),this.dom.foreground.appendChild(this.dom.measureCharMinor)),this.props.minorCharHeight=this.dom.measureCharMinor.clientHeight,this.props.minorCharWidth=this.dom.measureCharMinor.clientWidth,this.dom.measureCharMajor||(this.dom.measureCharMajor=document.createElement("DIV"),this.dom.measureCharMajor.className="text minor measure",this.dom.measureCharMajor.style.position="absolute",this.dom.measureCharMajor.appendChild(document.createTextNode("0")),this.dom.foreground.appendChild(this.dom.measureCharMajor)),this.props.majorCharHeight=this.dom.measureCharMajor.clientHeight,this.props.majorCharWidth=this.dom.measureCharMajor.clientWidth},s.prototype.snap=function(t){return this.step.snap(t)},t.exports=s},function(t,e,i){function s(t,e,i){this.id=null,this.parent=null,this.data=t,this.dom=null,this.conversion=e||{},this.options=i||{},this.selected=!1,this.displayed=!1,this.dirty=!0,this.top=null,this.left=null,this.width=null,this.height=null}var o=i(40);s.prototype.select=function(){this.selected=!0,this.displayed&&this.redraw()},s.prototype.unselect=function(){this.selected=!1,this.displayed&&this.redraw()},s.prototype.setParent=function(t){this.displayed?(this.hide(),this.parent=t,this.parent&&this.show()):this.parent=t},s.prototype.isVisible=function(){return!1},s.prototype.show=function(){return!1},s.prototype.hide=function(){return!1},s.prototype.redraw=function(){},s.prototype.repositionX=function(){},s.prototype.repositionY=function(){},s.prototype._repaintDeleteButton=function(t){if(this.selected&&this.options.editable.remove&&!this.dom.deleteButton){var e=this,i=document.createElement("div");i.className="delete",i.title="Delete this item",o(i,{preventDefault:!0}).on("tap",function(t){e.parent.removeFromDataSet(e),t.stopPropagation()}),t.appendChild(i),this.dom.deleteButton=i}else!this.selected&&this.dom.deleteButton&&(this.dom.deleteButton.parentNode&&this.dom.deleteButton.parentNode.removeChild(this.dom.deleteButton),this.dom.deleteButton=null)},t.exports=s},function(t,e,i){function s(t,e,i){if(this.props={dot:{width:0,height:0},line:{width:0,height:0}},t&&void 0==t.start)throw new Error('Property "start" missing in item '+t);o.call(this,t,e,i)}var o=i(28);s.prototype=new o(null,null,null),s.prototype.isVisible=function(t){var e=(t.end-t.start)/4;return this.data.start>t.start-e&&this.data.startt.start-e&&this.data.startt.start},s.prototype.redraw=function(){var t=this.dom;if(t||(this.dom={},t=this.dom,t.box=document.createElement("div"),t.content=document.createElement("div"),t.content.className="content",t.box.appendChild(t.content),t.box["timeline-item"]=this),!this.parent)throw new Error("Cannot redraw item: no parent attached");if(!t.box.parentNode){var e=this.parent.dom.foreground;if(!e)throw new Error("Cannot redraw time axis: parent has no foreground container element");e.appendChild(t.box)}if(this.displayed=!0,this.data.content!=this.content){if(this.content=this.data.content,this.content instanceof Element)t.content.innerHTML="",t.content.appendChild(this.content);else{if(void 0==this.data.content)throw new Error('Property "content" missing in item '+this.data.id);t.content.innerHTML=this.content}this.dirty=!0}this.data.title!=this.title&&(t.box.title=this.data.title,this.title=this.data.title);var i=(this.data.className?" "+this.data.className:"")+(this.selected?" selected":"");this.className!=i&&(this.className=i,t.box.className=this.baseClassName+i,this.dirty=!0),this.dirty&&(this.overflow="hidden"!==window.getComputedStyle(t.content).overflow,this.props.content.width=this.dom.content.offsetWidth,this.height=this.dom.box.offsetHeight,this.dirty=!1),this._repaintDeleteButton(t.box),this._repaintDragLeft(),this._repaintDragRight()},s.prototype.show=function(){this.displayed||this.redraw()},s.prototype.hide=function(){if(this.displayed){var t=this.dom.box;t.parentNode&&t.parentNode.removeChild(t),this.top=null,this.left=null,this.displayed=!1}},s.prototype.repositionX=function(){var t,e=this.props,i=this.parent.width,s=this.conversion.toScreen(this.data.start),o=this.conversion.toScreen(this.data.end),n=this.options.padding;-i>s&&(s=-i),o>2*i&&(o=2*i);var r=Math.max(o-s,1);this.overflow?(t=Math.max(-s,0),this.left=s,this.width=r+this.props.content.width):(t=0>s?Math.min(-s,o-s-e.content.width-2*n):0,this.left=s,this.width=r),this.dom.box.style.left=this.left+"px",this.dom.box.style.width=r+"px",this.dom.content.style.left=t+"px"},s.prototype.repositionY=function(){var t=this.options.orientation,e=this.dom.box;e.style.top="top"==t?this.top+"px":this.parent.height-this.top-this.height+"px"},s.prototype._repaintDragLeft=function(){if(this.selected&&this.options.editable.updateTime&&!this.dom.dragLeft){var t=document.createElement("div");t.className="drag-left",t.dragLeftItem=this,o(t,{preventDefault:!0}).on("drag",function(){}),this.dom.box.appendChild(t),this.dom.dragLeft=t}else!this.selected&&this.dom.dragLeft&&(this.dom.dragLeft.parentNode&&this.dom.dragLeft.parentNode.removeChild(this.dom.dragLeft),this.dom.dragLeft=null)},s.prototype._repaintDragRight=function(){if(this.selected&&this.options.editable.updateTime&&!this.dom.dragRight){var t=document.createElement("div");t.className="drag-right",t.dragRightItem=this,o(t,{preventDefault:!0}).on("drag",function(){}),this.dom.box.appendChild(t),this.dom.dragRight=t}else!this.selected&&this.dom.dragRight&&(this.dom.dragRight.parentNode&&this.dom.dragRight.parentNode.removeChild(this.dom.dragRight),this.dom.dragRight=null) -},t.exports=s},function(t,e,i){function s(t,e,i){if(!(this instanceof s))throw new SyntaxError("Constructor must be called with the new operator");this._initializeMixinLoaders(),this.containerElement=t,this.renderRefreshRate=60,this.renderTimestep=1e3/this.renderRefreshRate,this.renderTime=.5*this.renderTimestep,this.maxPhysicsTicksPerRender=3,this.physicsDiscreteStepsize=.5,this.initializing=!0,this.triggerFunctions={add:null,edit:null,editEdge:null,connect:null,del:null},this.defaultOptions={nodes:{mass:1,radiusMin:10,radiusMax:30,radius:10,shape:"ellipse",image:void 0,widthMin:16,widthMax:64,fixed:!1,fontColor:"black",fontSize:14,fontFace:"verdana",level:-1,color:{border:"#2B7CE9",background:"#97C2FC",highlight:{border:"#2B7CE9",background:"#D2E5FF"},hover:{border:"#2B7CE9",background:"#D2E5FF"}},borderColor:"#2B7CE9",backgroundColor:"#97C2FC",highlightColor:"#D2E5FF",group:void 0,borderWidth:1},edges:{widthMin:1,widthMax:15,width:1,widthSelectionMultiplier:2,hoverWidth:1.5,style:"line",color:{color:"#848484",highlight:"#848484",hover:"#848484"},fontColor:"#343434",fontSize:14,fontFace:"arial",fontFill:"white",arrowScaleFactor:1,dash:{length:10,gap:5,altLength:void 0},inheritColor:"from"},configurePhysics:!1,physics:{barnesHut:{enabled:!0,theta:1/.6,gravitationalConstant:-2e3,centralGravity:.3,springLength:95,springConstant:.04,damping:.09},repulsion:{centralGravity:0,springLength:200,springConstant:.05,nodeDistance:100,damping:.09},hierarchicalRepulsion:{enabled:!1,centralGravity:0,springLength:100,springConstant:.01,nodeDistance:150,damping:.09},damping:null,centralGravity:null,springLength:null,springConstant:null},clustering:{enabled:!1,initialMaxNodes:100,clusterThreshold:500,reduceToNodes:300,chainThreshold:.4,clusterEdgeThreshold:20,sectorThreshold:100,screenSizeThreshold:.2,fontSizeMultiplier:4,maxFontSize:1e3,forceAmplification:.1,distanceAmplification:.1,edgeGrowth:20,nodeScaling:{width:1,height:1,radius:1},maxNodeSizeIncrements:600,activeAreaBoxSize:80,clusterLevelDifference:2},navigation:{enabled:!1},keyboard:{enabled:!1,speed:{x:10,y:10,zoom:.02}},dataManipulation:{enabled:!1,initiallyVisible:!1},hierarchicalLayout:{enabled:!1,levelSeparation:150,nodeSpacing:100,direction:"UD"},freezeForStabilization:!1,smoothCurves:{enabled:!0,dynamic:!0,type:"continuous",roundness:.5},dynamicSmoothCurves:!0,maxVelocity:30,minVelocity:.1,stabilize:!0,stabilizationIterations:1e3,labels:{add:"Add Node",edit:"Edit",link:"Add Link",del:"Delete selected",editNode:"Edit Node",editEdge:"Edit Edge",back:"Back",addDescription:"Click in an empty space to place a new node.",linkDescription:"Click on a node and drag the edge to another node to connect them.",editEdgeDescription:"Click on the control points and drag them to a node to connect to it.",addError:"The function for add does not support two arguments (data,callback).",linkError:"The function for connect does not support two arguments (data,callback).",editError:"The function for edit does not support two arguments (data, callback).",editBoundError:"No edit function has been bound to this button.",deleteError:"The function for delete does not support two arguments (data, callback).",deleteClusterError:"Clusters cannot be deleted."},tooltip:{delay:300,fontColor:"black",fontSize:14,fontFace:"verdana",color:{border:"#666",background:"#FFFFC6"}},dragNetwork:!0,dragNodes:!0,zoomable:!0,hover:!1,hideEdgesOnDrag:!1,hideNodesOnDrag:!1,width:"100%",height:"100%",selectable:!0},this.constants=a.extend({},this.defaultOptions),this.hoverObj={nodes:{},edges:{}},this.controlNodesActive=!1;var o=this;this.groups=new u,this.images=new f,this.images.setOnloadCallback(function(){o._redraw()}),this.xIncrement=0,this.yIncrement=0,this.zoomIncrement=0,this._loadPhysicsSystem(),this._create(),this._loadSectorSystem(),this._loadClusterSystem(),this._loadSelectionSystem(),this._loadHierarchySystem(),this._setTranslation(this.frame.clientWidth/2,this.frame.clientHeight/2),this._setScale(1),this.setOptions(i),this.freezeSimulation=!1,this.cachedFunctions={},this.calculationNodes={},this.calculationNodeIndices=[],this.nodeIndices=[],this.nodes={},this.edges={},this.canvasTopLeft={x:0,y:0},this.canvasBottomRight={x:0,y:0},this.pointerPosition={x:0,y:0},this.areaCenter={},this.scale=1,this.previousScale=this.scale,this.nodesData=null,this.edgesData=null,this.nodesListeners={add:function(t,e){o._addNodes(e.items),o.start()},update:function(t,e){o._updateNodes(e.items),o.start()},remove:function(t,e){o._removeNodes(e.items),o.start()}},this.edgesListeners={add:function(t,e){o._addEdges(e.items),o.start()},update:function(t,e){o._updateEdges(e.items),o.start()},remove:function(t,e){o._removeEdges(e.items),o.start()}},this.moving=!0,this.timer=void 0,this.setData(e,this.constants.clustering.enabled||this.constants.hierarchicalLayout.enabled),this.initializing=!1,1==this.constants.hierarchicalLayout.enabled?this._setupHierarchicalLayout():0==this.constants.stabilize&&this.zoomExtent(!0,this.constants.clustering.enabled),this.constants.clustering.enabled&&this.startWithClustering()}var o=i(46),n=i(40),r=i(47),a=i(2),h=i(43),d=i(3),l=i(4),c=i(38),p=i(39),u=i(34),f=i(35),m=i(36),g=i(33),v=i(37),y=i(45);i(44),o(s.prototype),s.prototype._getScriptPath=function(){for(var t=document.getElementsByTagName("script"),e=0;et.x&&(s=t.x),ot.y&&(e=t.y),i=this.constants.clustering.initialMaxNodes?49.07548/(o+142.05338)+91444e-8:12.662/(o+7.4147)+.0964822:1==this.constants.clustering.enabled&&o>=this.constants.clustering.initialMaxNodes?77.5271985/(o+187.266146)+476710517e-13:30.5062972/(o+19.93597763)+.08413486;var n=Math.min(this.frame.canvas.clientWidth/600,this.frame.canvas.clientHeight/600);i*=n}else{var r=1.1*(Math.abs(s.minX)+Math.abs(s.maxX)),a=1.1*(Math.abs(s.minY)+Math.abs(s.maxY)),h=this.frame.canvas.clientWidth/r,d=this.frame.canvas.clientHeight/a;i=d>=h?h:d}i>1&&(i=1),this._setScale(i),this._centerNetwork(s),0==e&&(this.moving=!0,this.start())},s.prototype._updateNodeIndexList=function(){this._clearNodeIndexList();for(var t in this.nodes)this.nodes.hasOwnProperty(t)&&this.nodeIndices.push(t)},s.prototype.setData=function(t,e){if(void 0===e&&(e=!1),t&&t.dot&&(t.nodes||t.edges))throw new SyntaxError('Data must contain either parameter "dot" or parameter pair "nodes" and "edges", but not both.');if(this.setOptions(t&&t.options),t&&t.dot){if(t&&t.dot){var i=c.DOTToGraph(t.dot);return void this.setData(i)}}else if(t&&t.gephi){if(t&&t.gephi){var s=p.parseGephi(t.gephi);return void this.setData(s)}}else this._setNodes(t&&t.nodes),this._setEdges(t&&t.edges);if(this._putDataInSector(),!e)if(this.constants.stabilize){var o=this;setTimeout(function(){o._stabilize(),o.start()},0)}else this.start()},s.prototype.setOptions=function(t){if(t){var e,i=["nodes","edges","smoothCurves","hierarchicalLayout","clustering","navigation","keyboard","dataManipulation","onAdd","onEdit","onEditEdge","onConnect","onDelete"];if(a.selectiveNotDeepExtend(i,this.constants,t),a.selectiveNotDeepExtend(["color"],this.constants.nodes,t.nodes),a.selectiveNotDeepExtend(["color","length"],this.constants.edges,t.edges),t.physics&&(a.mergeOptions(this.constants.physics,t.physics,"barnesHut"),a.mergeOptions(this.constants.physics,t.physics,"repulsion"),t.physics.hierarchicalRepulsion)){this.constants.hierarchicalLayout.enabled=!0,this.constants.physics.hierarchicalRepulsion.enabled=!0,this.constants.physics.barnesHut.enabled=!1;for(e in t.physics.hierarchicalRepulsion)t.physics.hierarchicalRepulsion.hasOwnProperty(e)&&(this.constants.physics.hierarchicalRepulsion[e]=t.physics.hierarchicalRepulsion[e])}if(t.onAdd&&(this.triggerFunctions.add=t.onAdd),t.onEdit&&(this.triggerFunctions.edit=t.onEdit),t.onEditEdge&&(this.triggerFunctions.editEdge=t.onEditEdge),t.onConnect&&(this.triggerFunctions.connect=t.onConnect),t.onDelete&&(this.triggerFunctions.del=t.onDelete),a.mergeOptions(this.constants,t,"smoothCurves"),a.mergeOptions(this.constants,t,"hierarchicalLayout"),a.mergeOptions(this.constants,t,"clustering"),a.mergeOptions(this.constants,t,"navigation"),a.mergeOptions(this.constants,t,"keyboard"),a.mergeOptions(this.constants,t,"dataManipulation"),t.dataManipulation&&(this.editMode=this.constants.dataManipulation.initiallyVisible),t.edges&&(void 0!==t.edges.color&&(a.isString(t.edges.color)?(this.constants.edges.color={},this.constants.edges.color.color=t.edges.color,this.constants.edges.color.highlight=t.edges.color,this.constants.edges.color.hover=t.edges.color):(void 0!==t.edges.color.color&&(this.constants.edges.color.color=t.edges.color.color),void 0!==t.edges.color.highlight&&(this.constants.edges.color.highlight=t.edges.color.highlight),void 0!==t.edges.color.hover&&(this.constants.edges.color.hover=t.edges.color.hover))),t.edges.fontColor||void 0!==t.edges.color&&(a.isString(t.edges.color)?this.constants.edges.fontColor=t.edges.color:void 0!==t.edges.color.color&&(this.constants.edges.fontColor=t.edges.color.color))),t.nodes&&t.nodes.color){var s=a.parseColor(t.nodes.color);this.constants.nodes.color.background=s.background,this.constants.nodes.color.border=s.border,this.constants.nodes.color.highlight.background=s.highlight.background,this.constants.nodes.color.highlight.border=s.highlight.border,this.constants.nodes.color.hover.background=s.hover.background,this.constants.nodes.color.hover.border=s.hover.border}if(t.groups)for(var o in t.groups)if(t.groups.hasOwnProperty(o)){var n=t.groups[o];this.groups.add(o,n)}if(t.tooltip){for(e in t.tooltip)t.tooltip.hasOwnProperty(e)&&(this.constants.tooltip[e]=t.tooltip[e]);t.tooltip.color&&(this.constants.tooltip.color=a.parseColor(t.tooltip.color))}}this._loadPhysicsSystem(),this._loadNavigationControls(),this._loadManipulationSystem(),this._configureSmoothCurves(),this._createKeyBinds(),this.setSize(this.constants.width,this.constants.height),this.moving=!0,this.start()},s.prototype._create=function(){for(;this.containerElement.hasChildNodes();)this.containerElement.removeChild(this.containerElement.firstChild);if(this.frame=document.createElement("div"),this.frame.className="network-frame",this.frame.style.position="relative",this.frame.style.overflow="hidden",this.frame.canvas=document.createElement("canvas"),this.frame.canvas.style.position="relative",this.frame.appendChild(this.frame.canvas),!this.frame.canvas.getContext){var t=document.createElement("DIV");t.style.color="red",t.style.fontWeight="bold",t.style.padding="10px",t.innerHTML="Error: your browser does not support HTML canvas",this.frame.canvas.appendChild(t)}var e=this;this.drag={},this.pinch={},this.hammer=n(this.frame.canvas,{prevent_default:!0}),this.hammer.on("tap",e._onTap.bind(e)),this.hammer.on("doubletap",e._onDoubleTap.bind(e)),this.hammer.on("hold",e._onHold.bind(e)),this.hammer.on("pinch",e._onPinch.bind(e)),this.hammer.on("touch",e._onTouch.bind(e)),this.hammer.on("dragstart",e._onDragStart.bind(e)),this.hammer.on("drag",e._onDrag.bind(e)),this.hammer.on("dragend",e._onDragEnd.bind(e)),this.hammer.on("release",e._onRelease.bind(e)),this.hammer.on("mousewheel",e._onMouseWheel.bind(e)),this.hammer.on("DOMMouseScroll",e._onMouseWheel.bind(e)),this.hammer.on("mousemove",e._onMouseMoveTitle.bind(e)),this.containerElement.appendChild(this.frame)},s.prototype._createKeyBinds=function(){var t=this;this.mousetrap=r,this.mousetrap.reset(),1==this.constants.keyboard.enabled&&(this.mousetrap.bind("up",this._moveUp.bind(t),"keydown"),this.mousetrap.bind("up",this._yStopMoving.bind(t),"keyup"),this.mousetrap.bind("down",this._moveDown.bind(t),"keydown"),this.mousetrap.bind("down",this._yStopMoving.bind(t),"keyup"),this.mousetrap.bind("left",this._moveLeft.bind(t),"keydown"),this.mousetrap.bind("left",this._xStopMoving.bind(t),"keyup"),this.mousetrap.bind("right",this._moveRight.bind(t),"keydown"),this.mousetrap.bind("right",this._xStopMoving.bind(t),"keyup"),this.mousetrap.bind("=",this._zoomIn.bind(t),"keydown"),this.mousetrap.bind("=",this._stopZoom.bind(t),"keyup"),this.mousetrap.bind("-",this._zoomOut.bind(t),"keydown"),this.mousetrap.bind("-",this._stopZoom.bind(t),"keyup"),this.mousetrap.bind("[",this._zoomIn.bind(t),"keydown"),this.mousetrap.bind("[",this._stopZoom.bind(t),"keyup"),this.mousetrap.bind("]",this._zoomOut.bind(t),"keydown"),this.mousetrap.bind("]",this._stopZoom.bind(t),"keyup"),this.mousetrap.bind("pageup",this._zoomIn.bind(t),"keydown"),this.mousetrap.bind("pageup",this._stopZoom.bind(t),"keyup"),this.mousetrap.bind("pagedown",this._zoomOut.bind(t),"keydown"),this.mousetrap.bind("pagedown",this._stopZoom.bind(t),"keyup")),1==this.constants.dataManipulation.enabled&&(this.mousetrap.bind("escape",this._createManipulatorBar.bind(t)),this.mousetrap.bind("del",this._deleteSelected.bind(t)))},s.prototype._getPointer=function(t){return{x:t.pageX-a.getAbsoluteLeft(this.frame.canvas),y:t.pageY-a.getAbsoluteTop(this.frame.canvas)}},s.prototype._onTouch=function(t){this.drag.pointer=this._getPointer(t.gesture.center),this.drag.pinched=!1,this.pinch.scale=this._getScale(),this._handleTouch(this.drag.pointer)},s.prototype._onDragStart=function(){this._handleDragStart()},s.prototype._handleDragStart=function(){var t=this.drag,e=this._getNodeAt(t.pointer);if(t.dragging=!0,t.selection=[],t.translation=this._getTranslation(),t.nodeId=null,null!=e){t.nodeId=e.id,e.isSelected()||this._selectObject(e,!1);for(var i in this.selectionObj.nodes)if(this.selectionObj.nodes.hasOwnProperty(i)){var s=this.selectionObj.nodes[i],o={id:s.id,node:s,x:s.x,y:s.y,xFixed:s.xFixed,yFixed:s.yFixed};s.xFixed=!0,s.yFixed=!0,t.selection.push(o)}}},s.prototype._onDrag=function(t){this._handleOnDrag(t)},s.prototype._handleOnDrag=function(t){if(!this.drag.pinched){var e=this._getPointer(t.gesture.center),i=this,s=this.drag,o=s.selection;if(o&&o.length&&1==this.constants.dragNodes){var n=e.x-s.pointer.x,r=e.y-s.pointer.y;o.forEach(function(t){var e=t.node;t.xFixed||(e.x=i._XconvertDOMtoCanvas(i._XconvertCanvasToDOM(t.x)+n)),t.yFixed||(e.y=i._YconvertDOMtoCanvas(i._YconvertCanvasToDOM(t.y)+r))}),this.moving||(this.moving=!0,this.start())}else if(1==this.constants.dragNetwork){var a=e.x-this.drag.pointer.x,h=e.y-this.drag.pointer.y;this._setTranslation(this.drag.translation.x+a,this.drag.translation.y+h),this._redraw()}}},s.prototype._onDragEnd=function(){this.drag.dragging=!1;var t=this.drag.selection;t&&t.length?(t.forEach(function(t){t.node.xFixed=t.xFixed,t.node.yFixed=t.yFixed}),this.moving=!0,this.start()):this._redraw()},s.prototype._onTap=function(t){var e=this._getPointer(t.gesture.center);this.pointerPosition=e,this._handleTap(e)},s.prototype._onDoubleTap=function(t){var e=this._getPointer(t.gesture.center);this._handleDoubleTap(e)},s.prototype._onHold=function(t){var e=this._getPointer(t.gesture.center);this.pointerPosition=e,this._handleOnHold(e)},s.prototype._onRelease=function(t){var e=this._getPointer(t.gesture.center);this._handleOnRelease(e)},s.prototype._onPinch=function(t){var e=this._getPointer(t.gesture.center);this.drag.pinched=!0,"scale"in this.pinch||(this.pinch.scale=1);var i=this.pinch.scale*t.gesture.scale;this._zoom(i,e)},s.prototype._zoom=function(t,e){if(1==this.constants.zoomable){var i=this._getScale();1e-5>t&&(t=1e-5),t>10&&(t=10);var s=null;void 0!==this.drag&&1==this.drag.dragging&&(s=this.DOMtoCanvas(this.drag.pointer));var o=this._getTranslation(),n=t/i,r=(1-n)*e.x+o.x*n,a=(1-n)*e.y+o.y*n;if(this.areaCenter={x:this._XconvertDOMtoCanvas(e.x),y:this._YconvertDOMtoCanvas(e.y)},this._setScale(t),this._setTranslation(r,a),this.updateClustersDefault(),null!=s){var h=this.canvasToDOM(s);this.drag.pointer.x=h.x,this.drag.pointer.y=h.y}return this._redraw(),t>i?this.emit("zoom",{direction:"+"}):this.emit("zoom",{direction:"-"}),t}},s.prototype._onMouseWheel=function(t){var e=0;if(t.wheelDelta?e=t.wheelDelta/120:t.detail&&(e=-t.detail/3),e){var i=this._getScale(),s=e/10;0>e&&(s/=1-s),i*=1+s;var o=h.fakeGesture(this,t),n=this._getPointer(o.center);this._zoom(i,n)}t.preventDefault()},s.prototype._onMouseMoveTitle=function(t){var e=h.fakeGesture(this,t),i=this._getPointer(e.center);this.popupObj&&this._checkHidePopup(i);var s=this,o=function(){s._checkShowPopup(i)};if(this.popupTimer&&clearInterval(this.popupTimer),this.drag.dragging||(this.popupTimer=setTimeout(o,this.constants.tooltip.delay)),1==this.constants.hover){for(var n in this.hoverObj.edges)this.hoverObj.edges.hasOwnProperty(n)&&(this.hoverObj.edges[n].hover=!1,delete this.hoverObj.edges[n]);var r=this._getNodeAt(i);null==r&&(r=this._getEdgeAt(i)),null!=r&&this._hoverObject(r);for(var a in this.hoverObj.nodes)this.hoverObj.nodes.hasOwnProperty(a)&&(r instanceof m&&r.id!=a||r instanceof g||null==r)&&(this._blurObject(this.hoverObj.nodes[a]),delete this.hoverObj.nodes[a]);this.redraw()}},s.prototype._checkShowPopup=function(t){var e,i={left:this._XconvertDOMtoCanvas(t.x),top:this._YconvertDOMtoCanvas(t.y),right:this._XconvertDOMtoCanvas(t.x),bottom:this._YconvertDOMtoCanvas(t.y)},s=this.popupObj;if(void 0==this.popupObj){var o=this.nodes;for(e in o)if(o.hasOwnProperty(e)){var n=o[e];if(void 0!==n.getTitle()&&n.isOverlappingWith(i)){this.popupObj=n;break}}}if(void 0===this.popupObj){var r=this.edges;for(e in r)if(r.hasOwnProperty(e)){var a=r[e];if(a.connected&&void 0!==a.getTitle()&&a.isOverlappingWith(i)){this.popupObj=a;break}}}if(this.popupObj){if(this.popupObj!=s){var h=this;h.popup||(h.popup=new v(h.frame,h.constants.tooltip)),h.popup.setPosition(t.x-3,t.y-3),h.popup.setText(h.popupObj.getTitle()),h.popup.show()}}else this.popup&&this.popup.hide()},s.prototype._checkHidePopup=function(t){this.popupObj&&this._getNodeAt(t)||(this.popupObj=void 0,this.popup&&this.popup.hide())},s.prototype.setSize=function(t,e){this.frame.style.width=t,this.frame.style.height=e,this.frame.canvas.style.width="100%",this.frame.canvas.style.height="100%",this.frame.canvas.width=this.frame.canvas.clientWidth,this.frame.canvas.height=this.frame.canvas.clientHeight,void 0!==this.manipulationDiv&&(this.manipulationDiv.style.width=this.frame.canvas.clientWidth+"px"),void 0!==this.navigationDivs&&void 0!==this.navigationDivs.wrapper&&(this.navigationDivs.wrapper.style.width=this.frame.canvas.clientWidth+"px",this.navigationDivs.wrapper.style.height=this.frame.canvas.clientHeight+"px"),this.emit("resize",{width:this.frame.canvas.width,height:this.frame.canvas.height})},s.prototype._setNodes=function(t){var e=this.nodesData;if(t instanceof d||t instanceof l)this.nodesData=t;else if(t instanceof Array)this.nodesData=new d,this.nodesData.add(t);else{if(t)throw new TypeError("Array or DataSet expected");this.nodesData=new d}if(e&&a.forEach(this.nodesListeners,function(t,i){e.off(i,t)}),this.nodes={},this.nodesData){var i=this;a.forEach(this.nodesListeners,function(t,e){i.nodesData.on(e,t)});var s=this.nodesData.getIds();this._addNodes(s)}this._updateSelection()},s.prototype._addNodes=function(t){for(var e,i=0,s=t.length;s>i;i++){e=t[i];var o=this.nodesData.get(e),n=new m(o,this.images,this.groups,this.constants);if(this.nodes[e]=n,!(0!=n.xFixed&&0!=n.yFixed||null!==n.x&&null!==n.y)){var r=1*t.length,a=2*Math.PI*Math.random();0==n.xFixed&&(n.x=r*Math.cos(a)),0==n.yFixed&&(n.y=r*Math.sin(a))}this.moving=!0}this._updateNodeIndexList(),1==this.constants.hierarchicalLayout.enabled&&0==this.initializing&&(this._resetLevels(),this._setupHierarchicalLayout()),this._updateCalculationNodes(),this._reconnectEdges(),this._updateValueRange(this.nodes),this.updateLabels()},s.prototype._updateNodes=function(t){for(var e=this.nodes,i=this.nodesData,s=0,o=t.length;o>s;s++){var n=t[s],r=e[n],a=i.get(n);r?r.setProperties(a,this.constants):(r=new m(properties,this.images,this.groups,this.constants),e[n]=r)}this.moving=!0,1==this.constants.hierarchicalLayout.enabled&&0==this.initializing&&(this._resetLevels(),this._setupHierarchicalLayout()),this._updateNodeIndexList(),this._reconnectEdges(),this._updateValueRange(e)},s.prototype._removeNodes=function(t){for(var e=this.nodes,i=0,s=t.length;s>i;i++){var o=t[i];delete e[o]}this._updateNodeIndexList(),1==this.constants.hierarchicalLayout.enabled&&0==this.initializing&&(this._resetLevels(),this._setupHierarchicalLayout()),this._updateCalculationNodes(),this._reconnectEdges(),this._updateSelection(),this._updateValueRange(e)},s.prototype._setEdges=function(t){var e=this.edgesData;if(t instanceof d||t instanceof l)this.edgesData=t;else if(t instanceof Array)this.edgesData=new d,this.edgesData.add(t);else{if(t)throw new TypeError("Array or DataSet expected");this.edgesData=new d}if(e&&a.forEach(this.edgesListeners,function(t,i){e.off(i,t)}),this.edges={},this.edgesData){var i=this;a.forEach(this.edgesListeners,function(t,e){i.edgesData.on(e,t)});var s=this.edgesData.getIds();this._addEdges(s)}this._reconnectEdges()},s.prototype._addEdges=function(t){for(var e=this.edges,i=this.edgesData,s=0,o=t.length;o>s;s++){var n=t[s],r=e[n];r&&r.disconnect();var a=i.get(n,{showInternalIds:!0});e[n]=new g(a,this,this.constants)}this.moving=!0,this._updateValueRange(e),this._createBezierNodes(),1==this.constants.hierarchicalLayout.enabled&&0==this.initializing&&(this._resetLevels(),this._setupHierarchicalLayout()),this._updateCalculationNodes()},s.prototype._updateEdges=function(t){for(var e=this.edges,i=this.edgesData,s=0,o=t.length;o>s;s++){var n=t[s],r=i.get(n),a=e[n];a?(a.disconnect(),a.setProperties(r,this.constants),a.connect()):(a=new g(r,this,this.constants),this.edges[n]=a)}this._createBezierNodes(),1==this.constants.hierarchicalLayout.enabled&&0==this.initializing&&(this._resetLevels(),this._setupHierarchicalLayout()),this.moving=!0,this._updateValueRange(e)},s.prototype._removeEdges=function(t){for(var e=this.edges,i=0,s=t.length;s>i;i++){var o=t[i],n=e[o];n&&(null!=n.via&&delete this.sectors.support.nodes[n.via.id],n.disconnect(),delete e[o])}this.moving=!0,this._updateValueRange(e),1==this.constants.hierarchicalLayout.enabled&&0==this.initializing&&(this._resetLevels(),this._setupHierarchicalLayout()),this._updateCalculationNodes()},s.prototype._reconnectEdges=function(){var t,e=this.nodes,i=this.edges;for(t in e)e.hasOwnProperty(t)&&(e[t].edges=[]);for(t in i)if(i.hasOwnProperty(t)){var s=i[t];s.from=null,s.to=null,s.connect()}},s.prototype._updateValueRange=function(t){var e,i=void 0,s=void 0;for(e in t)if(t.hasOwnProperty(e)){var o=t[e].getValue();void 0!==o&&(i=void 0===i?o:Math.min(o,i),s=void 0===s?o:Math.max(o,s))}if(void 0!==i&&void 0!==s)for(e in t)t.hasOwnProperty(e)&&t[e].setValueRange(i,s)},s.prototype.redraw=function(){this.setSize(this.constants.width,this.constants.height),this._redraw()},s.prototype._redraw=function(){var t=this.frame.canvas.getContext("2d"),e=this.frame.canvas.width,i=this.frame.canvas.height;t.clearRect(0,0,e,i),t.save(),t.translate(this.translation.x,this.translation.y),t.scale(this.scale,this.scale),this.canvasTopLeft={x:this._XconvertDOMtoCanvas(0),y:this._YconvertDOMtoCanvas(0)},this.canvasBottomRight={x:this._XconvertDOMtoCanvas(this.frame.canvas.clientWidth),y:this._YconvertDOMtoCanvas(this.frame.canvas.clientHeight)},this._doInAllSectors("_drawAllSectorNodes",t),(0==this.drag.dragging||void 0===this.drag.dragging||0==this.constants.hideEdgesOnDrag)&&this._doInAllSectors("_drawEdges",t),(0==this.drag.dragging||void 0===this.drag.dragging||0==this.constants.hideNodesOnDrag)&&this._doInAllSectors("_drawNodes",t,!1),1==this.controlNodesActive&&this._doInAllSectors("_drawControlNodes",t),t.restore()},s.prototype._setTranslation=function(t,e){void 0===this.translation&&(this.translation={x:0,y:0}),void 0!==t&&(this.translation.x=t),void 0!==e&&(this.translation.y=e),this.emit("viewChanged")},s.prototype._getTranslation=function(){return{x:this.translation.x,y:this.translation.y}},s.prototype._setScale=function(t){this.scale=t},s.prototype._getScale=function(){return this.scale},s.prototype._XconvertDOMtoCanvas=function(t){return(t-this.translation.x)/this.scale},s.prototype._XconvertCanvasToDOM=function(t){return t*this.scale+this.translation.x},s.prototype._YconvertDOMtoCanvas=function(t){return(t-this.translation.y)/this.scale},s.prototype._YconvertCanvasToDOM=function(t){return t*this.scale+this.translation.y},s.prototype.canvasToDOM=function(t){return{x:this._XconvertCanvasToDOM(t.x),y:this._YconvertCanvasToDOM(t.y)}},s.prototype.DOMtoCanvas=function(t){return{x:this._XconvertDOMtoCanvas(t.x),y:this._YconvertDOMtoCanvas(t.y)}},s.prototype._drawNodes=function(t,e){void 0===e&&(e=!1);var i=this.nodes,s=[];for(var o in i)i.hasOwnProperty(o)&&(i[o].setScaleAndPos(this.scale,this.canvasTopLeft,this.canvasBottomRight),i[o].isSelected()?s.push(o):(i[o].inArea()||e)&&i[o].draw(t));for(var n=0,r=s.length;r>n;n++)(i[s[n]].inArea()||e)&&i[s[n]].draw(t)},s.prototype._drawEdges=function(t){var e=this.edges;for(var i in e)if(e.hasOwnProperty(i)){var s=e[i];s.setScale(this.scale),s.connected&&e[i].draw(t)}},s.prototype._drawControlNodes=function(t){var e=this.edges;for(var i in e)e.hasOwnProperty(i)&&e[i]._drawControlNodes(t)},s.prototype._stabilize=function(){1==this.constants.freezeForStabilization&&this._freezeDefinedNodes();for(var t=0;this.moving&&t0)for(t in i)i.hasOwnProperty(t)&&(i[t].discreteStepLimited(e,this.constants.maxVelocity),s=!0);else for(t in i)i.hasOwnProperty(t)&&(i[t].discreteStep(e),s=!0);if(1==s){var o=this.constants.minVelocity/Math.max(this.scale,.05);o>.5*this.constants.maxVelocity?this.moving=!0:(this.moving=this._isMoving(o),0==this.moving&&this.emit("stabilized",{iterations:null}),this.moving=this.moving||this.configurePhysics)}},s.prototype._physicsTick=function(){this.freezeSimulation||1==this.moving&&(this._doInAllActiveSectors("_initializeForceCalculation"),this._doInAllActiveSectors("_discreteStepNodes"),1==this.constants.smoothCurves.enabled&&1==this.constants.smoothCurves.dynamic&&this._doInSupportSector("_discreteStepNodes"),this._findCenter(this._getRange()))},s.prototype._animationStep=function(){this.timer=void 0,this._handleNavigation(),this.start();var t=Date.now(),e=1;this._physicsTick();for(var i=Date.now()-t;i<.9*(this.renderTimestep-this.renderTime)&&eh}return!1},s.prototype._getColor=function(){var t=this.options.color;return"to"==this.options.inheritColor?t={highlight:this.to.options.color.highlight.border,hover:this.to.options.color.hover.border,color:this.to.options.color.border}:("from"==this.options.inheritColor||1==this.options.inheritColor)&&(t={highlight:this.from.options.color.highlight.border,hover:this.from.options.color.hover.border,color:this.from.options.color.border}),1==this.selected?t.highlight:1==this.hover?t.hover:t.color},s.prototype._drawLine=function(t){if(t.strokeStyle=this._getColor(),t.lineWidth=this._getLineWidth(),this.from!=this.to){var e,i=this._line(t);if(this.label){if(1==this.options.smoothCurves.enabled&&null!=i){var s=.5*(.5*(this.from.x+i.x)+.5*(this.to.x+i.x)),o=.5*(.5*(this.from.y+i.y)+.5*(this.to.y+i.y));e={x:s,y:o}}else e=this._pointOnLine(.5);this._label(t,this.label,e.x,e.y)}}else{var n,r,a=this.physics.springLength/4,h=this.from;h.width||h.resize(t),h.width>h.height?(n=h.x+h.width/2,r=h.y-a):(n=h.x+a,r=h.y-h.height/2),this._circle(t,n,r,a),e=this._pointOnCircle(n,r,a,.5),this._label(t,this.label,e.x,e.y)}},s.prototype._getLineWidth=function(){return 1==this.selected?Math.min(this.widthSelected,this.options.widthMax)*this.networkScaleInv:1==this.hover?Math.min(this.options.hoverWidth,this.options.widthMax)*this.networkScaleInv:this.options.width*this.networkScaleInv},s.prototype._getViaCoordinates=function(){var t=null,e=null,i=this.options.smoothCurves.roundness,s=this.options.smoothCurves.type,o=Math.abs(this.from.x-this.to.x),n=Math.abs(this.from.y-this.to.y);return"discrete"==s||"diagonalCross"==s?Math.abs(this.from.x-this.to.x)this.to.y?this.from.xthis.to.x&&(t=this.from.x-i*n,e=this.from.y-i*n):this.from.ythis.to.x&&(t=this.from.x-i*n,e=this.from.y+i*n)),"discrete"==s&&(t=i*n>o?this.from.x:t)):Math.abs(this.from.x-this.to.x)>Math.abs(this.from.y-this.to.y)&&(this.from.y>this.to.y?this.from.xthis.to.x&&(t=this.from.x-i*o,e=this.from.y-i*o):this.from.ythis.to.x&&(t=this.from.x-i*o,e=this.from.y+i*o)),"discrete"==s&&(e=i*o>n?this.from.y:e)):"straightCross"==s?Math.abs(this.from.x-this.to.x)Math.abs(this.from.y-this.to.y)&&(t=this.from.xthis.to.y?this.from.xthis.to.x&&(t=this.from.x-i*n,e=this.from.y-i*n,t=this.to.x>t?this.to.x:t):this.from.ythis.to.x&&(t=this.from.x-i*n,e=this.from.y+i*n,t=this.to.x>t?this.to.x:t)):Math.abs(this.from.x-this.to.x)>Math.abs(this.from.y-this.to.y)&&(this.from.y>this.to.y?this.from.xe?this.to.y:e):this.from.x>this.to.x&&(t=this.from.x-i*o,e=this.from.y-i*o,e=this.to.y>e?this.to.y:e):this.from.ythis.to.x&&(t=this.from.x-i*o,e=this.from.y+i*o,e=this.to.yl.height?(a=l.x+.5*l.width,h=l.y-d):(a=l.x+d,h=l.y-.5*l.height),this._circle(t,a,h,d);var s=.2*Math.PI,o=(10+5*this.options.width)*this.options.arrowScaleFactor;e=this._pointOnCircle(a,h,d,.5),t.arrow(e.x,e.y,s,o),t.fill(),t.stroke(),this.label&&(e=this._pointOnCircle(a,h,d,.5),this._label(t,this.label,e.x,e.y))}},s.prototype._drawArrow=function(t){1==this.selected?(t.strokeStyle=this.options.color.highlight,t.fillStyle=this.options.color.highlight):1==this.hover?(t.strokeStyle=this.options.color.hover,t.fillStyle=this.options.color.hover):(t.strokeStyle=this.options.color.color,t.fillStyle=this.options.color.color),t.lineWidth=this._getLineWidth();var e,i;if(this.from!=this.to){e=Math.atan2(this.to.y-this.from.y,this.to.x-this.from.x);var s,o=this.to.x-this.from.x,n=this.to.y-this.from.y,r=Math.sqrt(o*o+n*n),a=this.from.distanceToBorder(t,e+Math.PI),h=(r-a)/r,d=h*this.from.x+(1-h)*this.to.x,l=h*this.from.y+(1-h)*this.to.y;1==this.options.smoothCurves.dynamic&&1==this.options.smoothCurves.enabled?s=this.via:1==this.options.smoothCurves.enabled&&(s=this._getViaCoordinates()),1==this.options.smoothCurves.enabled&&null!=s.x&&(e=Math.atan2(this.to.y-s.y,this.to.x-s.x),o=this.to.x-s.x,n=this.to.y-s.y,r=Math.sqrt(o*o+n*n));var c,p,u=this.to.distanceToBorder(t,e),f=(r-u)/r;if(1==this.options.smoothCurves.enabled&&null!=s.x?(c=(1-f)*s.x+f*this.to.x,p=(1-f)*s.y+f*this.to.y):(c=(1-f)*this.from.x+f*this.to.x,p=(1-f)*this.from.y+f*this.to.y),t.beginPath(),t.moveTo(d,l),1==this.options.smoothCurves.enabled&&null!=s.x?t.quadraticCurveTo(s.x,s.y,c,p):t.lineTo(c,p),t.stroke(),i=(10+5*this.options.width)*this.options.arrowScaleFactor,t.arrow(c,p,e,i),t.fill(),t.stroke(),this.label){var m;if(1==this.options.smoothCurves.enabled&&null!=s){var g=.5*(.5*(this.from.x+s.x)+.5*(this.to.x+s.x)),v=.5*(.5*(this.from.y+s.y)+.5*(this.to.y+s.y));m={x:g,y:v}}else m=this._pointOnLine(.5);this._label(t,this.label,m.x,m.y)}}else{var y,b,_,x=this.from,w=.25*Math.max(100,this.physics.springLength);x.width||x.resize(t),x.width>x.height?(y=x.x+.5*x.width,b=x.y-w,_={x:y,y:x.y,angle:.9*Math.PI}):(y=x.x+w,b=x.y-.5*x.height,_={x:x.x,y:b,angle:.6*Math.PI}),t.beginPath(),t.arc(y,b,w,0,2*Math.PI,!1),t.stroke();var i=(10+5*this.options.width)*this.options.arrowScaleFactor;t.arrow(_.x,_.y,_.angle,i),t.fill(),t.stroke(),this.label&&(m=this._pointOnCircle(y,b,w,.5),this._label(t,this.label,m.x,m.y))}},s.prototype._getDistanceToEdge=function(t,e,i,s,o,n){if(this.from!=this.to){if(1==this.options.smoothCurves.enabled){var r,a;if(1==this.options.smoothCurves.enabled&&1==this.options.smoothCurves.dynamic)r=this.via.x,a=this.via.y;else{var h=this._getViaCoordinates();r=h.x,a=h.y}var d,l,c,p,u,f,m,g=1e9;for(l=0;10>l;l++)c=.1*l,p=Math.pow(1-c,2)*t+2*c*(1-c)*r+Math.pow(c,2)*i,u=Math.pow(1-c,2)*e+2*c*(1-c)*a+Math.pow(c,2)*s,l>0&&(d=this._getDistanceToLine(f,m,p,u,o,n),g=g>d?d:g),f=p,m=u;return g}return this._getDistanceToLine(t,e,i,s,o,n)}var p,u,v,y,b=this.physics.springLength/4,_=this.from;return _.width||_.resize(ctx),_.width>_.height?(p=_.x+_.width/2,u=_.y-b):(p=_.x+b,u=_.y-_.height/2),v=p-o,y=u-n,Math.abs(Math.sqrt(v*v+y*y)-b)},s.prototype._getDistanceToLine=function(t,e,i,s,o,n){var r=i-t,a=s-e,h=r*r+a*a,d=((o-t)*r+(n-e)*a)/h;d>1?d=1:0>d&&(d=0);var l=t+d*r,c=e+d*a,p=l-o,u=c-n;return Math.sqrt(p*p+u*u)},s.prototype.setScale=function(t){this.networkScaleInv=1/t},s.prototype.select=function(){this.selected=!0},s.prototype.unselect=function(){this.selected=!1},s.prototype.positionBezierNode=function(){null!==this.via&&null!==this.from&&null!==this.to&&(this.via.x=.5*(this.from.x+this.to.x),this.via.y=.5*(this.from.y+this.to.y))},s.prototype._drawControlNodes=function(t){if(1==this.controlNodesEnabled){if(null===this.controlNodes.from&&null===this.controlNodes.to){var e="edgeIdFrom:".concat(this.id),i="edgeIdTo:".concat(this.id),s={nodes:{group:"",radius:8},physics:{damping:0},clustering:{maxNodeSizeIncrements:0,nodeScaling:{width:0,height:0,radius:0}}};this.controlNodes.from=new n({id:e,shape:"dot",color:{background:"#ff4e00",border:"#3c3c3c",highlight:{background:"#07f968"}}},{},{},s),this.controlNodes.to=new n({id:i,shape:"dot",color:{background:"#ff4e00",border:"#3c3c3c",highlight:{background:"#07f968"}}},{},{},s)}0==this.controlNodes.from.selected&&0==this.controlNodes.to.selected&&(this.controlNodes.positions=this.getControlNodePositions(t),this.controlNodes.from.x=this.controlNodes.positions.from.x,this.controlNodes.from.y=this.controlNodes.positions.from.y,this.controlNodes.to.x=this.controlNodes.positions.to.x,this.controlNodes.to.y=this.controlNodes.positions.to.y),this.controlNodes.from.draw(t),this.controlNodes.to.draw(t)}else this.controlNodes={from:null,to:null,positions:{}}},s.prototype._enableControlNodes=function(){this.controlNodesEnabled=!0},s.prototype._disableControlNodes=function(){this.controlNodesEnabled=!1},s.prototype._getSelectedControlNode=function(t,e){var i=this.controlNodes.positions,s=Math.sqrt(Math.pow(t-i.from.x,2)+Math.pow(e-i.from.y,2)),o=Math.sqrt(Math.pow(t-i.to.x,2)+Math.pow(e-i.to.y,2));return 15>s?(this.connectedNode=this.from,this.from=this.controlNodes.from,this.controlNodes.from):15>o?(this.connectedNode=this.to,this.to=this.controlNodes.to,this.controlNodes.to):null},s.prototype._restoreControlNodes=function(){1==this.controlNodes.from.selected&&(this.from=this.connectedNode,this.connectedNode=null,this.controlNodes.from.unselect()),1==this.controlNodes.to.selected&&(this.to=this.connectedNode,this.connectedNode=null,this.controlNodes.to.unselect())},s.prototype.getControlNodePositions=function(t){var e,i=Math.atan2(this.to.y-this.from.y,this.to.x-this.from.x),s=this.to.x-this.from.x,o=this.to.y-this.from.y,n=Math.sqrt(s*s+o*o),r=this.from.distanceToBorder(t,i+Math.PI),a=(n-r)/n,h=a*this.from.x+(1-a)*this.to.x,d=a*this.from.y+(1-a)*this.to.y;1==this.options.smoothCurves.dynamic&&1==this.options.smoothCurves.enabled?e=this.via:1==this.options.smoothCurves.enabled&&(e=this._getViaCoordinates()),1==this.options.smoothCurves.enabled&&null!=e.x&&(i=Math.atan2(this.to.y-e.y,this.to.x-e.x),s=this.to.x-e.x,o=this.to.y-e.y,n=Math.sqrt(s*s+o*o));var l,c,p=this.to.distanceToBorder(t,i),u=(n-p)/n;return 1==this.options.smoothCurves.enabled&&null!=e.x?(l=(1-u)*e.x+u*this.to.x,c=(1-u)*e.y+u*this.to.y):(l=(1-u)*this.from.x+u*this.to.x,c=(1-u)*this.from.y+u*this.to.y),{from:{x:h,y:d},to:{x:l,y:c}}},t.exports=s},function(t,e,i){function s(){this.clear(),this.defaultIndex=0}var o=i(2);s.DEFAULT=[{border:"#2B7CE9",background:"#97C2FC",highlight:{border:"#2B7CE9",background:"#D2E5FF"},hover:{border:"#2B7CE9",background:"#D2E5FF"}},{border:"#FFA500",background:"#FFFF00",highlight:{border:"#FFA500",background:"#FFFFA3"},hover:{border:"#FFA500",background:"#FFFFA3"}},{border:"#FA0A10",background:"#FB7E81",highlight:{border:"#FA0A10",background:"#FFAFB1"},hover:{border:"#FA0A10",background:"#FFAFB1"}},{border:"#41A906",background:"#7BE141",highlight:{border:"#41A906",background:"#A1EC76"},hover:{border:"#41A906",background:"#A1EC76"}},{border:"#E129F0",background:"#EB7DF4",highlight:{border:"#E129F0",background:"#F0B3F5"},hover:{border:"#E129F0",background:"#F0B3F5"}},{border:"#7C29F0",background:"#AD85E4",highlight:{border:"#7C29F0",background:"#D3BDF0"},hover:{border:"#7C29F0",background:"#D3BDF0"}},{border:"#C37F00",background:"#FFA807",highlight:{border:"#C37F00",background:"#FFCA66"},hover:{border:"#C37F00",background:"#FFCA66"}},{border:"#4220FB",background:"#6E6EFD",highlight:{border:"#4220FB",background:"#9B9BFD"},hover:{border:"#4220FB",background:"#9B9BFD"}},{border:"#FD5A77",background:"#FFC0CB",highlight:{border:"#FD5A77",background:"#FFD1D9"},hover:{border:"#FD5A77",background:"#FFD1D9"}},{border:"#4AD63A",background:"#C2FABC",highlight:{border:"#4AD63A",background:"#E6FFE3"},hover:{border:"#4AD63A",background:"#E6FFE3"}}],s.prototype.clear=function(){this.groups={},this.groups.length=function(){var t=0;for(var e in this)this.hasOwnProperty(e)&&t++;return t}},s.prototype.get=function(t){var e=this.groups[t];if(void 0==e){var i=this.defaultIndex%s.DEFAULT.length;this.defaultIndex++,e={},e.color=s.DEFAULT[i],this.groups[t]=e}return e},s.prototype.add=function(t,e){return this.groups[t]=e,e.color&&(e.color=o.parseColor(e.color)),e},t.exports=s},function(t){function e(){this.images={},this.callback=void 0}e.prototype.setOnloadCallback=function(t){this.callback=t},e.prototype.load=function(t){var e=this.images[t];if(void 0==e){var i=this;e=new Image,this.images[t]=e,e.onload=function(){i.callback&&i.callback(this)},e.src=t}return e},t.exports=e},function(t,e,i){function s(t,e,i,s){var n=o.selectiveBridgeObject(["nodes"],s);this.options=n.nodes,this.selected=!1,this.hover=!1,this.edges=[],this.dynamicEdges=[],this.reroutedEdges={},this.fontDrawThreshold=3,this.id=void 0,this.x=null,this.y=null,this.xFixed=!1,this.yFixed=!1,this.horizontalAlignLeft=!0,this.verticalAlignTop=!0,this.baseRadiusValue=s.nodes.radius,this.radiusFixed=!1,this.level=-1,this.preassignedLevel=!1,this.imagelist=e,this.grouplist=i,this.fx=0,this.fy=0,this.vx=0,this.vy=0,this.damping=s.physics.damping,this.fixedData={x:null,y:null},this.setProperties(t,n),this.resetCluster(),this.dynamicEdgesLength=0,this.clusterSession=0,this.clusterSizeWidthFactor=s.clustering.nodeScaling.width,this.clusterSizeHeightFactor=s.clustering.nodeScaling.height,this.clusterSizeRadiusFactor=s.clustering.nodeScaling.radius,this.maxNodeSizeIncrements=s.clustering.maxNodeSizeIncrements,this.growthIndicator=0,this.networkScaleInv=1,this.networkScale=1,this.canvasTopLeft={x:-300,y:-300},this.canvasBottomRight={x:300,y:300},this.parentEdgeId=null}var o=i(2);s.prototype.resetCluster=function(){this.formationScale=void 0,this.clusterSize=1,this.containedNodes={},this.containedEdges={},this.clusterSessions=[]},s.prototype.attachEdge=function(t){-1==this.edges.indexOf(t)&&this.edges.push(t),-1==this.dynamicEdges.indexOf(t)&&this.dynamicEdges.push(t),this.dynamicEdgesLength=this.dynamicEdges.length},s.prototype.detachEdge=function(t){var e=this.edges.indexOf(t);-1!=e&&(this.edges.splice(e,1),this.dynamicEdges.splice(e,1)),this.dynamicEdgesLength=this.dynamicEdges.length},s.prototype.setProperties=function(t,e){if(t){var i=["borderWidth","borderWidthSelected","shape","image","radius","fontColor","fontSize","fontFace","group","mass"];if(o.selectiveDeepExtend(i,this.options,t),this.originalLabel=void 0,void 0!==t.id&&(this.id=t.id),void 0!==t.label&&(this.label=t.label,this.originalLabel=t.label),void 0!==t.title&&(this.title=t.title),void 0!==t.x&&(this.x=t.x),void 0!==t.y&&(this.y=t.y),void 0!==t.value&&(this.value=t.value),void 0!==t.level&&(this.level=t.level,this.preassignedLevel=!0),void 0!==t.horizontalAlignLeft&&(this.horizontalAlignLeft=t.horizontalAlignLeft),void 0!==t.verticalAlignTop&&(this.verticalAlignTop=t.verticalAlignTop),void 0!==t.triggerFunction&&(this.triggerFunction=t.triggerFunction),void 0===this.id)throw"Node must have an id";if("number"==typeof this.options.group||"string"==typeof this.options.group&&""!=this.options.group){var s=this.grouplist.get(this.options.group);for(var n in s)s.hasOwnProperty(n)&&(this.options[n]=s[n])}if(void 0!==t.radius&&(this.baseRadiusValue=this.options.radius),void 0!==t.color&&(this.options.color=o.parseColor(t.color)),void 0!==this.options.image&&""!=this.options.image){if(!this.imagelist)throw"No imagelist provided";this.imageObj=this.imagelist.load(this.options.image)}switch(this.xFixed=this.xFixed||void 0!==t.x&&!t.allowedToMoveX,this.yFixed=this.yFixed||void 0!==t.y&&!t.allowedToMoveY,this.radiusFixed=this.radiusFixed||void 0!==t.radius,"image"==this.options.shape&&(this.options.radiusMin=e.nodes.widthMin,this.options.radiusMax=e.nodes.widthMax),this.options.shape){case"database":this.draw=this._drawDatabase,this.resize=this._resizeDatabase;break;case"box":this.draw=this._drawBox,this.resize=this._resizeBox;break;case"circle":this.draw=this._drawCircle,this.resize=this._resizeCircle;break;case"ellipse":this.draw=this._drawEllipse,this.resize=this._resizeEllipse;break;case"image":this.draw=this._drawImage,this.resize=this._resizeImage;break;case"text":this.draw=this._drawText,this.resize=this._resizeText;break;case"dot":this.draw=this._drawDot,this.resize=this._resizeShape;break;case"square":this.draw=this._drawSquare,this.resize=this._resizeShape;break;case"triangle":this.draw=this._drawTriangle,this.resize=this._resizeShape;break;case"triangleDown":this.draw=this._drawTriangleDown,this.resize=this._resizeShape;break;case"star":this.draw=this._drawStar,this.resize=this._resizeShape;break;default:this.draw=this._drawEllipse,this.resize=this._resizeEllipse}this._reset()}},s.prototype.select=function(){this.selected=!0,this._reset()},s.prototype.unselect=function(){this.selected=!1,this._reset()},s.prototype.clearSizeCache=function(){this._reset()},s.prototype._reset=function(){this.width=void 0,this.height=void 0},s.prototype.getTitle=function(){return"function"==typeof this.title?this.title():this.title},s.prototype.distanceToBorder=function(t,e){var i=1;switch(this.width||this.resize(t),this.options.shape){case"circle":case"dot":return this.options.radius+i;case"ellipse":var s=this.width/2,o=this.height/2,n=Math.sin(e)*s,r=Math.cos(e)*o;return s*o/Math.sqrt(n*n+r*r);case"box":case"image":case"text":default:return this.width?Math.min(Math.abs(this.width/2/Math.cos(e)),Math.abs(this.height/2/Math.sin(e)))+i:0}},s.prototype._setForce=function(t,e){this.fx=t,this.fy=e},s.prototype._addForce=function(t,e){this.fx+=t,this.fy+=e},s.prototype.discreteStep=function(t){if(!this.xFixed){var e=this.damping*this.vx,i=(this.fx-e)/this.options.mass;this.vx+=i*t,this.x+=this.vx*t}if(!this.yFixed){var s=this.damping*this.vy,o=(this.fy-s)/this.options.mass;this.vy+=o*t,this.y+=this.vy*t}},s.prototype.discreteStepLimited=function(t,e){if(this.xFixed)this.fx=0;else{var i=this.damping*this.vx,s=(this.fx-i)/this.options.mass;this.vx+=s*t,this.vx=Math.abs(this.vx)>e?this.vx>0?e:-e:this.vx,this.x+=this.vx*t}if(this.yFixed)this.fy=0;else{var o=this.damping*this.vy,n=(this.fy-o)/this.options.mass;this.vy+=n*t,this.vy=Math.abs(this.vy)>e?this.vy>0?e:-e:this.vy,this.y+=this.vy*t}},s.prototype.isFixed=function(){return this.xFixed&&this.yFixed},s.prototype.isMoving=function(t){return Math.abs(this.vx)>t||Math.abs(this.vy)>t},s.prototype.isSelected=function(){return this.selected},s.prototype.getValue=function(){return this.value},s.prototype.getDistance=function(t,e){var i=this.x-t,s=this.y-e;return Math.sqrt(i*i+s*s)},s.prototype.setValueRange=function(t,e){if(!this.radiusFixed&&void 0!==this.value)if(e==t)this.options.radius=(this.options.radiusMin+this.options.radiusMax)/2;else{var i=(this.options.radiusMax-this.options.radiusMin)/(e-t);this.options.radius=(this.value-t)*i+this.options.radiusMin}this.baseRadiusValue=this.options.radius},s.prototype.draw=function(){throw"Draw method not initialized for node"},s.prototype.resize=function(){throw"Resize method not initialized for node"},s.prototype.isOverlappingWith=function(t){return this.leftt.left&&this.topt.top},s.prototype._resizeImage=function(){if(!this.width||!this.height){var t,e;if(this.value){this.options.radius=this.baseRadiusValue;var i=this.imageObj.height/this.imageObj.width;void 0!==i?(t=this.options.radius||this.imageObj.width,e=this.options.radius*i||this.imageObj.height):(t=0,e=0)}else t=this.imageObj.width,e=this.imageObj.height;this.width=t,this.height=e,this.growthIndicator=0,this.width>0&&this.height>0&&(this.width+=Math.min(this.clusterSize-1,this.maxNodeSizeIncrements)*this.clusterSizeWidthFactor,this.height+=Math.min(this.clusterSize-1,this.maxNodeSizeIncrements)*this.clusterSizeHeightFactor,this.options.radius+=Math.min(this.clusterSize-1,this.maxNodeSizeIncrements)*this.clusterSizeRadiusFactor,this.growthIndicator=this.width-t)}},s.prototype._drawImage=function(t){this._resizeImage(t),this.left=this.x-this.width/2,this.top=this.y-this.height/2;var e;if(0!=this.imageObj.width){if(this.clusterSize>1){var i=this.clusterSize>1?10:0;i*=this.networkScaleInv,i=Math.min(.2*this.width,i),t.globalAlpha=.5,t.drawImage(this.imageObj,this.left-i,this.top-i,this.width+2*i,this.height+2*i)}t.globalAlpha=1,t.drawImage(this.imageObj,this.left,this.top,this.width,this.height),e=this.y+this.height/2}else e=this.y;this._label(t,this.label,this.x,e,void 0,"top")},s.prototype._resizeBox=function(t){if(!this.width){var e=5,i=this.getTextSize(t);this.width=i.width+2*e,this.height=i.height+2*e,this.width+=.5*Math.min(this.clusterSize-1,this.maxNodeSizeIncrements)*this.clusterSizeWidthFactor,this.height+=.5*Math.min(this.clusterSize-1,this.maxNodeSizeIncrements)*this.clusterSizeHeightFactor,this.growthIndicator=this.width-(i.width+2*e)}},s.prototype._drawBox=function(t){this._resizeBox(t),this.left=this.x-this.width/2,this.top=this.y-this.height/2;var e=2.5,i=this.options.borderWidth,s=this.options.borderWidthSelected||2*this.options.borderWidth;t.strokeStyle=this.selected?this.options.color.highlight.border:this.hover?this.options.color.hover.border:this.options.color.border,this.clusterSize>1&&(t.lineWidth=(this.selected?s:i)+(this.clusterSize>1?e:0),t.lineWidth*=this.networkScaleInv,t.lineWidth=Math.min(this.width,t.lineWidth),t.roundRect(this.left-2*t.lineWidth,this.top-2*t.lineWidth,this.width+4*t.lineWidth,this.height+4*t.lineWidth,this.options.radius),t.stroke()),t.lineWidth=(this.selected?s:i)+(this.clusterSize>1?e:0),t.lineWidth*=this.networkScaleInv,t.lineWidth=Math.min(this.width,t.lineWidth),t.fillStyle=this.selected?this.options.color.highlight.background:this.options.color.background,t.roundRect(this.left,this.top,this.width,this.height,this.options.radius),t.fill(),t.stroke(),this._label(t,this.label,this.x,this.y)},s.prototype._resizeDatabase=function(t){if(!this.width){var e=5,i=this.getTextSize(t),s=i.width+2*e;this.width=s,this.height=s,this.width+=Math.min(this.clusterSize-1,this.maxNodeSizeIncrements)*this.clusterSizeWidthFactor,this.height+=Math.min(this.clusterSize-1,this.maxNodeSizeIncrements)*this.clusterSizeHeightFactor,this.options.radius+=Math.min(this.clusterSize-1,this.maxNodeSizeIncrements)*this.clusterSizeRadiusFactor,this.growthIndicator=this.width-s}},s.prototype._drawDatabase=function(t){this._resizeDatabase(t),this.left=this.x-this.width/2,this.top=this.y-this.height/2;var e=2.5,i=this.options.borderWidth,s=this.options.borderWidthSelected||2*this.options.borderWidth;t.strokeStyle=this.selected?this.options.color.highlight.border:this.hover?this.options.color.hover.border:this.options.color.border,this.clusterSize>1&&(t.lineWidth=(this.selected?s:i)+(this.clusterSize>1?e:0),t.lineWidth*=this.networkScaleInv,t.lineWidth=Math.min(this.width,t.lineWidth),t.database(this.x-this.width/2-2*t.lineWidth,this.y-.5*this.height-2*t.lineWidth,this.width+4*t.lineWidth,this.height+4*t.lineWidth),t.stroke()),t.lineWidth=(this.selected?s:i)+(this.clusterSize>1?e:0),t.lineWidth*=this.networkScaleInv,t.lineWidth=Math.min(this.width,t.lineWidth),t.fillStyle=this.selected?this.options.color.highlight.background:this.hover?this.options.color.hover.background:this.options.color.background,t.database(this.x-this.width/2,this.y-.5*this.height,this.width,this.height),t.fill(),t.stroke(),this._label(t,this.label,this.x,this.y)},s.prototype._resizeCircle=function(t){if(!this.width){var e=5,i=this.getTextSize(t),s=Math.max(i.width,i.height)+2*e;this.options.radius=s/2,this.width=s,this.height=s,this.options.radius+=.5*Math.min(this.clusterSize-1,this.maxNodeSizeIncrements)*this.clusterSizeRadiusFactor,this.growthIndicator=this.options.radius-.5*s}},s.prototype._drawCircle=function(t){this._resizeCircle(t),this.left=this.x-this.width/2,this.top=this.y-this.height/2;var e=2.5,i=this.options.borderWidth,s=this.options.borderWidthSelected||2*this.options.borderWidth;t.strokeStyle=this.selected?this.options.color.highlight.border:this.hover?this.options.color.hover.border:this.options.color.border,this.clusterSize>1&&(t.lineWidth=(this.selected?s:i)+(this.clusterSize>1?e:0),t.lineWidth*=this.networkScaleInv,t.lineWidth=Math.min(this.width,t.lineWidth),t.circle(this.x,this.y,this.options.radius+2*t.lineWidth),t.stroke()),t.lineWidth=(this.selected?s:i)+(this.clusterSize>1?e:0),t.lineWidth*=this.networkScaleInv,t.lineWidth=Math.min(this.width,t.lineWidth),t.fillStyle=this.selected?this.options.color.highlight.background:this.hover?this.options.color.hover.background:this.options.color.background,t.circle(this.x,this.y,this.options.radius),t.fill(),t.stroke(),this._label(t,this.label,this.x,this.y)},s.prototype._resizeEllipse=function(t){if(!this.width){var e=this.getTextSize(t);this.width=1.5*e.width,this.height=2*e.height,this.width1&&(t.lineWidth=(this.selected?s:i)+(this.clusterSize>1?e:0),t.lineWidth*=this.networkScaleInv,t.lineWidth=Math.min(this.width,t.lineWidth),t.ellipse(this.left-2*t.lineWidth,this.top-2*t.lineWidth,this.width+4*t.lineWidth,this.height+4*t.lineWidth),t.stroke()),t.lineWidth=(this.selected?s:i)+(this.clusterSize>1?e:0),t.lineWidth*=this.networkScaleInv,t.lineWidth=Math.min(this.width,t.lineWidth),t.fillStyle=this.selected?this.options.color.highlight.background:this.hover?this.options.color.hover.background:this.options.color.background,t.ellipse(this.left,this.top,this.width,this.height),t.fill(),t.stroke(),this._label(t,this.label,this.x,this.y)},s.prototype._drawDot=function(t){this._drawShape(t,"circle")},s.prototype._drawTriangle=function(t){this._drawShape(t,"triangle")},s.prototype._drawTriangleDown=function(t){this._drawShape(t,"triangleDown")},s.prototype._drawSquare=function(t){this._drawShape(t,"square")},s.prototype._drawStar=function(t){this._drawShape(t,"star")},s.prototype._resizeShape=function(){if(!this.width){this.options.radius=this.baseRadiusValue;var t=2*this.options.radius;this.width=t,this.height=t,this.width+=Math.min(this.clusterSize-1,this.maxNodeSizeIncrements)*this.clusterSizeWidthFactor,this.height+=Math.min(this.clusterSize-1,this.maxNodeSizeIncrements)*this.clusterSizeHeightFactor,this.options.radius+=.5*Math.min(this.clusterSize-1,this.maxNodeSizeIncrements)*this.clusterSizeRadiusFactor,this.growthIndicator=this.width-t}},s.prototype._drawShape=function(t,e){this._resizeShape(t),this.left=this.x-this.width/2,this.top=this.y-this.height/2;var i=2.5,s=this.options.borderWidth,o=this.options.borderWidthSelected||2*this.options.borderWidth,n=2;switch(e){case"dot":n=2;break;case"square":n=2;break;case"triangle":n=3;break;case"triangleDown":n=3;break;case"star":n=4}t.strokeStyle=this.selected?this.options.color.highlight.border:this.hover?this.options.color.hover.border:this.options.color.border,this.clusterSize>1&&(t.lineWidth=(this.selected?o:s)+(this.clusterSize>1?i:0),t.lineWidth*=this.networkScaleInv,t.lineWidth=Math.min(this.width,t.lineWidth),t[e](this.x,this.y,this.options.radius+n*t.lineWidth),t.stroke()),t.lineWidth=(this.selected?o:s)+(this.clusterSize>1?i:0),t.lineWidth*=this.networkScaleInv,t.lineWidth=Math.min(this.width,t.lineWidth),t.fillStyle=this.selected?this.options.color.highlight.background:this.hover?this.options.color.hover.background:this.options.color.background,t[e](this.x,this.y,this.options.radius),t.fill(),t.stroke(),this.label&&this._label(t,this.label,this.x,this.y+this.height/2,void 0,"top",!0) -},s.prototype._resizeText=function(t){if(!this.width){var e=5,i=this.getTextSize(t);this.width=i.width+2*e,this.height=i.height+2*e,this.width+=Math.min(this.clusterSize-1,this.maxNodeSizeIncrements)*this.clusterSizeWidthFactor,this.height+=Math.min(this.clusterSize-1,this.maxNodeSizeIncrements)*this.clusterSizeHeightFactor,this.options.radius+=Math.min(this.clusterSize-1,this.maxNodeSizeIncrements)*this.clusterSizeRadiusFactor,this.growthIndicator=this.width-(i.width+2*e)}},s.prototype._drawText=function(t){this._resizeText(t),this.left=this.x-this.width/2,this.top=this.y-this.height/2,this._label(t,this.label,this.x,this.y)},s.prototype._label=function(t,e,i,s,o,n,r){if(e&&Number(this.options.fontSize)*this.networkScale>this.fontDrawThreshold){t.font=(this.selected?"bold ":"")+this.options.fontSize+"px "+this.options.fontFace,t.fillStyle=this.options.fontColor||"black",t.textAlign=o||"center",t.textBaseline=n||"middle";var a=e.split("\n"),h=a.length,d=Number(this.options.fontSize)+4,l=s+(1-h)/2*d;1==r&&(l=s+(1-h)/(2*d));for(var c=0;h>c;c++)t.fillText(a[c],i,l),l+=d}},s.prototype.getTextSize=function(t){if(void 0!==this.label){t.font=(this.selected?"bold ":"")+this.options.fontSize+"px "+this.options.fontFace;for(var e=this.label.split("\n"),i=(Number(this.options.fontSize)+4)*e.length,s=0,o=0,n=e.length;n>o;o++)s=Math.max(s,t.measureText(e[o]).width);return{width:s,height:i}}return{width:0,height:0}},s.prototype.inArea=function(){return void 0!==this.width?this.x+this.width*this.networkScaleInv>=this.canvasTopLeft.x&&this.x-this.width*this.networkScaleInv=this.canvasTopLeft.y&&this.y-this.height*this.networkScaleInv=this.canvasTopLeft.x&&this.x=this.canvasTopLeft.y&&this.ys&&(n=s-e-this.padding),no&&(r=o-i-this.padding),ri;i++)if(e.id===r.nodes[i].id){o=r.nodes[i];break}for(o||(o={id:e.id},t.node&&(o.attr=a(o.attr,t.node))),i=n.length-1;i>=0;i--){var h=n[i];h.nodes||(h.nodes=[]),-1==h.nodes.indexOf(o)&&h.nodes.push(o)}e.attr&&(o.attr=a(o.attr,e.attr))}function l(t,e){if(t.edges||(t.edges=[]),t.edges.push(e),t.edge){var i=a({},t.edge);e.attr=a(i,e.attr)}}function c(t,e,i,s,o){var n={from:e,to:i,type:s};return t.edge&&(n.attr=a({},t.edge)),n.attr=a(n.attr||{},o),n}function p(){for(k=C.NULL,L="";" "==O||" "==O||"\n"==O||"\r"==O;)o();do{var t=!1;if("#"==O){for(var e=T-1;" "==D.charAt(e)||" "==D.charAt(e);)e--;if("\n"==D.charAt(e)||""==D.charAt(e)){for(;""!=O&&"\n"!=O;)o();t=!0}}if("/"==O&&"/"==n()){for(;""!=O&&"\n"!=O;)o();t=!0}if("/"==O&&"*"==n()){for(;""!=O;){if("*"==O&&"/"==n()){o(),o();break}o()}t=!0}for(;" "==O||" "==O||"\n"==O||"\r"==O;)o()}while(t);if(""==O)return void(k=C.DELIMITER);var i=O+n();if(E[i])return k=C.DELIMITER,L=i,o(),void o();if(E[O])return k=C.DELIMITER,L=O,void o();if(r(O)||"-"==O){for(L+=O,o();r(O);)L+=O,o();return"false"==L?L=!1:"true"==L?L=!0:isNaN(Number(L))||(L=Number(L)),void(k=C.IDENTIFIER)}if('"'==O){for(o();""!=O&&('"'!=O||'"'==O&&'"'==n());)L+=O,'"'==O&&o(),o();if('"'!=O)throw x('End of string " expected');return o(),void(k=C.IDENTIFIER)}for(k=C.UNKNOWN;""!=O;)L+=O,o();throw new SyntaxError('Syntax error in part "'+w(L,30)+'"')}function u(){var t={};if(s(),p(),"strict"==L&&(t.strict=!0,p()),("graph"==L||"digraph"==L)&&(t.type=L,p()),k==C.IDENTIFIER&&(t.id=L,p()),"{"!=L)throw x("Angle bracket { expected");if(p(),f(t),"}"!=L)throw x("Angle bracket } expected");if(p(),""!==L)throw x("End of file expected");return p(),delete t.node,delete t.edge,delete t.graph,t}function f(t){for(;""!==L&&"}"!=L;)m(t),";"==L&&p()}function m(t){var e=g(t);if(e)return void b(t,e);var i=v(t);if(!i){if(k!=C.IDENTIFIER)throw x("Identifier expected");var s=L;if(p(),"="==L){if(p(),k!=C.IDENTIFIER)throw x("Identifier expected");t[s]=L,p()}else y(t,s)}}function g(t){var e=null;if("subgraph"==L&&(e={},e.type="subgraph",p(),k==C.IDENTIFIER&&(e.id=L,p())),"{"==L){if(p(),e||(e={}),e.parent=t,e.node=t.node,e.edge=t.edge,e.graph=t.graph,f(e),"}"!=L)throw x("Angle bracket } expected");p(),delete e.node,delete e.edge,delete e.graph,delete e.parent,t.subgraphs||(t.subgraphs=[]),t.subgraphs.push(e)}return e}function v(t){return"node"==L?(p(),t.node=_(),"node"):"edge"==L?(p(),t.edge=_(),"edge"):"graph"==L?(p(),t.graph=_(),"graph"):null}function y(t,e){var i={id:e},s=_();s&&(i.attr=s),d(t,i),b(t,e)}function b(t,e){for(;"->"==L||"--"==L;){var i,s=L;p();var o=g(t);if(o)i=o;else{if(k!=C.IDENTIFIER)throw x("Identifier or subgraph expected");i=L,d(t,{id:i}),p()}var n=_(),r=c(t,e,i,s,n);l(t,r),e=i}}function _(){for(var t=null;"["==L;){for(p(),t={};""!==L&&"]"!=L;){if(k!=C.IDENTIFIER)throw x("Attribute name expected");var e=L;if(p(),"="!=L)throw x("Equal sign = expected");if(p(),k!=C.IDENTIFIER)throw x("Attribute value expected");var i=L;h(t,e,i),p(),","==L&&p()}if("]"!=L)throw x("Bracket ] expected");p()}return t}function x(t){return new SyntaxError(t+', got "'+w(L,30)+'" (char '+T+")")}function w(t,e){return t.length<=e?t:t.substr(0,27)+"..."}function S(t,e,i){t instanceof Array?t.forEach(function(t){e instanceof Array?e.forEach(function(e){i(t,e)}):i(t,e)}):e instanceof Array?e.forEach(function(e){i(t,e)}):i(t,e)}function M(t){function e(t){var e={from:t.from,to:t.to};return a(e,t.attr),e.style="->"==t.type?"arrow":"line",e}var s=i(t),o={nodes:[],edges:[],options:{}};return s.nodes&&s.nodes.forEach(function(t){var e={id:t.id,label:String(t.label||t.id)};a(e,t.attr),e.image&&(e.shape="image"),o.nodes.push(e)}),s.edges&&s.edges.forEach(function(t){var i,s;i=t.from instanceof Object?t.from.nodes:{id:t.from},s=t.to instanceof Object?t.to.nodes:{id:t.to},t.from instanceof Object&&t.from.edges&&t.from.edges.forEach(function(t){var i=e(t);o.edges.push(i)}),S(i,s,function(i,s){var n=c(o,i.id,s.id,t.type,t.attr),r=e(n);o.edges.push(r)}),t.to instanceof Object&&t.to.edges&&t.to.edges.forEach(function(t){var i=e(t);o.edges.push(i)})}),s.attr&&(o.options=s.attr),o}var C={NULL:0,DELIMITER:1,IDENTIFIER:2,UNKNOWN:3},E={"{":!0,"}":!0,"[":!0,"]":!0,";":!0,"=":!0,",":!0,"->":!0,"--":!0},D="",T=0,O="",L="",k=C.NULL,N=/[a-zA-Z_0-9.:#]/;e.parseDOT=i,e.DOTToGraph=M},function(t,e){function i(t,e){var i=[],s=[];this.options={edges:{inheritColor:!0},nodes:{allowedToMove:!1,parseColor:!1}},void 0!==e&&(this.options.nodes.allowedToMove=e.allowedToMove|!1,this.options.nodes.parseColor=e.parseColor|!1,this.options.edges.inheritColor=e.inheritColor|!0);for(var o=t.edges,n=t.nodes,r=0;r=s&&(s=864e5),e=new Date(e.valueOf()-.05*s),i=new Date(i.valueOf()+.05*s)}(null!==e||null!==i)&&this.range.setRange(e,i)},s.prototype.setWindow=function(t,e){if(1==arguments.length){var i=arguments[0];this.range.setRange(i.start,i.end)}else this.range.setRange(t,e)},s.prototype.getWindow=function(){var t=this.range.getRange();return{start:new Date(t.start),end:new Date(t.end)}},s.prototype.redraw=function(){var t=!1,e=this.options,i=this.props,s=this.dom;if(s){s.root.className="vis timeline root "+e.orientation,s.root.style.maxHeight=r.option.asSize(e.maxHeight,""),s.root.style.minHeight=r.option.asSize(e.minHeight,""),s.root.style.width=r.option.asSize(e.width,""),i.border.left=(s.centerContainer.offsetWidth-s.centerContainer.clientWidth)/2,i.border.right=i.border.left,i.border.top=(s.centerContainer.offsetHeight-s.centerContainer.clientHeight)/2,i.border.bottom=i.border.top;var o=s.root.offsetHeight-s.root.clientHeight,n=s.root.offsetWidth-s.root.clientWidth;i.center.height=s.center.offsetHeight,i.left.height=s.left.offsetHeight,i.right.height=s.right.offsetHeight,i.top.height=s.top.clientHeight||-i.border.top,i.bottom.height=s.bottom.clientHeight||-i.border.bottom;var a=Math.max(i.left.height,i.center.height,i.right.height),h=i.top.height+a+i.bottom.height+o+i.border.top+i.border.bottom;s.root.style.height=r.option.asSize(e.height,h+"px"),i.root.height=s.root.offsetHeight,i.background.height=i.root.height-o;var d=i.root.height-i.top.height-i.bottom.height-o;i.centerContainer.height=d,i.leftContainer.height=d,i.rightContainer.height=i.leftContainer.height,i.root.width=s.root.offsetWidth,i.background.width=i.root.width-n,i.left.width=s.leftContainer.clientWidth||-i.border.left,i.leftContainer.width=i.left.width,i.right.width=s.rightContainer.clientWidth||-i.border.right,i.rightContainer.width=i.right.width;var l=i.root.width-i.left.width-i.right.width-n;i.center.width=l,i.centerContainer.width=l,i.top.width=l,i.bottom.width=l,s.background.style.height=i.background.height+"px",s.backgroundVertical.style.height=i.background.height+"px",s.backgroundHorizontal.style.height=i.centerContainer.height+"px",s.centerContainer.style.height=i.centerContainer.height+"px",s.leftContainer.style.height=i.leftContainer.height+"px",s.rightContainer.style.height=i.rightContainer.height+"px",s.background.style.width=i.background.width+"px",s.backgroundVertical.style.width=i.centerContainer.width+"px",s.backgroundHorizontal.style.width=i.background.width+"px",s.centerContainer.style.width=i.center.width+"px",s.top.style.width=i.top.width+"px",s.bottom.style.width=i.bottom.width+"px",s.background.style.left="0",s.background.style.top="0",s.backgroundVertical.style.left=i.left.width+"px",s.backgroundVertical.style.top="0",s.backgroundHorizontal.style.left="0",s.backgroundHorizontal.style.top=i.top.height+"px",s.centerContainer.style.left=i.left.width+"px",s.centerContainer.style.top=i.top.height+"px",s.leftContainer.style.left="0",s.leftContainer.style.top=i.top.height+"px",s.rightContainer.style.left=i.left.width+i.center.width+"px",s.rightContainer.style.top=i.top.height+"px",s.top.style.left=i.left.width+"px",s.top.style.top="0",s.bottom.style.left=i.left.width+"px",s.bottom.style.top=i.top.height+i.centerContainer.height+"px",this._updateScrollTop();var c=this.props.scrollTop;"bottom"==e.orientation&&(c+=Math.max(this.props.centerContainer.height-this.props.center.height-this.props.border.top-this.props.border.bottom,0)),s.center.style.left="0",s.center.style.top=c+"px",s.left.style.left="0",s.left.style.top=c+"px",s.right.style.left="0",s.right.style.top=c+"px";var p=0==this.props.scrollTop?"hidden":"",u=this.props.scrollTop==this.props.scrollTopMin?"hidden":"";s.shadowTop.style.visibility=p,s.shadowBottom.style.visibility=u,s.shadowTopLeft.style.visibility=p,s.shadowBottomLeft.style.visibility=u,s.shadowTopRight.style.visibility=p,s.shadowBottomRight.style.visibility=u,this.components.forEach(function(e){t=e.redraw()||t}),t&&this.redraw()}},s.prototype.repaint=function(){throw new Error("Function repaint is deprecated. Use redraw instead.")},s.prototype._toTime=function(t){var e=this.range.conversion(this.props.center.width);return new Date(t/e.scale+e.offset)},s.prototype._toGlobalTime=function(t){var e=this.range.conversion(this.props.root.width);return new Date(t/e.scale+e.offset)},s.prototype._toScreen=function(t){var e=this.range.conversion(this.props.center.width);return(t.valueOf()-e.offset)*e.scale},s.prototype._toGlobalScreen=function(t){var e=this.range.conversion(this.props.root.width);return(t.valueOf()-e.offset)*e.scale},s.prototype._initAutoResize=function(){1==this.options.autoResize?this._startAutoResize():this._stopAutoResize()},s.prototype._startAutoResize=function(){var t=this;this._stopAutoResize(),this._onResize=function(){return 1!=t.options.autoResize?void t._stopAutoResize():void(t.dom.root&&(t.dom.root.clientWidth!=t.props.lastWidth||t.dom.root.clientHeight!=t.props.lastHeight)&&(t.props.lastWidth=t.dom.root.clientWidth,t.props.lastHeight=t.dom.root.clientHeight,t.emit("change")))},r.addEventListener(window,"resize",this._onResize),this.watchTimer=setInterval(this._onResize,1e3)},s.prototype._stopAutoResize=function(){this.watchTimer&&(clearInterval(this.watchTimer),this.watchTimer=void 0),r.removeEventListener(window,"resize",this._onResize),this._onResize=null},s.prototype._onTouch=function(){this.touch.allowDragging=!0},s.prototype._onPinch=function(){this.touch.allowDragging=!1},s.prototype._onDragStart=function(){this.touch.initialScrollTop=this.props.scrollTop},s.prototype._onDrag=function(t){if(this.touch.allowDragging){var e=t.gesture.deltaY,i=this._getScrollTop(),s=this._setScrollTop(this.touch.initialScrollTop+e);s!=i&&this.redraw()}},s.prototype._setScrollTop=function(t){return this.props.scrollTop=t,this._updateScrollTop(),this.props.scrollTop},s.prototype._updateScrollTop=function(){var t=Math.min(this.props.centerContainer.height-this.props.center.height,0);return t!=this.props.scrollTopMin&&("bottom"==this.options.orientation&&(this.props.scrollTop+=t-this.props.scrollTopMin),this.props.scrollTopMin=t),this.props.scrollTop>0&&(this.props.scrollTop=0),this.props.scrollTops;s++){var o=s%2===0?1.3*i:.5*i;this.lineTo(t+o*Math.sin(2*s*Math.PI/10),e-o*Math.cos(2*s*Math.PI/10))}this.closePath()},CanvasRenderingContext2D.prototype.roundRect=function(t,e,i,s,o){var n=Math.PI/180;0>i-2*o&&(o=i/2),0>s-2*o&&(o=s/2),this.beginPath(),this.moveTo(t+o,e),this.lineTo(t+i-o,e),this.arc(t+i-o,e+o,o,270*n,360*n,!1),this.lineTo(t+i,e+s-o),this.arc(t+i-o,e+s-o,o,0,90*n,!1),this.lineTo(t+o,e+s),this.arc(t+o,e+s-o,o,90*n,180*n,!1),this.lineTo(t,e+o),this.arc(t+o,e+o,o,180*n,270*n,!1)},CanvasRenderingContext2D.prototype.ellipse=function(t,e,i,s){var o=.5522848,n=i/2*o,r=s/2*o,a=t+i,h=e+s,d=t+i/2,l=e+s/2;this.beginPath(),this.moveTo(t,l),this.bezierCurveTo(t,l-r,d-n,e,d,e),this.bezierCurveTo(d+n,e,a,l-r,a,l),this.bezierCurveTo(a,l+r,d+n,h,d,h),this.bezierCurveTo(d-n,h,t,l+r,t,l)},CanvasRenderingContext2D.prototype.database=function(t,e,i,s){var o=1/3,n=i,r=s*o,a=.5522848,h=n/2*a,d=r/2*a,l=t+n,c=e+r,p=t+n/2,u=e+r/2,f=e+(s-r/2),m=e+s;this.beginPath(),this.moveTo(l,u),this.bezierCurveTo(l,u+d,p+h,c,p,c),this.bezierCurveTo(p-h,c,t,u+d,t,u),this.bezierCurveTo(t,u-d,p-h,e,p,e),this.bezierCurveTo(p+h,e,l,u-d,l,u),this.lineTo(l,f),this.bezierCurveTo(l,f+d,p+h,m,p,m),this.bezierCurveTo(p-h,m,t,f+d,t,f),this.lineTo(t,u)},CanvasRenderingContext2D.prototype.arrow=function(t,e,i,s){var o=t-s*Math.cos(i),n=e-s*Math.sin(i),r=t-.9*s*Math.cos(i),a=e-.9*s*Math.sin(i),h=o+s/3*Math.cos(i+.5*Math.PI),d=n+s/3*Math.sin(i+.5*Math.PI),l=o+s/3*Math.cos(i-.5*Math.PI),c=n+s/3*Math.sin(i-.5*Math.PI);this.beginPath(),this.moveTo(t,e),this.lineTo(h,d),this.lineTo(r,a),this.lineTo(l,c),this.closePath()},CanvasRenderingContext2D.prototype.dashedLine=function(t,e,i,s,o){o||(o=[10,5]),0==p&&(p=.001);var n=o.length;this.moveTo(t,e);for(var r=i-t,a=s-e,h=a/r,d=Math.sqrt(r*r+a*a),l=0,c=!0;d>=.1;){var p=o[l++%n];p>d&&(p=d);var u=Math.sqrt(p*p/(1+h*h));0>r&&(u=-u),t+=u,e+=h*u,this[c?"lineTo":"moveTo"](t,e),d-=p,c=!c}})},function(t,e,i){var s=i(56),o=i(50),n=i(51),r=i(52),a=i(53),h=i(54),d=i(55);e._loadMixin=function(t){for(var e in t)t.hasOwnProperty(e)&&(this[e]=t[e])},e._clearMixin=function(t){for(var e in t)t.hasOwnProperty(e)&&(this[e]=void 0)},e._loadPhysicsSystem=function(){this._loadMixin(s),this._loadSelectedForceSolver(),1==this.constants.configurePhysics&&this._loadPhysicsConfiguration()},e._loadClusterSystem=function(){this.clusterSession=0,this.hubThreshold=5,this._loadMixin(o)},e._loadSectorSystem=function(){this.sectors={},this.activeSector=["default"],this.sectors.active={},this.sectors.active["default"]={nodes:{},edges:{},nodeIndices:[],formationScale:1,drawingNode:void 0},this.sectors.frozen={},this.sectors.support={nodes:{},edges:{},nodeIndices:[],formationScale:1,drawingNode:void 0},this.nodeIndices=this.sectors.active["default"].nodeIndices,this._loadMixin(n)},e._loadSelectionSystem=function(){this.selectionObj={nodes:{},edges:{}},this._loadMixin(r)},e._loadManipulationSystem=function(){this.blockConnectingEdgeSelection=!1,this.forceAppendSelection=!1,1==this.constants.dataManipulation.enabled?(void 0===this.manipulationDiv&&(this.manipulationDiv=document.createElement("div"),this.manipulationDiv.className="network-manipulationDiv",this.manipulationDiv.id="network-manipulationDiv",this.manipulationDiv.style.display=1==this.editMode?"block":"none",this.containerElement.insertBefore(this.manipulationDiv,this.frame)),void 0===this.editModeDiv&&(this.editModeDiv=document.createElement("div"),this.editModeDiv.className="network-manipulation-editMode",this.editModeDiv.id="network-manipulation-editMode",this.editModeDiv.style.display=1==this.editMode?"none":"block",this.containerElement.insertBefore(this.editModeDiv,this.frame)),void 0===this.closeDiv&&(this.closeDiv=document.createElement("div"),this.closeDiv.className="network-manipulation-closeDiv",this.closeDiv.id="network-manipulation-closeDiv",this.closeDiv.style.display=this.manipulationDiv.style.display,this.containerElement.insertBefore(this.closeDiv,this.frame)),this._loadMixin(a),this._createManipulatorBar()):void 0!==this.manipulationDiv&&(this._createManipulatorBar(),this.containerElement.removeChild(this.manipulationDiv),this.containerElement.removeChild(this.editModeDiv),this.containerElement.removeChild(this.closeDiv),this.manipulationDiv=void 0,this.editModeDiv=void 0,this.closeDiv=void 0,this._clearMixin(a))},e._loadNavigationControls=function(){this._loadMixin(h),this._cleanNavigation(),1==this.constants.navigation.enabled&&this._loadNavigationElements()},e._loadHierarchySystem=function(){this._loadMixin(d)}},function(t){function e(t){return t?i(t):void 0}function i(t){for(var i in e.prototype)t[i]=e.prototype[i];return t}t.exports=e,e.prototype.on=e.prototype.addEventListener=function(t,e){return this._callbacks=this._callbacks||{},(this._callbacks[t]=this._callbacks[t]||[]).push(e),this},e.prototype.once=function(t,e){function i(){s.off(t,i),e.apply(this,arguments)}var s=this;return this._callbacks=this._callbacks||{},i.fn=e,this.on(t,i),this},e.prototype.off=e.prototype.removeListener=e.prototype.removeAllListeners=e.prototype.removeEventListener=function(t,e){if(this._callbacks=this._callbacks||{},0==arguments.length)return this._callbacks={},this;var i=this._callbacks[t];if(!i)return this;if(1==arguments.length)return delete this._callbacks[t],this;for(var s,o=0;os;++s)i[s].apply(this,e)}return this},e.prototype.listeners=function(t){return this._callbacks=this._callbacks||{},this._callbacks[t]||[]},e.prototype.hasListeners=function(t){return!!this.listeners(t).length}},function(t){function e(t,e,i){return t.addEventListener?t.addEventListener(e,i,!1):void t.attachEvent("on"+e,i)}function i(t){return"keypress"==t.type?String.fromCharCode(t.which):_[t.which]?_[t.which]:x[t.which]?x[t.which]:String.fromCharCode(t.which).toLowerCase()}function s(t){var e=t.target||t.srcElement,i=e.tagName;return(" "+e.className+" ").indexOf(" mousetrap ")>-1?!1:"INPUT"==i||"SELECT"==i||"TEXTAREA"==i||e.contentEditable&&"true"==e.contentEditable}function o(t,e){return t.sort().join(",")===e.sort().join(",")}function n(t){t=t||{};var e,i=!1;for(e in E)t[e]?i=!0:E[e]=0;i||(T=!1)}function r(t,e,i,s,n){var r,a,h=[];if(!M[t])return[];for("keyup"==i&&c(t)&&(e=[t]),r=0;r95&&112>t||_.hasOwnProperty(t)&&(y[_[t]]=t)}return y}function f(t,e,i){return i||(i=u()[t]?"keydown":"keypress"),"keypress"==i&&e.length&&(i="keydown"),i}function m(t,e,s,o){E[t]=0,o||(o=f(e[0],[]));var r,a=function(){T=o,++E[t],p()},d=function(t){h(s,t),"keyup"!==o&&(D=i(t)),setTimeout(n,10)};for(r=0;r1)return m(t,d,e,i);for(h="+"===t?["+"]:t.split("+"),n=0;n":".","?":"/","|":"\\"},S={option:"alt",command:"meta","return":"enter",escape:"esc"},M={},C={},E={},D=!1,T=!1,O=1;20>O;++O)_[111+O]="f"+O;for(O=0;9>=O;++O)_[O+96]=O;e(document,"keypress",l),e(document,"keydown",l),e(document,"keyup",l);var L={bind:function(t,e,i){return v(t instanceof Array?t:[t],e,i),C[t+":"+i]=e,this},unbind:function(t,e){return C[t+":"+e]&&(delete C[t+":"+e],this.bind(t,function(){},e)),this},trigger:function(t,e){return C[t+":"+e](),this},reset:function(){return M={},C={},this}};t.exports=L},function(t,e,i){var s;!function(o,n){"use strict";function r(){a.READY||(w.determineEventTypes(),x.each(a.gestures,function(t){M.register(t)}),w.onTouch(a.DOCUMENT,v,M.detect),w.onTouch(a.DOCUMENT,y,M.detect),a.READY=!0)}var a=function C(t,e){return new C.Instance(t,e||{})};a.VERSION="1.1.3",a.defaults={behavior:{userSelect:"none",touchAction:"pan-y",touchCallout:"none",contentZooming:"none",userDrag:"none",tapHighlightColor:"rgba(0,0,0,0)"}},a.DOCUMENT=document,a.HAS_POINTEREVENTS=navigator.pointerEnabled||navigator.msPointerEnabled,a.HAS_TOUCHEVENTS="ontouchstart"in o,a.IS_MOBILE=/mobile|tablet|ip(ad|hone|od)|android|silk/i.test(navigator.userAgent),a.NO_MOUSEEVENTS=a.HAS_TOUCHEVENTS&&a.IS_MOBILE||a.HAS_POINTEREVENTS,a.CALCULATE_INTERVAL=25;var h={},d=a.DIRECTION_DOWN="down",l=a.DIRECTION_LEFT="left",c=a.DIRECTION_UP="up",p=a.DIRECTION_RIGHT="right",u=a.POINTER_MOUSE="mouse",f=a.POINTER_TOUCH="touch",m=a.POINTER_PEN="pen",g=a.EVENT_START="start",v=a.EVENT_MOVE="move",y=a.EVENT_END="end",b=a.EVENT_RELEASE="release",_=a.EVENT_TOUCH="touch"; -a.READY=!1,a.plugins=a.plugins||{},a.gestures=a.gestures||{};var x=a.utils={extend:function(t,e,i){for(var s in e)!e.hasOwnProperty(s)||t[s]!==n&&i||(t[s]=e[s]);return t},on:function(t,e,i){t.addEventListener(e,i,!1)},off:function(t,e,i){t.removeEventListener(e,i,!1)},each:function(t,e,i){var s,o;if("forEach"in t)t.forEach(e,i);else if(t.length!==n){for(s=0,o=t.length;o>s;s++)if(e.call(i,t[s],s,t)===!1)return}else for(s in t)if(t.hasOwnProperty(s)&&e.call(i,t[s],s,t)===!1)return},inStr:function(t,e){return t.indexOf(e)>-1},inArray:function(t,e){if(t.indexOf){var i=t.indexOf(e);return-1===i?!1:i}for(var s=0,o=t.length;o>s;s++)if(t[s]===e)return s;return!1},toArray:function(t){return Array.prototype.slice.call(t,0)},hasParent:function(t,e){for(;t;){if(t==e)return!0;t=t.parentNode}return!1},getCenter:function(t){var e=[],i=[],s=[],o=[],n=Math.min,r=Math.max;return 1===t.length?{pageX:t[0].pageX,pageY:t[0].pageY,clientX:t[0].clientX,clientY:t[0].clientY}:(x.each(t,function(t){e.push(t.pageX),i.push(t.pageY),s.push(t.clientX),o.push(t.clientY)}),{pageX:(n.apply(Math,e)+r.apply(Math,e))/2,pageY:(n.apply(Math,i)+r.apply(Math,i))/2,clientX:(n.apply(Math,s)+r.apply(Math,s))/2,clientY:(n.apply(Math,o)+r.apply(Math,o))/2})},getVelocity:function(t,e,i){return{x:Math.abs(e/t)||0,y:Math.abs(i/t)||0}},getAngle:function(t,e){var i=e.clientX-t.clientX,s=e.clientY-t.clientY;return 180*Math.atan2(s,i)/Math.PI},getDirection:function(t,e){var i=Math.abs(t.clientX-e.clientX),s=Math.abs(t.clientY-e.clientY);return i>=s?t.clientX-e.clientX>0?l:p:t.clientY-e.clientY>0?c:d},getDistance:function(t,e){var i=e.clientX-t.clientX,s=e.clientY-t.clientY;return Math.sqrt(i*i+s*s)},getScale:function(t,e){return t.length>=2&&e.length>=2?this.getDistance(e[0],e[1])/this.getDistance(t[0],t[1]):1},getRotation:function(t,e){return t.length>=2&&e.length>=2?this.getAngle(e[1],e[0])-this.getAngle(t[1],t[0]):0},isVertical:function(t){return t==c||t==d},setPrefixedCss:function(t,e,i,s){var o=["","Webkit","Moz","O","ms"];e=x.toCamelCase(e);for(var n=0;n0&&this.started&&(r=v),this.started=!0;var d=this.collectEventData(i,r,o,t);return e!=y&&s.call(M,d),a&&(d.changedLength=h,d.eventType=a,s.call(M,d),d.eventType=r,delete d.changedLength),r==y&&(s.call(M,d),this.started=!1),r},determineEventTypes:function(){var t;return t=a.HAS_POINTEREVENTS?o.PointerEvent?["pointerdown","pointermove","pointerup pointercancel lostpointercapture"]:["MSPointerDown","MSPointerMove","MSPointerUp MSPointerCancel MSLostPointerCapture"]:a.NO_MOUSEEVENTS?["touchstart","touchmove","touchend touchcancel"]:["touchstart mousedown","touchmove mousemove","touchend touchcancel mouseup"],h[g]=t[0],h[v]=t[1],h[y]=t[2],h},getTouchList:function(t,e){if(a.HAS_POINTEREVENTS)return S.getTouchList();if(t.touches){if(e==v)return t.touches;var i=[],s=[].concat(x.toArray(t.touches),x.toArray(t.changedTouches)),o=[];return x.each(s,function(t){x.inArray(i,t.identifier)===!1&&o.push(t),i.push(t.identifier)}),o}return t.identifier=1,[t]},collectEventData:function(t,e,i,s){var o=f;return x.inStr(s.type,"mouse")||S.matchType(u,s)?o=u:S.matchType(m,s)&&(o=m),{center:x.getCenter(i),timeStamp:Date.now(),target:s.target,touches:i,eventType:e,pointerType:o,srcEvent:s,preventDefault:function(){var t=this.srcEvent;t.preventManipulation&&t.preventManipulation(),t.preventDefault&&t.preventDefault()},stopPropagation:function(){this.srcEvent.stopPropagation()},stopDetect:function(){return M.stopDetect()}}}},S=a.PointerEvent={pointers:{},getTouchList:function(){var t=[];return x.each(this.pointers,function(e){t.push(e)}),t},updatePointer:function(t,e){t==y||t!=y&&1!==e.buttons?delete this.pointers[e.pointerId]:(e.identifier=e.pointerId,this.pointers[e.pointerId]=e)},matchType:function(t,e){if(!e.pointerType)return!1;var i=e.pointerType,s={};return s[u]=i===(e.MSPOINTER_TYPE_MOUSE||u),s[f]=i===(e.MSPOINTER_TYPE_TOUCH||f),s[m]=i===(e.MSPOINTER_TYPE_PEN||m),s[t]},reset:function(){this.pointers={}}},M=a.detection={gestures:[],current:null,previous:null,stopped:!1,startDetect:function(t,e){this.current||(this.stopped=!1,this.current={inst:t,startEvent:x.extend({},e),lastEvent:!1,lastCalcEvent:!1,futureCalcEvent:!1,lastCalcData:{},name:""},this.detect(e))},detect:function(t){if(this.current&&!this.stopped){t=this.extendEventData(t);var e=this.current.inst,i=e.options;return x.each(this.gestures,function(s){!this.stopped&&e.enabled&&i[s.name]&&s.handler.call(s,t,e)},this),this.current&&(this.current.lastEvent=t),t.eventType==y&&this.stopDetect(),t}},stopDetect:function(){this.previous=x.extend({},this.current),this.current=null,this.stopped=!0},getCalculatedData:function(t,e,i,s,o){var n=this.current,r=!1,h=n.lastCalcEvent,d=n.lastCalcData;h&&t.timeStamp-h.timeStamp>a.CALCULATE_INTERVAL&&(e=h.center,i=t.timeStamp-h.timeStamp,s=t.center.clientX-h.center.clientX,o=t.center.clientY-h.center.clientY,r=!0),(t.eventType==_||t.eventType==b)&&(n.futureCalcEvent=t),(!n.lastCalcEvent||r)&&(d.velocity=x.getVelocity(i,s,o),d.angle=x.getAngle(e,t.center),d.direction=x.getDirection(e,t.center),n.lastCalcEvent=n.futureCalcEvent||t,n.futureCalcEvent=t),t.velocityX=d.velocity.x,t.velocityY=d.velocity.y,t.interimAngle=d.angle,t.interimDirection=d.direction},extendEventData:function(t){var e=this.current,i=e.startEvent,s=e.lastEvent||i;(t.eventType==_||t.eventType==b)&&(i.touches=[],x.each(t.touches,function(t){i.touches.push({clientX:t.clientX,clientY:t.clientY})}));var o=t.timeStamp-i.timeStamp,n=t.center.clientX-i.center.clientX,r=t.center.clientY-i.center.clientY;return this.getCalculatedData(t,s.center,o,n,r),x.extend(t,{startEvent:i,deltaTime:o,deltaX:n,deltaY:r,distance:x.getDistance(i.center,t.center),angle:x.getAngle(i.center,t.center),direction:x.getDirection(i.center,t.center),scale:x.getScale(i.touches,t.touches),rotation:x.getRotation(i.touches,t.touches)}),t},register:function(t){var e=t.defaults||{};return e[t.name]===n&&(e[t.name]=!0),x.extend(a.defaults,e,!0),t.index=t.index||1e3,this.gestures.push(t),this.gestures.sort(function(t,e){return t.indexe.index?1:0}),this.gestures}};a.Instance=function(t,e){var i=this;r(),this.element=t,this.enabled=!0,x.each(e,function(t,i){delete e[i],e[x.toCamelCase(i)]=t}),this.options=x.extend(x.extend({},a.defaults),e||{}),this.options.behavior&&x.toggleBehavior(this.element,this.options.behavior,!0),this.eventStartHandler=w.onTouch(t,g,function(t){i.enabled&&t.eventType==g?M.startDetect(i,t):t.eventType==_&&M.detect(t)}),this.eventHandlers=[]},a.Instance.prototype={on:function(t,e){var i=this;return w.on(i.element,t,e,function(t){i.eventHandlers.push({gesture:t,handler:e})}),i},off:function(t,e){var i=this;return w.off(i.element,t,e,function(t){var s=x.inArray({gesture:t,handler:e});s!==!1&&i.eventHandlers.splice(s,1)}),i},trigger:function(t,e){e||(e={});var i=a.DOCUMENT.createEvent("Event");i.initEvent(t,!0,!0),i.gesture=e;var s=this.element;return x.hasParent(e.target,s)&&(s=e.target),s.dispatchEvent(i),this},enable:function(t){return this.enabled=t,this},dispose:function(){var t,e;for(x.toggleBehavior(this.element,this.options.behavior,!1),t=-1;e=this.eventHandlers[++t];)x.off(this.element,e.gesture,e.handler);return this.eventHandlers=[],w.off(this.element,h[g],this.eventStartHandler),null}},function(t){function e(e,s){var o=M.current;if(!(s.options.dragMaxTouches>0&&e.touches.length>s.options.dragMaxTouches))switch(e.eventType){case g:i=!1;break;case v:if(e.distance0)){var r=Math.abs(s.options.dragMinDistance/e.distance);n.pageX+=e.deltaX*r,n.pageY+=e.deltaY*r,n.clientX+=e.deltaX*r,n.clientY+=e.deltaY*r,e=M.extendEventData(e)}(o.lastEvent.dragLockToAxis||s.options.dragLockToAxis&&s.options.dragLockMinDistance<=e.distance)&&(e.dragLockToAxis=!0);var a=o.lastEvent.direction;e.dragLockToAxis&&a!==e.direction&&(e.direction=x.isVertical(a)?e.deltaY<0?c:d:e.deltaX<0?l:p),i||(s.trigger(t+"start",e),i=!0),s.trigger(t,e),s.trigger(t+e.direction,e);var h=x.isVertical(e.direction);(s.options.dragBlockVertical&&h||s.options.dragBlockHorizontal&&!h)&&e.preventDefault();break;case b:i&&e.changedLength<=s.options.dragMaxTouches&&(s.trigger(t+"end",e),i=!1);break;case y:i=!1}}var i=!1;a.gestures.Drag={name:t,index:50,handler:e,defaults:{dragMinDistance:10,dragDistanceCorrection:!0,dragMaxTouches:1,dragBlockHorizontal:!1,dragBlockVertical:!1,dragLockToAxis:!1,dragLockMinDistance:25}}}("drag"),a.gestures.Gesture={name:"gesture",index:1337,handler:function(t,e){e.trigger(this.name,t)}},function(t){function e(e,s){var o=s.options,n=M.current;switch(e.eventType){case g:clearTimeout(i),n.name=t,i=setTimeout(function(){n&&n.name==t&&s.trigger(t,e)},o.holdTimeout);break;case v:e.distance>o.holdThreshold&&clearTimeout(i);break;case b:clearTimeout(i)}}var i;a.gestures.Hold={name:t,index:10,defaults:{holdTimeout:500,holdThreshold:2},handler:e}}("hold"),a.gestures.Release={name:"release",index:1/0,handler:function(t,e){t.eventType==b&&e.trigger(this.name,t)}},a.gestures.Swipe={name:"swipe",index:40,defaults:{swipeMinTouches:1,swipeMaxTouches:1,swipeVelocityX:.6,swipeVelocityY:.6},handler:function(t,e){if(t.eventType==b){var i=t.touches.length,s=e.options;if(is.swipeMaxTouches)return;(t.velocityX>s.swipeVelocityX||t.velocityY>s.swipeVelocityY)&&(e.trigger(this.name,t),e.trigger(this.name+t.direction,t))}}},function(t){function e(e,s){var o,n,r=s.options,a=M.current,h=M.previous;switch(e.eventType){case g:i=!1;break;case v:i=i||e.distance>r.tapMaxDistance;break;case y:!x.inStr(e.srcEvent.type,"cancel")&&e.deltaTimes.options.transformMinRotation&&s.trigger("rotate",e),o>s.options.transformMinScale&&(s.trigger("pinch",e),s.trigger("pinch"+(e.scale<1?"in":"out"),e));break;case b:i&&e.changedLength<2&&(s.trigger(t+"end",e),i=!1)}}var i=!1;a.gestures.Transform={name:t,index:45,defaults:{transformMinScale:.01,transformMinRotation:1},handler:e}}("transform"),s=function(){return a}.call(e,i,e,t),!(s!==n&&(t.exports=s))}(window)},function(t,e,i){var s;(function(t,o){(function(n){function r(t,e,i){switch(arguments.length){case 2:return null!=t?t:e;case 3:return null!=t?t:null!=e?e:i;default:throw new Error("Implement me")}}function a(){return{empty:!1,unusedTokens:[],unusedInput:[],overflow:-2,charsLeftOver:0,nullInput:!1,invalidMonth:null,invalidFormat:!1,userInvalidated:!1,iso:!1}}function h(t,e){function i(){ve.suppressDeprecationWarnings===!1&&"undefined"!=typeof console&&console.warn&&console.warn("Deprecation warning: "+t)}var s=!0;return f(function(){return s&&(i(),s=!1),e.apply(this,arguments)},e)}function d(t,e){return function(i){return v(t.call(this,i),e)}}function l(t,e){return function(i){return this.lang().ordinal(t.call(this,i),e)}}function c(){}function p(t){L(t),f(this,t)}function u(t){var e=S(t),i=e.year||0,s=e.quarter||0,o=e.month||0,n=e.week||0,r=e.day||0,a=e.hour||0,h=e.minute||0,d=e.second||0,l=e.millisecond||0;this._milliseconds=+l+1e3*d+6e4*h+36e5*a,this._days=+r+7*n,this._months=+o+3*s+12*i,this._data={},this._bubble()}function f(t,e){for(var i in e)e.hasOwnProperty(i)&&(t[i]=e[i]);return e.hasOwnProperty("toString")&&(t.toString=e.toString),e.hasOwnProperty("valueOf")&&(t.valueOf=e.valueOf),t}function m(t){var e,i={};for(e in t)t.hasOwnProperty(e)&&ke.hasOwnProperty(e)&&(i[e]=t[e]);return i}function g(t){return 0>t?Math.ceil(t):Math.floor(t)}function v(t,e,i){for(var s=""+Math.abs(t),o=t>=0;s.lengths;s++)(i&&t[s]!==e[s]||!i&&C(t[s])!==C(e[s]))&&r++;return r+n}function w(t){if(t){var e=t.toLowerCase().replace(/(.)s$/,"$1");t=ri[t]||ai[e]||e}return t}function S(t){var e,i,s={};for(i in t)t.hasOwnProperty(i)&&(e=w(i),e&&(s[e]=t[i]));return s}function M(t){var e,i;if(0===t.indexOf("week"))e=7,i="day";else{if(0!==t.indexOf("month"))return;e=12,i="month"}ve[t]=function(s,o){var r,a,h=ve.fn._lang[t],d=[];if("number"==typeof s&&(o=s,s=n),a=function(t){var e=ve().utc().set(i,t);return h.call(ve.fn._lang,e,s||"")},null!=o)return a(o);for(r=0;e>r;r++)d.push(a(r));return d}}function C(t){var e=+t,i=0;return 0!==e&&isFinite(e)&&(i=e>=0?Math.floor(e):Math.ceil(e)),i}function E(t,e){return new Date(Date.UTC(t,e+1,0)).getUTCDate()}function D(t,e,i){return re(ve([t,11,31+e-i]),e,i).week}function T(t){return O(t)?366:365}function O(t){return t%4===0&&t%100!==0||t%400===0}function L(t){var e;t._a&&-2===t._pf.overflow&&(e=t._a[Me]<0||t._a[Me]>11?Me:t._a[Ce]<1||t._a[Ce]>E(t._a[Se],t._a[Me])?Ce:t._a[Ee]<0||t._a[Ee]>23?Ee:t._a[De]<0||t._a[De]>59?De:t._a[Te]<0||t._a[Te]>59?Te:t._a[Oe]<0||t._a[Oe]>999?Oe:-1,t._pf._overflowDayOfYear&&(Se>e||e>Ce)&&(e=Ce),t._pf.overflow=e)}function k(t){return null==t._isValid&&(t._isValid=!isNaN(t._d.getTime())&&t._pf.overflow<0&&!t._pf.empty&&!t._pf.invalidMonth&&!t._pf.nullInput&&!t._pf.invalidFormat&&!t._pf.userInvalidated,t._strict&&(t._isValid=t._isValid&&0===t._pf.charsLeftOver&&0===t._pf.unusedTokens.length)),t._isValid}function N(t){return t?t.toLowerCase().replace("_","-"):t}function I(t,e){return e._isUTC?ve(t).zone(e._offset||0):ve(t).local()}function A(t,e){return e.abbr=t,Le[t]||(Le[t]=new c),Le[t].set(e),Le[t]}function z(t){delete Le[t]}function P(t){var e,s,o,n,r=0,a=function(t){if(!Le[t]&&Ne)try{i(57)("./"+t)}catch(e){}return Le[t]};if(!t)return ve.fn._lang;if(!b(t)){if(s=a(t))return s;t=[t]}for(;r0;){if(s=a(n.slice(0,e).join("-")))return s;if(o&&o.length>=e&&x(n,o,!0)>=e-1)break;e--}r++}return ve.fn._lang}function R(t){return t.match(/\[[\s\S]/)?t.replace(/^\[|\]$/g,""):t.replace(/\\/g,"")}function F(t){var e,i,s=t.match(Pe);for(e=0,i=s.length;i>e;e++)s[e]=pi[s[e]]?pi[s[e]]:R(s[e]);return function(o){var n="";for(e=0;i>e;e++)n+=s[e]instanceof Function?s[e].call(o,t):s[e];return n}}function H(t,e){return t.isValid()?(e=Y(e,t.lang()),hi[e]||(hi[e]=F(e)),hi[e](t)):t.lang().invalidDate()}function Y(t,e){function i(t){return e.longDateFormat(t)||t}var s=5;for(Re.lastIndex=0;s>=0&&Re.test(t);)t=t.replace(Re,i),Re.lastIndex=0,s-=1;return t}function B(t,e){var i,s=e._strict;switch(t){case"Q":return Ze;case"DDDD":return Ke;case"YYYY":case"GGGG":case"gggg":return s?$e:Ye;case"Y":case"G":case"g":return Qe;case"YYYYYY":case"YYYYY":case"GGGGG":case"ggggg":return s?Je:Be;case"S":if(s)return Ze;case"SS":if(s)return qe;case"SSS":if(s)return Ke;case"DDD":return He;case"MMM":case"MMMM":case"dd":case"ddd":case"dddd":return Ge;case"a":case"A":return P(e._l)._meridiemParse;case"X":return Ue;case"Z":case"ZZ":return je;case"T":return Ve;case"SSSS":return We;case"MM":case"DD":case"YY":case"GG":case"gg":case"HH":case"hh":case"mm":case"ss":case"ww":case"WW":return s?qe:Fe;case"M":case"D":case"d":case"H":case"h":case"m":case"s":case"w":case"W":case"e":case"E":return Fe;case"Do":return Xe;default:return i=new RegExp(K(q(t.replace("\\","")),"i"))}}function W(t){t=t||"";var e=t.match(je)||[],i=e[e.length-1]||[],s=(i+"").match(oi)||["-",0,0],o=+(60*s[1])+C(s[2]);return"+"===s[0]?-o:o}function G(t,e,i){var s,o=i._a;switch(t){case"Q":null!=e&&(o[Me]=3*(C(e)-1));break;case"M":case"MM":null!=e&&(o[Me]=C(e)-1);break;case"MMM":case"MMMM":s=P(i._l).monthsParse(e),null!=s?o[Me]=s:i._pf.invalidMonth=e;break;case"D":case"DD":null!=e&&(o[Ce]=C(e));break;case"Do":null!=e&&(o[Ce]=C(parseInt(e,10)));break;case"DDD":case"DDDD":null!=e&&(i._dayOfYear=C(e));break;case"YY":o[Se]=ve.parseTwoDigitYear(e);break;case"YYYY":case"YYYYY":case"YYYYYY":o[Se]=C(e);break;case"a":case"A":i._isPm=P(i._l).isPM(e);break;case"H":case"HH":case"h":case"hh":o[Ee]=C(e);break;case"m":case"mm":o[De]=C(e);break;case"s":case"ss":o[Te]=C(e);break;case"S":case"SS":case"SSS":case"SSSS":o[Oe]=C(1e3*("0."+e));break;case"X":i._d=new Date(1e3*parseFloat(e));break;case"Z":case"ZZ":i._useUTC=!0,i._tzm=W(e);break;case"dd":case"ddd":case"dddd":s=P(i._l).weekdaysParse(e),null!=s?(i._w=i._w||{},i._w.d=s):i._pf.invalidWeekday=e;break;case"w":case"ww":case"W":case"WW":case"d":case"e":case"E":t=t.substr(0,1);case"gggg":case"GGGG":case"GGGGG":t=t.substr(0,2),e&&(i._w=i._w||{},i._w[t]=C(e));break;case"gg":case"GG":i._w=i._w||{},i._w[t]=ve.parseTwoDigitYear(e)}}function j(t){var e,i,s,o,n,a,h,d;e=t._w,null!=e.GG||null!=e.W||null!=e.E?(n=1,a=4,i=r(e.GG,t._a[Se],re(ve(),1,4).year),s=r(e.W,1),o=r(e.E,1)):(d=P(t._l),n=d._week.dow,a=d._week.doy,i=r(e.gg,t._a[Se],re(ve(),n,a).year),s=r(e.w,1),null!=e.d?(o=e.d,n>o&&++s):o=null!=e.e?e.e+n:n),h=ae(i,s,o,a,n),t._a[Se]=h.year,t._dayOfYear=h.dayOfYear}function V(t){var e,i,s,o,n=[];if(!t._d){for(s=X(t),t._w&&null==t._a[Ce]&&null==t._a[Me]&&j(t),t._dayOfYear&&(o=r(t._a[Se],s[Se]),t._dayOfYear>T(o)&&(t._pf._overflowDayOfYear=!0),i=ie(o,0,t._dayOfYear),t._a[Me]=i.getUTCMonth(),t._a[Ce]=i.getUTCDate()),e=0;3>e&&null==t._a[e];++e)t._a[e]=n[e]=s[e];for(;7>e;e++)t._a[e]=n[e]=null==t._a[e]?2===e?1:0:t._a[e];t._d=(t._useUTC?ie:ee).apply(null,n),null!=t._tzm&&t._d.setUTCMinutes(t._d.getUTCMinutes()+t._tzm)}}function U(t){var e;t._d||(e=S(t._i),t._a=[e.year,e.month,e.day,e.hour,e.minute,e.second,e.millisecond],V(t))}function X(t){var e=new Date;return t._useUTC?[e.getUTCFullYear(),e.getUTCMonth(),e.getUTCDate()]:[e.getFullYear(),e.getMonth(),e.getDate()]}function Z(t){if(t._f===ve.ISO_8601)return void J(t);t._a=[],t._pf.empty=!0;var e,i,s,o,n,r=P(t._l),a=""+t._i,h=a.length,d=0;for(s=Y(t._f,r).match(Pe)||[],e=0;e0&&t._pf.unusedInput.push(n),a=a.slice(a.indexOf(i)+i.length),d+=i.length),pi[o]?(i?t._pf.empty=!1:t._pf.unusedTokens.push(o),G(o,i,t)):t._strict&&!i&&t._pf.unusedTokens.push(o);t._pf.charsLeftOver=h-d,a.length>0&&t._pf.unusedInput.push(a),t._isPm&&t._a[Ee]<12&&(t._a[Ee]+=12),t._isPm===!1&&12===t._a[Ee]&&(t._a[Ee]=0),V(t),L(t)}function q(t){return t.replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g,function(t,e,i,s,o){return e||i||s||o})}function K(t){return t.replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&")}function $(t){var e,i,s,o,n;if(0===t._f.length)return t._pf.invalidFormat=!0,void(t._d=new Date(0/0));for(o=0;on)&&(s=n,i=e));f(t,i||e)}function J(t){var e,i,s=t._i,o=ti.exec(s);if(o){for(t._pf.iso=!0,e=0,i=ii.length;i>e;e++)if(ii[e][1].exec(s)){t._f=ii[e][0]+(o[6]||" ");break}for(e=0,i=si.length;i>e;e++)if(si[e][1].exec(s)){t._f+=si[e][0];break}s.match(je)&&(t._f+="Z"),Z(t)}else t._isValid=!1}function Q(t){J(t),t._isValid===!1&&(delete t._isValid,ve.createFromInputFallback(t))}function te(t){var e=t._i,i=Ie.exec(e);e===n?t._d=new Date:i?t._d=new Date(+i[1]):"string"==typeof e?Q(t):b(e)?(t._a=e.slice(0),V(t)):_(e)?t._d=new Date(+e):"object"==typeof e?U(t):"number"==typeof e?t._d=new Date(e):ve.createFromInputFallback(t)}function ee(t,e,i,s,o,n,r){var a=new Date(t,e,i,s,o,n,r);return 1970>t&&a.setFullYear(t),a}function ie(t){var e=new Date(Date.UTC.apply(null,arguments));return 1970>t&&e.setUTCFullYear(t),e}function se(t,e){if("string"==typeof t)if(isNaN(t)){if(t=e.weekdaysParse(t),"number"!=typeof t)return null}else t=parseInt(t,10);return t}function oe(t,e,i,s,o){return o.relativeTime(e||1,!!i,t,s)}function ne(t,e,i){var s=we(Math.abs(t)/1e3),o=we(s/60),n=we(o/60),r=we(n/24),a=we(r/365),h=s0,h[4]=i,oe.apply({},h)}function re(t,e,i){var s,o=i-e,n=i-t.day();return n>o&&(n-=7),o-7>n&&(n+=7),s=ve(t).add("d",n),{week:Math.ceil(s.dayOfYear()/7),year:s.year()}}function ae(t,e,i,s,o){var n,r,a=ie(t,0,1).getUTCDay();return a=0===a?7:a,i=null!=i?i:o,n=o-a+(a>s?7:0)-(o>a?7:0),r=7*(e-1)+(i-o)+n+1,{year:r>0?t:t-1,dayOfYear:r>0?r:T(t-1)+r}}function he(t){var e=t._i,i=t._f;return null===e||i===n&&""===e?ve.invalid({nullInput:!0}):("string"==typeof e&&(t._i=e=P().preparse(e)),ve.isMoment(e)?(t=m(e),t._d=new Date(+e._d)):i?b(i)?$(t):Z(t):te(t),new p(t))}function de(t,e){var i,s;if(1===e.length&&b(e[0])&&(e=e[0]),!e.length)return ve();for(i=e[0],s=1;s=0?"+":"-";return e+v(Math.abs(t),6)},gg:function(){return v(this.weekYear()%100,2)},gggg:function(){return v(this.weekYear(),4)},ggggg:function(){return v(this.weekYear(),5)},GG:function(){return v(this.isoWeekYear()%100,2)},GGGG:function(){return v(this.isoWeekYear(),4)},GGGGG:function(){return v(this.isoWeekYear(),5)},e:function(){return this.weekday()},E:function(){return this.isoWeekday()},a:function(){return this.lang().meridiem(this.hours(),this.minutes(),!0)},A:function(){return this.lang().meridiem(this.hours(),this.minutes(),!1)},H:function(){return this.hours()},h:function(){return this.hours()%12||12},m:function(){return this.minutes()},s:function(){return this.seconds()},S:function(){return C(this.milliseconds()/100)},SS:function(){return v(C(this.milliseconds()/10),2)},SSS:function(){return v(this.milliseconds(),3)},SSSS:function(){return v(this.milliseconds(),3)},Z:function(){var t=-this.zone(),e="+";return 0>t&&(t=-t,e="-"),e+v(C(t/60),2)+":"+v(C(t)%60,2)},ZZ:function(){var t=-this.zone(),e="+";return 0>t&&(t=-t,e="-"),e+v(C(t/60),2)+v(C(t)%60,2)},z:function(){return this.zoneAbbr()},zz:function(){return this.zoneName()},X:function(){return this.unix()},Q:function(){return this.quarter()}},ui=["months","monthsShort","weekdays","weekdaysShort","weekdaysMin"];li.length;)be=li.pop(),pi[be+"o"]=l(pi[be],be);for(;ci.length;)be=ci.pop(),pi[be+be]=d(pi[be],2);for(pi.DDDD=d(pi.DDD,3),f(c.prototype,{set:function(t){var e,i;for(i in t)e=t[i],"function"==typeof e?this[i]=e:this["_"+i]=e},_months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),months:function(t){return this._months[t.month()]},_monthsShort:"Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),monthsShort:function(t){return this._monthsShort[t.month()]},monthsParse:function(t){var e,i,s;for(this._monthsParse||(this._monthsParse=[]),e=0;12>e;e++)if(this._monthsParse[e]||(i=ve.utc([2e3,e]),s="^"+this.months(i,"")+"|^"+this.monthsShort(i,""),this._monthsParse[e]=new RegExp(s.replace(".",""),"i")),this._monthsParse[e].test(t))return e},_weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),weekdays:function(t){return this._weekdays[t.day()]},_weekdaysShort:"Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),weekdaysShort:function(t){return this._weekdaysShort[t.day()]},_weekdaysMin:"Su_Mo_Tu_We_Th_Fr_Sa".split("_"),weekdaysMin:function(t){return this._weekdaysMin[t.day()]},weekdaysParse:function(t){var e,i,s;for(this._weekdaysParse||(this._weekdaysParse=[]),e=0;7>e;e++)if(this._weekdaysParse[e]||(i=ve([2e3,1]).day(e),s="^"+this.weekdays(i,"")+"|^"+this.weekdaysShort(i,"")+"|^"+this.weekdaysMin(i,""),this._weekdaysParse[e]=new RegExp(s.replace(".",""),"i")),this._weekdaysParse[e].test(t))return e},_longDateFormat:{LT:"h:mm A",L:"MM/DD/YYYY",LL:"MMMM D YYYY",LLL:"MMMM D YYYY LT",LLLL:"dddd, MMMM D YYYY LT"},longDateFormat:function(t){var e=this._longDateFormat[t];return!e&&this._longDateFormat[t.toUpperCase()]&&(e=this._longDateFormat[t.toUpperCase()].replace(/MMMM|MM|DD|dddd/g,function(t){return t.slice(1)}),this._longDateFormat[t]=e),e},isPM:function(t){return"p"===(t+"").toLowerCase().charAt(0)},_meridiemParse:/[ap]\.?m?\.?/i,meridiem:function(t,e,i){return t>11?i?"pm":"PM":i?"am":"AM"},_calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},calendar:function(t,e){var i=this._calendar[t];return"function"==typeof i?i.apply(e):i},_relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},relativeTime:function(t,e,i,s){var o=this._relativeTime[i];return"function"==typeof o?o(t,e,i,s):o.replace(/%d/i,t)},pastFuture:function(t,e){var i=this._relativeTime[t>0?"future":"past"];return"function"==typeof i?i(e):i.replace(/%s/i,e)},ordinal:function(t){return this._ordinal.replace("%d",t)},_ordinal:"%d",preparse:function(t){return t},postformat:function(t){return t},week:function(t){return re(t,this._week.dow,this._week.doy).week},_week:{dow:0,doy:6},_invalidDate:"Invalid date",invalidDate:function(){return this._invalidDate}}),ve=function(t,e,i,s){var o;return"boolean"==typeof i&&(s=i,i=n),o={},o._isAMomentObject=!0,o._i=t,o._f=e,o._l=i,o._strict=s,o._isUTC=!1,o._pf=a(),he(o)},ve.suppressDeprecationWarnings=!1,ve.createFromInputFallback=h("moment construction falls back to js Date. This is discouraged and will be removed in upcoming major release. Please refer to https://github.com/moment/moment/issues/1407 for more info.",function(t){t._d=new Date(t._i)}),ve.min=function(){var t=[].slice.call(arguments,0);return de("isBefore",t)},ve.max=function(){var t=[].slice.call(arguments,0);return de("isAfter",t)},ve.utc=function(t,e,i,s){var o;return"boolean"==typeof i&&(s=i,i=n),o={},o._isAMomentObject=!0,o._useUTC=!0,o._isUTC=!0,o._l=i,o._i=t,o._f=e,o._strict=s,o._pf=a(),he(o).utc()},ve.unix=function(t){return ve(1e3*t)},ve.duration=function(t,e){var i,s,o,n=t,r=null;return ve.isDuration(t)?n={ms:t._milliseconds,d:t._days,M:t._months}:"number"==typeof t?(n={},e?n[e]=t:n.milliseconds=t):(r=Ae.exec(t))?(i="-"===r[1]?-1:1,n={y:0,d:C(r[Ce])*i,h:C(r[Ee])*i,m:C(r[De])*i,s:C(r[Te])*i,ms:C(r[Oe])*i}):(r=ze.exec(t))&&(i="-"===r[1]?-1:1,o=function(t){var e=t&&parseFloat(t.replace(",","."));return(isNaN(e)?0:e)*i},n={y:o(r[2]),M:o(r[3]),d:o(r[4]),h:o(r[5]),m:o(r[6]),s:o(r[7]),w:o(r[8])}),s=new u(n),ve.isDuration(t)&&t.hasOwnProperty("_lang")&&(s._lang=t._lang),s -},ve.version=_e,ve.defaultFormat=ei,ve.ISO_8601=function(){},ve.momentProperties=ke,ve.updateOffset=function(){},ve.relativeTimeThreshold=function(t,e){return di[t]===n?!1:(di[t]=e,!0)},ve.lang=function(t,e){var i;return t?(e?A(N(t),e):null===e?(z(t),t="en"):Le[t]||P(t),i=ve.duration.fn._lang=ve.fn._lang=P(t),i._abbr):ve.fn._lang._abbr},ve.langData=function(t){return t&&t._lang&&t._lang._abbr&&(t=t._lang._abbr),P(t)},ve.isMoment=function(t){return t instanceof p||null!=t&&t.hasOwnProperty("_isAMomentObject")},ve.isDuration=function(t){return t instanceof u},be=ui.length-1;be>=0;--be)M(ui[be]);ve.normalizeUnits=function(t){return w(t)},ve.invalid=function(t){var e=ve.utc(0/0);return null!=t?f(e._pf,t):e._pf.userInvalidated=!0,e},ve.parseZone=function(){return ve.apply(null,arguments).parseZone()},ve.parseTwoDigitYear=function(t){return C(t)+(C(t)>68?1900:2e3)},f(ve.fn=p.prototype,{clone:function(){return ve(this)},valueOf:function(){return+this._d+6e4*(this._offset||0)},unix:function(){return Math.floor(+this/1e3)},toString:function(){return this.clone().lang("en").format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ")},toDate:function(){return this._offset?new Date(+this):this._d},toISOString:function(){var t=ve(this).utc();return 00:!1},parsingFlags:function(){return f({},this._pf)},invalidAt:function(){return this._pf.overflow},utc:function(){return this.zone(0)},local:function(){return this.zone(0),this._isUTC=!1,this},format:function(t){var e=H(this,t||ve.defaultFormat);return this.lang().postformat(e)},add:function(t,e){var i;return i="string"==typeof t&&"string"==typeof e?ve.duration(isNaN(+e)?+t:+e,isNaN(+e)?e:t):"string"==typeof t?ve.duration(+e,t):ve.duration(t,e),y(this,i,1),this},subtract:function(t,e){var i;return i="string"==typeof t&&"string"==typeof e?ve.duration(isNaN(+e)?+t:+e,isNaN(+e)?e:t):"string"==typeof t?ve.duration(+e,t):ve.duration(t,e),y(this,i,-1),this},diff:function(t,e,i){var s,o,n=I(t,this),r=6e4*(this.zone()-n.zone());return e=w(e),"year"===e||"month"===e?(s=432e5*(this.daysInMonth()+n.daysInMonth()),o=12*(this.year()-n.year())+(this.month()-n.month()),o+=(this-ve(this).startOf("month")-(n-ve(n).startOf("month")))/s,o-=6e4*(this.zone()-ve(this).startOf("month").zone()-(n.zone()-ve(n).startOf("month").zone()))/s,"year"===e&&(o/=12)):(s=this-n,o="second"===e?s/1e3:"minute"===e?s/6e4:"hour"===e?s/36e5:"day"===e?(s-r)/864e5:"week"===e?(s-r)/6048e5:s),i?o:g(o)},from:function(t,e){return ve.duration(this.diff(t)).lang(this.lang()._abbr).humanize(!e)},fromNow:function(t){return this.from(ve(),t)},calendar:function(t){var e=t||ve(),i=I(e,this).startOf("day"),s=this.diff(i,"days",!0),o=-6>s?"sameElse":-1>s?"lastWeek":0>s?"lastDay":1>s?"sameDay":2>s?"nextDay":7>s?"nextWeek":"sameElse";return this.format(this.lang().calendar(o,this))},isLeapYear:function(){return O(this.year())},isDST:function(){return this.zone()+ve(t).startOf(e)},isBefore:function(t,e){return e="undefined"!=typeof e?e:"millisecond",+this.clone().startOf(e)<+ve(t).startOf(e)},isSame:function(t,e){return e=e||"ms",+this.clone().startOf(e)===+I(t,this).startOf(e)},min:h("moment().min is deprecated, use moment.min instead. https://github.com/moment/moment/issues/1548",function(t){return t=ve.apply(null,arguments),this>t?this:t}),max:h("moment().max is deprecated, use moment.max instead. https://github.com/moment/moment/issues/1548",function(t){return t=ve.apply(null,arguments),t>this?this:t}),zone:function(t,e){var i=this._offset||0;return null==t?this._isUTC?i:this._d.getTimezoneOffset():("string"==typeof t&&(t=W(t)),Math.abs(t)<16&&(t=60*t),this._offset=t,this._isUTC=!0,i!==t&&(!e||this._changeInProgress?y(this,ve.duration(i-t,"m"),1,!1):this._changeInProgress||(this._changeInProgress=!0,ve.updateOffset(this,!0),this._changeInProgress=null)),this)},zoneAbbr:function(){return this._isUTC?"UTC":""},zoneName:function(){return this._isUTC?"Coordinated Universal Time":""},parseZone:function(){return this._tzm?this.zone(this._tzm):"string"==typeof this._i&&this.zone(this._i),this},hasAlignedHourOffset:function(t){return t=t?ve(t).zone():0,(this.zone()-t)%60===0},daysInMonth:function(){return E(this.year(),this.month())},dayOfYear:function(t){var e=we((ve(this).startOf("day")-ve(this).startOf("year"))/864e5)+1;return null==t?e:this.add("d",t-e)},quarter:function(t){return null==t?Math.ceil((this.month()+1)/3):this.month(3*(t-1)+this.month()%3)},weekYear:function(t){var e=re(this,this.lang()._week.dow,this.lang()._week.doy).year;return null==t?e:this.add("y",t-e)},isoWeekYear:function(t){var e=re(this,1,4).year;return null==t?e:this.add("y",t-e)},week:function(t){var e=this.lang().week(this);return null==t?e:this.add("d",7*(t-e))},isoWeek:function(t){var e=re(this,1,4).week;return null==t?e:this.add("d",7*(t-e))},weekday:function(t){var e=(this.day()+7-this.lang()._week.dow)%7;return null==t?e:this.add("d",t-e)},isoWeekday:function(t){return null==t?this.day()||7:this.day(this.day()%7?t:t-7)},isoWeeksInYear:function(){return D(this.year(),1,4)},weeksInYear:function(){var t=this._lang._week;return D(this.year(),t.dow,t.doy)},get:function(t){return t=w(t),this[t]()},set:function(t,e){return t=w(t),"function"==typeof this[t]&&this[t](e),this},lang:function(t){return t===n?this._lang:(this._lang=P(t),this)}}),ve.fn.millisecond=ve.fn.milliseconds=ue("Milliseconds",!1),ve.fn.second=ve.fn.seconds=ue("Seconds",!1),ve.fn.minute=ve.fn.minutes=ue("Minutes",!1),ve.fn.hour=ve.fn.hours=ue("Hours",!0),ve.fn.date=ue("Date",!0),ve.fn.dates=h("dates accessor is deprecated. Use date instead.",ue("Date",!0)),ve.fn.year=ue("FullYear",!0),ve.fn.years=h("years accessor is deprecated. Use year instead.",ue("FullYear",!0)),ve.fn.days=ve.fn.day,ve.fn.months=ve.fn.month,ve.fn.weeks=ve.fn.week,ve.fn.isoWeeks=ve.fn.isoWeek,ve.fn.quarters=ve.fn.quarter,ve.fn.toJSON=ve.fn.toISOString,f(ve.duration.fn=u.prototype,{_bubble:function(){var t,e,i,s,o=this._milliseconds,n=this._days,r=this._months,a=this._data;a.milliseconds=o%1e3,t=g(o/1e3),a.seconds=t%60,e=g(t/60),a.minutes=e%60,i=g(e/60),a.hours=i%24,n+=g(i/24),a.days=n%30,r+=g(n/30),a.months=r%12,s=g(r/12),a.years=s},weeks:function(){return g(this.days()/7)},valueOf:function(){return this._milliseconds+864e5*this._days+this._months%12*2592e6+31536e6*C(this._months/12)},humanize:function(t){var e=+this,i=ne(e,!t,this.lang());return t&&(i=this.lang().pastFuture(e,i)),this.lang().postformat(i)},add:function(t,e){var i=ve.duration(t,e);return this._milliseconds+=i._milliseconds,this._days+=i._days,this._months+=i._months,this._bubble(),this},subtract:function(t,e){var i=ve.duration(t,e);return this._milliseconds-=i._milliseconds,this._days-=i._days,this._months-=i._months,this._bubble(),this},get:function(t){return t=w(t),this[t.toLowerCase()+"s"]()},as:function(t){return t=w(t),this["as"+t.charAt(0).toUpperCase()+t.slice(1)+"s"]()},lang:ve.fn.lang,toIsoString:function(){var t=Math.abs(this.years()),e=Math.abs(this.months()),i=Math.abs(this.days()),s=Math.abs(this.hours()),o=Math.abs(this.minutes()),n=Math.abs(this.seconds()+this.milliseconds()/1e3);return this.asSeconds()?(this.asSeconds()<0?"-":"")+"P"+(t?t+"Y":"")+(e?e+"M":"")+(i?i+"D":"")+(s||o||n?"T":"")+(s?s+"H":"")+(o?o+"M":"")+(n?n+"S":""):"P0D"}});for(be in ni)ni.hasOwnProperty(be)&&(me(be,ni[be]),fe(be.toLowerCase()));me("Weeks",6048e5),ve.duration.fn.asMonths=function(){return(+this-31536e6*this.years())/2592e6+12*this.years()},ve.lang("en",{ordinal:function(t){var e=t%10,i=1===C(t%100/10)?"th":1===e?"st":2===e?"nd":3===e?"rd":"th";return t+i}}),Ne?o.exports=ve:(s=function(t,e,i){return i.config&&i.config()&&i.config().noGlobal===!0&&(xe.moment=ye),ve}.call(e,i,e,o),!(s!==n&&(o.exports=s)),ge(!0))}).call(this)}).call(e,function(){return this}(),i(61)(t))},function(t,e){e.startWithClustering=function(){this.clusterToFit(this.constants.clustering.initialMaxNodes,!0),this.updateLabels(),this.stabilize&&this._stabilize(),this.start()},e.clusterToFit=function(t,e){for(var i=this.nodeIndices.length,s=50,o=0;i>t&&s>o;)o%3==0?(this.forceAggregateHubs(!0),this.normalizeClusterLevels()):this.increaseClusterLevel(),i=this.nodeIndices.length,o+=1;o>0&&1==e&&this.repositionNodes(),this._updateCalculationNodes()},e.openCluster=function(t){var e=this.moving;if(t.clusterSize>this.constants.clustering.sectorThreshold&&this._nodeInActiveArea(t)&&("default"!=this._sector()||1!=this.nodeIndices.length)){this._addSector(t);for(var i=0;this.nodeIndices.lengthi;)this.decreaseClusterLevel(),i+=1}else this._expandClusterNode(t,!1,!0),this._updateNodeIndexList(),this._updateDynamicEdges(),this._updateCalculationNodes(),this.updateLabels();this.moving!=e&&this.start()},e.updateClustersDefault=function(){1==this.constants.clustering.enabled&&this.updateClusters(0,!1,!1)},e.increaseClusterLevel=function(){this.updateClusters(-1,!1,!0)},e.decreaseClusterLevel=function(){this.updateClusters(1,!1,!0)},e.updateClusters=function(t,e,i,s){var o=this.moving,n=this.nodeIndices.length;this.previousScale>this.scale&&0==t&&this._collapseSector(),this.previousScale>this.scale||-1==t?this._formClusters(i):(this.previousScalethis.scale||-1==t)&&(this._aggregateHubs(i),this._updateNodeIndexList()),(this.previousScale>this.scale||-1==t)&&(this.handleChains(),this._updateNodeIndexList()),this.previousScale=this.scale,this._updateDynamicEdges(),this.updateLabels(),this.nodeIndices.lengththis.constants.clustering.chainThreshold&&this._reduceAmountOfChains(1-this.constants.clustering.chainThreshold/t)},e._aggregateHubs=function(t){this._getHubSize(),this._formClustersByHub(t,!1)},e.forceAggregateHubs=function(t){var e=this.moving,i=this.nodeIndices.length;this._aggregateHubs(!0),this._updateNodeIndexList(),this._updateDynamicEdges(),this.updateLabels(),this.nodeIndices.length!=i&&(this.clusterSession+=1),(0==t||void 0===t)&&this.moving!=e&&this.start()},e._openClustersBySize=function(){for(var t in this.nodes)if(this.nodes.hasOwnProperty(t)){var e=this.nodes[t];1==e.inView()&&(e.width*this.scale>this.constants.clustering.screenSizeThreshold*this.frame.canvas.clientWidth||e.height*this.scale>this.constants.clustering.screenSizeThreshold*this.frame.canvas.clientHeight)&&this.openCluster(e)}},e._openClusters=function(t,e){for(var i=0;i1&&(t.clusterSizei)){var r=n.from,a=n.to;n.to.options.mass>n.from.options.mass&&(r=n.to,a=n.from),1==a.dynamicEdgesLength?this._addToCluster(r,a,!1):1==r.dynamicEdgesLength&&this._addToCluster(a,r,!1)}}},e._forceClustersByZoom=function(){for(var t in this.nodes)if(this.nodes.hasOwnProperty(t)){var e=this.nodes[t];if(1==e.dynamicEdgesLength&&0!=e.dynamicEdges.length){var i=e.dynamicEdges[0],s=i.toId==e.id?this.nodes[i.fromId]:this.nodes[i.toId];e.id!=s.id&&(s.options.mass>e.options.mass?this._addToCluster(s,e,!0):this._addToCluster(e,s,!0))}}},e._clusterToSmallestNeighbour=function(t){for(var e=-1,i=null,s=0;so.clusterSessions.length&&(e=o.clusterSessions.length,i=o)}null!=o&&void 0!==this.nodes[o.id]&&this._addToCluster(o,t,!0)},e._formClustersByHub=function(t,e){for(var i in this.nodes)this.nodes.hasOwnProperty(i)&&this._formClusterFromHub(this.nodes[i],t,e)},e._formClusterFromHub=function(t,e,i,s){if(void 0===s&&(s=0),t.dynamicEdgesLength>=this.hubThreshold&&0==i||t.dynamicEdgesLength==this.hubThreshold&&1==i){for(var o,n,r,a=this.constants.clustering.clusterEdgeThreshold/this.scale,h=!1,d=[],l=t.dynamicEdges.length,c=0;l>c;c++)d.push(t.dynamicEdges[c].id);if(0==e)for(h=!1,c=0;l>c;c++){var p=this.edges[d[c]];if(void 0!==p&&p.connected&&p.toId!=p.fromId&&(o=p.to.x-p.from.x,n=p.to.y-p.from.y,r=Math.sqrt(o*o+n*n),a>r)){h=!0;break}}if(!e&&h||e)for(c=0;l>c;c++)if(p=this.edges[d[c]],void 0!==p){var u=this.nodes[p.fromId==t.id?p.toId:p.fromId];u.dynamicEdges.length<=this.hubThreshold+s&&u.id!=t.id&&this._addToCluster(t,u,e)}}},e._addToCluster=function(t,e,i){t.containedNodes[e.id]=e;for(var s=0;s1)for(var s=0;s1&&(e.label="[".concat(String(e.clusterSize),"]"))}for(t in this.nodes)this.nodes.hasOwnProperty(t)&&(e=this.nodes[t],1==e.clusterSize&&(e.label=void 0!==e.originalLabel?e.originalLabel:String(e.id)))},e.normalizeClusterLevels=function(){var t,e=0,i=1e9,s=0;for(t in this.nodes)this.nodes.hasOwnProperty(t)&&(s=this.nodes[t].clusterSessions.length,s>e&&(e=s),i>s&&(i=s));if(e-i>this.constants.clustering.clusterLevelDifference){var o=this.nodeIndices.length,n=e-this.constants.clustering.clusterLevelDifference;for(t in this.nodes)this.nodes.hasOwnProperty(t)&&this.nodes[t].clusterSessions.lengths&&(s=n.dynamicEdgesLength),t+=n.dynamicEdgesLength,e+=Math.pow(n.dynamicEdgesLength,2),i+=1}t/=i,e/=i;var r=e-Math.pow(t,2),a=Math.sqrt(r);this.hubThreshold=Math.floor(t+2*a),this.hubThreshold>s&&(this.hubThreshold=s)},e._reduceAmountOfChains=function(t){this.hubThreshold=2;var e=Math.floor(this.nodeIndices.length*t);for(var i in this.nodes)this.nodes.hasOwnProperty(i)&&2==this.nodes[i].dynamicEdgesLength&&this.nodes[i].dynamicEdges.length>=2&&e>0&&(this._formClusterFromHub(this.nodes[i],!0,!0,1),e-=1)},e._getChainFraction=function(){var t=0,e=0;for(var i in this.nodes)this.nodes.hasOwnProperty(i)&&(2==this.nodes[i].dynamicEdgesLength&&this.nodes[i].dynamicEdges.length>=2&&(t+=1),e+=1);return t/e}},function(t,e,i){var s=i(2);e._putDataInSector=function(){this.sectors.active[this._sector()].nodes=this.nodes,this.sectors.active[this._sector()].edges=this.edges,this.sectors.active[this._sector()].nodeIndices=this.nodeIndices},e._switchToSector=function(t,e){void 0===e||"active"==e?this._switchToActiveSector(t):this._switchToFrozenSector(t)},e._switchToActiveSector=function(t){this.nodeIndices=this.sectors.active[t].nodeIndices,this.nodes=this.sectors.active[t].nodes,this.edges=this.sectors.active[t].edges},e._switchToSupportSector=function(){this.nodeIndices=this.sectors.support.nodeIndices,this.nodes=this.sectors.support.nodes,this.edges=this.sectors.support.edges},e._switchToFrozenSector=function(t){this.nodeIndices=this.sectors.frozen[t].nodeIndices,this.nodes=this.sectors.frozen[t].nodes,this.edges=this.sectors.frozen[t].edges},e._loadLatestSector=function(){this._switchToSector(this._sector())},e._sector=function(){return this.activeSector[this.activeSector.length-1]},e._previousSector=function(){if(this.activeSector.length>1)return this.activeSector[this.activeSector.length-2];throw new TypeError("there are not enough sectors in the this.activeSector array.")},e._setActiveSector=function(t){this.activeSector.push(t)},e._forgetLastSector=function(){this.activeSector.pop()},e._createNewSector=function(t){this.sectors.active[t]={nodes:{},edges:{},nodeIndices:[],formationScale:this.scale,drawingNode:void 0},this.sectors.active[t].drawingNode=new Node({id:t,color:{background:"#eaefef",border:"495c5e"}},{},{},this.constants),this.sectors.active[t].drawingNode.clusterSize=2},e._deleteActiveSector=function(t){delete this.sectors.active[t]},e._deleteFrozenSector=function(t){delete this.sectors.frozen[t]},e._freezeSector=function(t){this.sectors.frozen[t]=this.sectors.active[t],this._deleteActiveSector(t)},e._activateSector=function(t){this.sectors.active[t]=this.sectors.frozen[t],this._deleteFrozenSector(t)},e._mergeThisWithFrozen=function(t){for(var e in this.nodes)this.nodes.hasOwnProperty(e)&&(this.sectors.frozen[t].nodes[e]=this.nodes[e]);for(var i in this.edges)this.edges.hasOwnProperty(i)&&(this.sectors.frozen[t].edges[i]=this.edges[i]);for(var s=0;s1?this[t](s[0],s[1]):this[t](e)}this._loadLatestSector()},e._doInSupportSector=function(t,e){if(void 0===e)this._switchToSupportSector(),this[t]();else{this._switchToSupportSector();var i=Array.prototype.splice.call(arguments,1);i.length>1?this[t](i[0],i[1]):this[t](e)}this._loadLatestSector()},e._doInAllFrozenSectors=function(t,e){if(void 0===e)for(var i in this.sectors.frozen)this.sectors.frozen.hasOwnProperty(i)&&(this._switchToFrozenSector(i),this[t]());else for(var i in this.sectors.frozen)if(this.sectors.frozen.hasOwnProperty(i)){this._switchToFrozenSector(i);var s=Array.prototype.splice.call(arguments,1);s.length>1?this[t](s[0],s[1]):this[t](e)}this._loadLatestSector()},e._doInAllSectors=function(t,e){var i=Array.prototype.splice.call(arguments,1);void 0===e?(this._doInAllActiveSectors(t),this._doInAllFrozenSectors(t)):i.length>1?(this._doInAllActiveSectors(t,i[0],i[1]),this._doInAllFrozenSectors(t,i[0],i[1])):(this._doInAllActiveSectors(t,e),this._doInAllFrozenSectors(t,e))},e._clearNodeIndexList=function(){var t=this._sector();this.sectors.active[t].nodeIndices=[],this.nodeIndices=this.sectors.active[t].nodeIndices},e._drawSectorNodes=function(t,e){var i,s=1e9,o=-1e9,n=1e9,r=-1e9;for(var a in this.sectors[e])if(this.sectors[e].hasOwnProperty(a)&&void 0!==this.sectors[e][a].drawingNode){this._switchToSector(a,e),s=1e9,o=-1e9,n=1e9,r=-1e9;for(var h in this.nodes)this.nodes.hasOwnProperty(h)&&(i=this.nodes[h],i.resize(t),n>i.x-.5*i.width&&(n=i.x-.5*i.width),ri.y-.5*i.height&&(s=i.y-.5*i.height),o0?this.nodes[i[i.length-1]]:null},e._getEdgesOverlappingWith=function(t,e){var i=this.edges;for(var s in i)i.hasOwnProperty(s)&&i[s].isOverlappingWith(t)&&e.push(s)},e._getAllEdgesOverlappingWith=function(t){var e=[];return this._doInAllActiveSectors("_getEdgesOverlappingWith",t,e),e},e._getEdgeAt=function(t){var e=this._pointerToPositionObject(t),i=this._getAllEdgesOverlappingWith(e);return i.length>0?this.edges[i[i.length-1]]:null},e._addToSelection=function(t){t instanceof s?this.selectionObj.nodes[t.id]=t:this.selectionObj.edges[t.id]=t},e._addToHover=function(t){t instanceof s?this.hoverObj.nodes[t.id]=t:this.hoverObj.edges[t.id]=t},e._removeFromSelection=function(t){t instanceof s?delete this.selectionObj.nodes[t.id]:delete this.selectionObj.edges[t.id]},e._unselectAll=function(t){void 0===t&&(t=!1);for(var e in this.selectionObj.nodes)this.selectionObj.nodes.hasOwnProperty(e)&&this.selectionObj.nodes[e].unselect();for(var i in this.selectionObj.edges)this.selectionObj.edges.hasOwnProperty(i)&&this.selectionObj.edges[i].unselect();this.selectionObj={nodes:{},edges:{}},0==t&&this.emit("select",this.getSelection())},e._unselectClusters=function(t){void 0===t&&(t=!1);for(var e in this.selectionObj.nodes)this.selectionObj.nodes.hasOwnProperty(e)&&this.selectionObj.nodes[e].clusterSize>1&&(this.selectionObj.nodes[e].unselect(),this._removeFromSelection(this.selectionObj.nodes[e]));0==t&&this.emit("select",this.getSelection())},e._getSelectedNodeCount=function(){var t=0;for(var e in this.selectionObj.nodes)this.selectionObj.nodes.hasOwnProperty(e)&&(t+=1);return t},e._getSelectedNode=function(){for(var t in this.selectionObj.nodes)if(this.selectionObj.nodes.hasOwnProperty(t))return this.selectionObj.nodes[t];return null},e._getSelectedEdge=function(){for(var t in this.selectionObj.edges)if(this.selectionObj.edges.hasOwnProperty(t))return this.selectionObj.edges[t];return null},e._getSelectedEdgeCount=function(){var t=0;for(var e in this.selectionObj.edges)this.selectionObj.edges.hasOwnProperty(e)&&(t+=1);return t},e._getSelectedObjectCount=function(){var t=0;for(var e in this.selectionObj.nodes)this.selectionObj.nodes.hasOwnProperty(e)&&(t+=1);for(var i in this.selectionObj.edges)this.selectionObj.edges.hasOwnProperty(i)&&(t+=1);return t},e._selectionIsEmpty=function(){for(var t in this.selectionObj.nodes)if(this.selectionObj.nodes.hasOwnProperty(t))return!1;for(var e in this.selectionObj.edges)if(this.selectionObj.edges.hasOwnProperty(e))return!1;return!0},e._clusterInSelection=function(){for(var t in this.selectionObj.nodes)if(this.selectionObj.nodes.hasOwnProperty(t)&&this.selectionObj.nodes[t].clusterSize>1)return!0;return!1},e._selectConnectedEdges=function(t){for(var e=0;ee;e++){s=t[e];var o=this.nodes[s];if(!o)throw new RangeError('Node with id "'+s+'" not found');this._selectObject(o,!0,!0)}console.log("setSelection is deprecated. Please use selectNodes instead."),this.redraw()},e.selectNodes=function(t,e){var i,s,o;if(!t||void 0==t.length)throw"Selection must be an array with ids";for(this._unselectAll(!0),i=0,s=t.length;s>i;i++){o=t[i]; -var n=this.nodes[o];if(!n)throw new RangeError('Node with id "'+o+'" not found');this._selectObject(n,!0,!0,e)}this.redraw()},e.selectEdges=function(t){var e,i,s;if(!t||void 0==t.length)throw"Selection must be an array with ids";for(this._unselectAll(!0),e=0,i=t.length;i>e;e++){s=t[e];var o=this.edges[s];if(!o)throw new RangeError('Edge with id "'+s+'" not found');this._selectObject(o,!0,!0,highlightEdges)}this.redraw()},e._updateSelection=function(){for(var t in this.selectionObj.nodes)this.selectionObj.nodes.hasOwnProperty(t)&&(this.nodes.hasOwnProperty(t)||delete this.selectionObj.nodes[t]);for(var e in this.selectionObj.edges)this.selectionObj.edges.hasOwnProperty(e)&&(this.edges.hasOwnProperty(e)||delete this.selectionObj.edges[e])}},function(t,e,i){var s=i(2),o=i(36),n=i(33);e._clearManipulatorBar=function(){for(;this.manipulationDiv.hasChildNodes();)this.manipulationDiv.removeChild(this.manipulationDiv.firstChild)},e._restoreOverloadedFunctions=function(){for(var t in this.cachedFunctions)this.cachedFunctions.hasOwnProperty(t)&&(this[t]=this.cachedFunctions[t])},e._toggleEditMode=function(){this.editMode=!this.editMode;var t=document.getElementById("network-manipulationDiv"),e=document.getElementById("network-manipulation-closeDiv"),i=document.getElementById("network-manipulation-editMode");1==this.editMode?(t.style.display="block",e.style.display="block",i.style.display="none",e.onclick=this._toggleEditMode.bind(this)):(t.style.display="none",e.style.display="none",i.style.display="block",e.onclick=null),this._createManipulatorBar()},e._createManipulatorBar=function(){if(this.boundFunction&&this.off("select",this.boundFunction),void 0!==this.edgeBeingEdited&&(this.edgeBeingEdited._disableControlNodes(),this.edgeBeingEdited=void 0,this.selectedControlNode=null,this.controlNodesActive=!1),this._restoreOverloadedFunctions(),this.freezeSimulation=!1,this.blockConnectingEdgeSelection=!1,this.forceAppendSelection=!1,1==this.editMode){for(;this.manipulationDiv.hasChildNodes();)this.manipulationDiv.removeChild(this.manipulationDiv.firstChild);this.manipulationDiv.innerHTML=""+this.constants.labels.add+"
"+this.constants.labels.link+"",1==this._getSelectedNodeCount()&&this.triggerFunctions.edit?this.manipulationDiv.innerHTML+="
"+this.constants.labels.editNode+"":1==this._getSelectedEdgeCount()&&0==this._getSelectedNodeCount()&&(this.manipulationDiv.innerHTML+="
"+this.constants.labels.editEdge+""),0==this._selectionIsEmpty()&&(this.manipulationDiv.innerHTML+="
"+this.constants.labels.del+"");var t=document.getElementById("network-manipulate-addNode");t.onclick=this._createAddNodeToolbar.bind(this);var e=document.getElementById("network-manipulate-connectNode");if(e.onclick=this._createAddEdgeToolbar.bind(this),1==this._getSelectedNodeCount()&&this.triggerFunctions.edit){var i=document.getElementById("network-manipulate-editNode");i.onclick=this._editNode.bind(this)}else if(1==this._getSelectedEdgeCount()&&0==this._getSelectedNodeCount()){var i=document.getElementById("network-manipulate-editEdge");i.onclick=this._createEditEdgeToolbar.bind(this)}if(0==this._selectionIsEmpty()){var s=document.getElementById("network-manipulate-delete");s.onclick=this._deleteSelected.bind(this)}var o=document.getElementById("network-manipulation-closeDiv");o.onclick=this._toggleEditMode.bind(this),this.boundFunction=this._createManipulatorBar.bind(this),this.on("select",this.boundFunction)}else{this.editModeDiv.innerHTML=""+this.constants.labels.edit+"";var n=document.getElementById("network-manipulate-editModeButton");n.onclick=this._toggleEditMode.bind(this)}},e._createAddNodeToolbar=function(){this._clearManipulatorBar(),this.boundFunction&&this.off("select",this.boundFunction),this.manipulationDiv.innerHTML=""+this.constants.labels.back+"
"+this.constants.labels.addDescription+"";var t=document.getElementById("network-manipulate-back");t.onclick=this._createManipulatorBar.bind(this),this.boundFunction=this._addNode.bind(this),this.on("select",this.boundFunction)},e._createAddEdgeToolbar=function(){this._clearManipulatorBar(),this._unselectAll(!0),this.freezeSimulation=!0,this.boundFunction&&this.off("select",this.boundFunction),this._unselectAll(),this.forceAppendSelection=!1,this.blockConnectingEdgeSelection=!0,this.manipulationDiv.innerHTML=""+this.constants.labels.back+"
"+this.constants.labels.linkDescription+"";var t=document.getElementById("network-manipulate-back");t.onclick=this._createManipulatorBar.bind(this),this.boundFunction=this._handleConnect.bind(this),this.on("select",this.boundFunction),this.cachedFunctions._handleTouch=this._handleTouch,this.cachedFunctions._handleOnRelease=this._handleOnRelease,this._handleTouch=this._handleConnect,this._handleOnRelease=this._finishConnect,this._redraw()},e._createEditEdgeToolbar=function(){this._clearManipulatorBar(),this.controlNodesActive=!0,this.boundFunction&&this.off("select",this.boundFunction),this.edgeBeingEdited=this._getSelectedEdge(),this.edgeBeingEdited._enableControlNodes(),this.manipulationDiv.innerHTML=""+this.constants.labels.back+"
"+this.constants.labels.editEdgeDescription+"";var t=document.getElementById("network-manipulate-back");t.onclick=this._createManipulatorBar.bind(this),this.cachedFunctions._handleTouch=this._handleTouch,this.cachedFunctions._handleOnRelease=this._handleOnRelease,this.cachedFunctions._handleTap=this._handleTap,this.cachedFunctions._handleDragStart=this._handleDragStart,this.cachedFunctions._handleOnDrag=this._handleOnDrag,this._handleTouch=this._selectControlNode,this._handleTap=function(){},this._handleOnDrag=this._controlNodeDrag,this._handleDragStart=function(){},this._handleOnRelease=this._releaseControlNode,this._redraw()},e._selectControlNode=function(t){this.edgeBeingEdited.controlNodes.from.unselect(),this.edgeBeingEdited.controlNodes.to.unselect(),this.selectedControlNode=this.edgeBeingEdited._getSelectedControlNode(this._XconvertDOMtoCanvas(t.x),this._YconvertDOMtoCanvas(t.y)),null!==this.selectedControlNode&&(this.selectedControlNode.select(),this.freezeSimulation=!0),this._redraw()},e._controlNodeDrag=function(t){var e=this._getPointer(t.gesture.center);null!==this.selectedControlNode&&void 0!==this.selectedControlNode&&(this.selectedControlNode.x=this._XconvertDOMtoCanvas(e.x),this.selectedControlNode.y=this._YconvertDOMtoCanvas(e.y)),this._redraw()},e._releaseControlNode=function(t){var e=this._getNodeAt(t);null!=e?(1==this.edgeBeingEdited.controlNodes.from.selected&&(this._editEdge(e.id,this.edgeBeingEdited.to.id),this.edgeBeingEdited.controlNodes.from.unselect()),1==this.edgeBeingEdited.controlNodes.to.selected&&(this._editEdge(this.edgeBeingEdited.from.id,e.id),this.edgeBeingEdited.controlNodes.to.unselect())):this.edgeBeingEdited._restoreControlNodes(),this.freezeSimulation=!1,this._redraw()},e._handleConnect=function(t){if(0==this._getSelectedNodeCount()){var e=this._getNodeAt(t);null!=e&&(e.clusterSize>1?alert("Cannot create edges to a cluster."):(this._selectObject(e,!1),this.sectors.support.nodes.targetNode=new o({id:"targetNode"},{},{},this.constants),this.sectors.support.nodes.targetNode.x=e.x,this.sectors.support.nodes.targetNode.y=e.y,this.sectors.support.nodes.targetViaNode=new o({id:"targetViaNode"},{},{},this.constants),this.sectors.support.nodes.targetViaNode.x=e.x,this.sectors.support.nodes.targetViaNode.y=e.y,this.sectors.support.nodes.targetViaNode.parentEdgeId="connectionEdge",this.edges.connectionEdge=new n({id:"connectionEdge",from:e.id,to:this.sectors.support.nodes.targetNode.id},this,this.constants),this.edges.connectionEdge.from=e,this.edges.connectionEdge.connected=!0,this.edges.connectionEdge.smooth=!0,this.edges.connectionEdge.selected=!0,this.edges.connectionEdge.to=this.sectors.support.nodes.targetNode,this.edges.connectionEdge.via=this.sectors.support.nodes.targetViaNode,this.cachedFunctions._handleOnDrag=this._handleOnDrag,this._handleOnDrag=function(t){var e=this._getPointer(t.gesture.center);this.sectors.support.nodes.targetNode.x=this._XconvertDOMtoCanvas(e.x),this.sectors.support.nodes.targetNode.y=this._YconvertDOMtoCanvas(e.y),this.sectors.support.nodes.targetViaNode.x=.5*(this._XconvertDOMtoCanvas(e.x)+this.edges.connectionEdge.from.x),this.sectors.support.nodes.targetViaNode.y=this._YconvertDOMtoCanvas(e.y)},this.moving=!0,this.start()))}},e._finishConnect=function(t){if(1==this._getSelectedNodeCount()){this._handleOnDrag=this.cachedFunctions._handleOnDrag,delete this.cachedFunctions._handleOnDrag;var e=this.edges.connectionEdge.fromId;delete this.edges.connectionEdge,delete this.sectors.support.nodes.targetNode,delete this.sectors.support.nodes.targetViaNode;var i=this._getNodeAt(t);null!=i&&(i.clusterSize>1?alert("Cannot create edges to a cluster."):(this._createEdge(e,i.id),this._createManipulatorBar())),this._unselectAll()}},e._addNode=function(){if(this._selectionIsEmpty()&&1==this.editMode){var t=this._pointerToPositionObject(this.pointerPosition),e={id:s.randomUUID(),x:t.left,y:t.top,label:"new",allowedToMoveX:!0,allowedToMoveY:!0};if(this.triggerFunctions.add)if(2==this.triggerFunctions.add.length){var i=this;this.triggerFunctions.add(e,function(t){i.nodesData.add(t),i._createManipulatorBar(),i.moving=!0,i.start()})}else alert(this.constants.labels.addError),this._createManipulatorBar(),this.moving=!0,this.start();else this.nodesData.add(e),this._createManipulatorBar(),this.moving=!0,this.start()}},e._createEdge=function(t,e){if(1==this.editMode){var i={from:t,to:e};if(this.triggerFunctions.connect)if(2==this.triggerFunctions.connect.length){var s=this;this.triggerFunctions.connect(i,function(t){s.edgesData.add(t),s.moving=!0,s.start()})}else alert(this.constants.labels.linkError),this.moving=!0,this.start();else this.edgesData.add(i),this.moving=!0,this.start()}},e._editEdge=function(t,e){if(1==this.editMode){var i={id:this.edgeBeingEdited.id,from:t,to:e};if(this.triggerFunctions.editEdge)if(2==this.triggerFunctions.editEdge.length){var s=this;this.triggerFunctions.editEdge(i,function(t){s.edgesData.update(t),s.moving=!0,s.start()})}else alert(this.constants.labels.linkError),this.moving=!0,this.start();else this.edgesData.update(i),this.moving=!0,this.start()}},e._editNode=function(){if(this.triggerFunctions.edit&&1==this.editMode){var t=this._getSelectedNode(),e={id:t.id,label:t.label,group:t.options.group,shape:t.options.shape,color:{background:t.options.color.background,border:t.options.color.border,highlight:{background:t.options.color.highlight.background,border:t.options.color.highlight.border}}};if(2==this.triggerFunctions.edit.length){var i=this;this.triggerFunctions.edit(e,function(t){i.nodesData.update(t),i._createManipulatorBar(),i.moving=!0,i.start()})}else alert(this.constants.labels.editError)}else alert(this.constants.labels.editBoundError)},e._deleteSelected=function(){if(!this._selectionIsEmpty()&&1==this.editMode)if(this._clusterInSelection())alert(this.constants.labels.deleteClusterError);else{var t=this.getSelectedNodes(),e=this.getSelectedEdges();if(this.triggerFunctions.del){var i=this,s={nodes:t,edges:e};(this.triggerFunctions.del.length=2)?this.triggerFunctions.del(s,function(t){i.edgesData.remove(t.edges),i.nodesData.remove(t.nodes),i._unselectAll(),i.moving=!0,i.start()}):alert(this.constants.labels.deleteError)}else this.edgesData.remove(e),this.nodesData.remove(t),this._unselectAll(),this.moving=!0,this.start()}}},function(t,e,i){var s=i(2),o=i(40);e._cleanNavigation=function(){var t=document.getElementById("network-navigation_wrapper");null!=t&&this.containerElement.removeChild(t),document.onmouseup=null},e._loadNavigationElements=function(){this._cleanNavigation(),this.navigationDivs={};var t=["up","down","left","right","zoomIn","zoomOut","zoomExtends"],e=["_moveUp","_moveDown","_moveLeft","_moveRight","_zoomIn","_zoomOut","zoomExtent"];this.navigationDivs.wrapper=document.createElement("div"),this.navigationDivs.wrapper.id="network-navigation_wrapper",this.navigationDivs.wrapper.style.position="absolute",this.navigationDivs.wrapper.style.width=this.frame.canvas.clientWidth+"px",this.navigationDivs.wrapper.style.height=this.frame.canvas.clientHeight+"px",this.containerElement.insertBefore(this.navigationDivs.wrapper,this.frame);for(var i=this,s=0;s0){"RL"==this.constants.hierarchicalLayout.direction||"DU"==this.constants.hierarchicalLayout.direction?this.constants.hierarchicalLayout.levelSeparation*=-1:this.constants.hierarchicalLayout.levelSeparation=Math.abs(this.constants.hierarchicalLayout.levelSeparation),"RL"==this.constants.hierarchicalLayout.direction||"LR"==this.constants.hierarchicalLayout.direction?1==this.constants.smoothCurves.enabled&&(this.constants.smoothCurves.type="vertical"):1==this.constants.smoothCurves.enabled&&(this.constants.smoothCurves.type="horizontal");var t,e,i=0,s=!1,o=!1;for(e in this.nodes)this.nodes.hasOwnProperty(e)&&(t=this.nodes[e],-1!=t.level?s=!0:o=!0,is&&(n.xFixed=!1,n.x=i[n.level].minPos,r=!0):n.yFixed&&n.level>s&&(n.yFixed=!1,n.y=i[n.level].minPos,r=!0),1==r&&(i[n.level].minPos+=i[n.level].nodeSpacing,n.edges.length>1&&this._placeBranchNodes(n.edges,n.id,i,n.level))}},e._setLevel=function(t,e,i){for(var s=0;st)&&(o.level=t,e.length>1&&this._setLevel(t+1,o.edges,o.id))}},e._restoreNodes=function(){for(var t in this.nodes)this.nodes.hasOwnProperty(t)&&(this.nodes[t].xFixed=!1,this.nodes[t].yFixed=!1)}},function(t,e,i){function s(){this.constants.smoothCurves.enabled=!this.constants.smoothCurves.enabled;var t=document.getElementById("graph_toggleSmooth");t.style.background=1==this.constants.smoothCurves.enabled?"#A4FF56":"#FF8532",this._configureSmoothCurves(!1)}function o(){for(var t in this.calculationNodes)this.calculationNodes.hasOwnProperty(t)&&(this.calculationNodes[t].vx=0,this.calculationNodes[t].vy=0,this.calculationNodes[t].fx=0,this.calculationNodes[t].fy=0);1==this.constants.hierarchicalLayout.enabled?(this._setupHierarchicalLayout(),a.call(this,"graph_H_nd",1,"physics_hierarchicalRepulsion_nodeDistance"),a.call(this,"graph_H_cg",1,"physics_centralGravity"),a.call(this,"graph_H_sc",1,"physics_springConstant"),a.call(this,"graph_H_sl",1,"physics_springLength"),a.call(this,"graph_H_damp",1,"physics_damping")):this.repositionNodes(),this.moving=!0,this.start()}function n(){var t="No options are required, default values used.",e=[],i=document.getElementById("graph_physicsMethod1"),s=document.getElementById("graph_physicsMethod2");if(1==i.checked){if(this.constants.physics.barnesHut.gravitationalConstant!=this.backupConstants.physics.barnesHut.gravitationalConstant&&e.push("gravitationalConstant: "+this.constants.physics.barnesHut.gravitationalConstant),this.constants.physics.centralGravity!=this.backupConstants.physics.barnesHut.centralGravity&&e.push("centralGravity: "+this.constants.physics.centralGravity),this.constants.physics.springLength!=this.backupConstants.physics.barnesHut.springLength&&e.push("springLength: "+this.constants.physics.springLength),this.constants.physics.springConstant!=this.backupConstants.physics.barnesHut.springConstant&&e.push("springConstant: "+this.constants.physics.springConstant),this.constants.physics.damping!=this.backupConstants.physics.barnesHut.damping&&e.push("damping: "+this.constants.physics.damping),0!=e.length){t="var options = {",t+="physics: {barnesHut: {";for(var o=0;othis.constants.clustering.clusterThreshold&&1==this.constants.clustering.enabled&&this.clusterToFit(this.constants.clustering.reduceToNodes,!1),this._calculateForces())},e._calculateForces=function(){this._calculateGravitationalForces(),this._calculateNodeForces(),this.constants.physics.springConstant>0&&(1==this.constants.smoothCurves.enabled&&1==this.constants.smoothCurves.dynamic?this._calculateSpringForcesWithSupport():1==this.constants.physics.hierarchicalRepulsion.enabled?this._calculateHierarchicalSpringForces():this._calculateSpringForces())},e._updateCalculationNodes=function(){if(1==this.constants.smoothCurves.enabled&&1==this.constants.smoothCurves.dynamic){this.calculationNodes={},this.calculationNodeIndices=[];for(var t in this.nodes)this.nodes.hasOwnProperty(t)&&(this.calculationNodes[t]=this.nodes[t]);var e=this.sectors.support.nodes;for(var i in e)e.hasOwnProperty(i)&&(this.edges.hasOwnProperty(e[i].parentEdgeId)?this.calculationNodes[i]=e[i]:e[i]._setForce(0,0));for(var s in this.calculationNodes)this.calculationNodes.hasOwnProperty(s)&&this.calculationNodeIndices.push(s)}else this.calculationNodes=this.nodes,this.calculationNodeIndices=this.nodeIndices},e._calculateGravitationalForces=function(){var t,e,i,s,o,n=this.calculationNodes,r=this.constants.physics.centralGravity,a=0;for(o=0;oSimulation Mode:Barnes HutRepulsionHierarchical
Options:
',this.containerElement.parentElement.insertBefore(this.physicsConfiguration,this.containerElement),this.optionsDiv=document.createElement("div"),this.optionsDiv.style.fontSize="14px",this.optionsDiv.style.fontFamily="verdana",this.containerElement.parentElement.insertBefore(this.optionsDiv,this.containerElement); +var i=this;this.frame.slide.onmousedown=function(t){i._onMouseDown(t)},this.frame.prev.onclick=function(t){i.prev(t)},this.frame.play.onclick=function(t){i.togglePlay(t)},this.frame.next.onclick=function(t){i.next(t)}}this.onChangeCallback=void 0,this.values=[],this.index=void 0,this.playTimeout=void 0,this.playInterval=1e3,this.playLoop=!0}var o=i(1);s.prototype.prev=function(){var t=this.getIndex();t>0&&(t--,this.setIndex(t))},s.prototype.next=function(){var t=this.getIndex();t0?this.setIndex(0):this.index=void 0},s.prototype.setIndex=function(t){if(!(ts&&(s=0),s>this.values.length-1&&(s=this.values.length-1),s},s.prototype.indexToLeft=function(t){var e=parseFloat(this.frame.bar.style.width)-this.frame.slide.clientWidth-10,i=t/(this.values.length-1)*e,s=i+3;return s},s.prototype._onMouseMove=function(t){var e=t.clientX-this.startClientX,i=this.startSlideX+e,s=this.leftToIndex(i);this.setIndex(s),o.preventDefault()},s.prototype._onMouseUp=function(){this.frame.style.cursor="auto",o.removeEventListener(document,"mousemove",this.onmousemove),o.removeEventListener(document,"mouseup",this.onmouseup),o.preventDefault()},t.exports=s},function(t){function e(t,e,i,s){this._start=0,this._end=0,this._step=1,this.prettyStep=!0,this.precision=5,this._current=0,this.setRange(t,e,i,s)}e.prototype.setRange=function(t,e,i,s){this._start=t?t:0,this._end=e?e:0,this.setStep(i,s)},e.prototype.setStep=function(t,i){void 0===t||0>=t||(void 0!==i&&(this.prettyStep=i),this._step=this.prettyStep===!0?e.calculatePrettyStep(t):t)},e.calculatePrettyStep=function(t){var e=function(t){return Math.log(t)/Math.LN10},i=Math.pow(10,Math.round(e(t))),s=2*Math.pow(10,Math.round(e(t/2))),o=5*Math.pow(10,Math.round(e(t/5))),n=i;return Math.abs(s-t)<=Math.abs(n-t)&&(n=s),Math.abs(o-t)<=Math.abs(n-t)&&(n=o),0>=n&&(n=1),n},e.prototype.getCurrent=function(){return parseFloat(this._current.toPrecision(this.precision))},e.prototype.getStep=function(){return this._step},e.prototype.start=function(){this._current=this._start-this._start%this._step},e.prototype.next=function(){this._current+=this._step},e.prototype.end=function(){return this._current>this._end},t.exports=e},function(t,e,i){function s(t,e,i){for(var n in h.prototype)h.prototype.hasOwnProperty(n)&&!s.prototype.hasOwnProperty(n)&&(s.prototype[n]=h.prototype[n]);if(!(this instanceof s))throw new SyntaxError("Constructor must be called with the new operator");var r=this;this.defaultOptions={start:null,end:null,autoResize:!0,orientation:"bottom",width:null,height:null,maxHeight:null,minHeight:null},this.options=o.deepExtend({},this.defaultOptions),this._create(t),this.components=[],this.body={dom:this.dom,domProps:this.props,emitter:{on:this.on.bind(this),off:this.off.bind(this),emit:this.emit.bind(this)},util:{snap:null,toScreen:r._toScreen.bind(r),toGlobalScreen:r._toGlobalScreen.bind(r),toTime:r._toTime.bind(r),toGlobalTime:r._toGlobalTime.bind(r)}},this.range=new a(this.body),this.components.push(this.range),this.body.range=this.range,this.timeAxis=new d(this.body),this.components.push(this.timeAxis),this.body.util.snap=this.timeAxis.snap.bind(this.timeAxis),this.currentTime=new l(this.body),this.components.push(this.currentTime),this.customTime=new c(this.body),this.components.push(this.customTime),this.itemSet=new p(this.body),this.components.push(this.itemSet),this.itemsData=null,this.groupsData=null,i&&this.setOptions(i),e?this.setItems(e):this.redraw()}var o=(i(46),i(41),i(1)),n=i(3),r=i(4),a=i(15),h=i(42),d=i(27),l=i(19),c=i(20),p=i(24);s.prototype.setOptions=function(t){if(t){var e=["width","height","minHeight","maxHeight","autoResize","start","end","orientation"];o.selectiveExtend(e,this.options,t),this._initAutoResize()}if(this.components.forEach(function(e){e.setOptions(t)}),t&&t.order)throw new Error("Option order is deprecated. There is no replacement for this feature.");this.redraw()},s.prototype.setItems=function(t){var e,i=null==this.itemsData;if(e=t?t instanceof n||t instanceof r?t:new n(t,{type:{start:"Date",end:"Date"}}):null,this.itemsData=e,this.itemSet&&this.itemSet.setItems(e),i&&("start"in this.options||"end"in this.options)){this.fit();var s="start"in this.options?o.convert(this.options.start,"Date"):null,a="end"in this.options?o.convert(this.options.end,"Date"):null;this.setWindow(s,a)}},s.prototype.setGroups=function(t){var e;e=t?t instanceof n||t instanceof r?t:new n(t):null,this.groupsData=e,this.itemSet.setGroups(e)},s.prototype.setSelection=function(t){this.itemSet&&this.itemSet.setSelection(t)},s.prototype.getSelection=function(){return this.itemSet&&this.itemSet.getSelection()||[]},s.prototype.getItemRange=function(){var t=this.itemsData.getDataSet(),e=null,i=null;if(t){var s=t.min("start");e=s?o.convert(s.start,"Date").valueOf():null;var n=t.max("start");n&&(i=o.convert(n.start,"Date").valueOf());var r=t.max("end");r&&(i=null==i?o.convert(r.end,"Date").valueOf():Math.max(i,o.convert(r.end,"Date").valueOf()))}return{min:null!=e?new Date(e):null,max:null!=i?new Date(i):null}},t.exports=s},function(t,e,i){function s(t,e,i,n){for(var r in h.prototype)h.prototype.hasOwnProperty(r)&&!s.prototype.hasOwnProperty(r)&&(s.prototype[r]=h.prototype[r]);var u=this;this.defaultOptions={start:null,end:null,autoResize:!0,orientation:"bottom",width:null,height:null,maxHeight:null,minHeight:null},this.options=o.deepExtend({},this.defaultOptions),this._create(t),this.components=[],this.body={dom:this.dom,domProps:this.props,emitter:{on:this.on.bind(this),off:this.off.bind(this),emit:this.emit.bind(this)},util:{snap:null,toScreen:u._toScreen.bind(u),toGlobalScreen:u._toGlobalScreen.bind(u),toTime:u._toTime.bind(u),toGlobalTime:u._toGlobalTime.bind(u)}},this.range=new a(this.body),this.components.push(this.range),this.body.range=this.range,this.timeAxis=new d(this.body),this.components.push(this.timeAxis),this.body.util.snap=this.timeAxis.snap.bind(this.timeAxis),this.currentTime=new l(this.body),this.components.push(this.currentTime),this.customTime=new c(this.body),this.components.push(this.customTime),this.linegraph=new p(this.body),this.components.push(this.linegraph),this.itemsData=null,this.groupsData=null,i&&this.setOptions(i),n&&this.setGroups(n),e?this.setItems(e):this.redraw()}var o=(i(46),i(41),i(1)),n=i(3),r=i(4),a=i(15),h=i(42),d=i(27),l=i(19),c=i(20),p=i(26);s.prototype.setOptions=function(t){if(t){var e=["width","height","minHeight","maxHeight","autoResize","start","end","orientation"];o.selectiveExtend(e,this.options,t),this._initAutoResize()}if(this.components.forEach(function(e){e.setOptions(t)}),t&&t.order)throw new Error("Option order is deprecated. There is no replacement for this feature.");this.redraw()},s.prototype.setItems=function(t){var e,i=null==this.itemsData;if(e=t?t instanceof n||t instanceof r?t:new n(t,{type:{start:"Date",end:"Date"}}):null,this.itemsData=e,this.linegraph&&this.linegraph.setItems(e),i&&("start"in this.options||"end"in this.options)){this.fit();var s="start"in this.options?o.convert(this.options.start,"Date"):null,a="end"in this.options?o.convert(this.options.end,"Date"):null;this.setWindow(s,a)}},s.prototype.setGroups=function(t){var e;e=t?t instanceof n||t instanceof r?t:new n(t):null,this.groupsData=e,this.linegraph.setGroups(e)},s.prototype.getLegend=function(t,e,i){return void 0===e&&(e=15),void 0===i&&(i=15),void 0!==this.linegraph.groups[t]?this.linegraph.groups[t].getLegend(e,i):"cannot find group:"+t},s.prototype.isGroupVisible=function(t){return void 0!==this.linegraph.groups[t]?this.linegraph.groups[t].visible:!1},s.prototype.getItemRange=function(){var t=null,e=null;for(var i in this.linegraph.groups)if(this.linegraph.groups.hasOwnProperty(i)&&1==this.linegraph.groups[i].visible)for(var s=0;sr?r:t,e=null==e?r:r>e?r:e}return{min:null!=t?new Date(t):null,max:null!=e?new Date(e):null}},t.exports=s},function(t){function e(t,e,i,s,o){this.current=0,this.autoScale=!0,this.stepIndex=0,this.step=1,this.scale=1,this.marginStart,this.marginEnd,this.majorSteps=[1,2,5,10],this.minorSteps=[.25,.5,1,2],this.setRange(t,e,i,s,o)}e.prototype.setRange=function(t,e,i,s,o){this._start=t,this._end=e,t==e&&(this._start=t-.75,this._end=e+1),this.autoScale&&this.setMinimumStep(i,s,o),this.setFirst()},e.prototype.setMinimumStep=function(t,e){var i=this._end-this._start,s=1.1*i,o=t*(s/e),n=Math.round(Math.log(s)/Math.LN10),r=-1,a=Math.pow(10,n),h=0;0>n&&(h=n);for(var d=!1,l=h;Math.abs(l)<=Math.abs(n);l++){a=Math.pow(10,l);for(var c=0;c=o){d=!0,r=c;break}}if(1==d)break}this.stepIndex=r,this.scale=a,this.step=a*this.minorSteps[r]},e.prototype.first=function(){this.setFirst()},e.prototype.setFirst=function(){var t=this._start-this.scale*this.minorSteps[this.stepIndex],e=this._end+this.scale*this.minorSteps[this.stepIndex];this.marginEnd=this.roundToMinor(e),this.marginStart=this.roundToMinor(t),this.marginRange=this.marginEnd-this.marginStart,this.current=this.marginEnd},e.prototype.roundToMinor=function(t){var e=t-t%(this.scale*this.minorSteps[this.stepIndex]);return t%(this.scale*this.minorSteps[this.stepIndex])>.5*this.scale*this.minorSteps[this.stepIndex]?e+this.scale*this.minorSteps[this.stepIndex]:e},e.prototype.hasNext=function(){return this.current>=this.marginStart},e.prototype.next=function(){var t=this.current;this.current-=this.step,this.current==t&&(this.current=this._end)},e.prototype.previous=function(){this.current+=this.step,this.marginEnd+=this.step,this.marginRange=this.marginEnd-this.marginStart},e.prototype.getCurrent=function(){for(var t=""+Number(this.current).toPrecision(5),e=t.length-1;e>0;e--){if("0"!=t[e]){if("."==t[e]||","==t[e]){t=t.slice(0,e);break}break}t=t.slice(0,e)}return t},e.prototype.snap=function(){},e.prototype.isMajor=function(){return this.current%(this.scale*this.majorSteps[this.stepIndex])==0},t.exports=e},function(t,e,i){function s(t,e){var i=h().hours(0).minutes(0).seconds(0).milliseconds(0);this.start=i.clone().add("days",-3).valueOf(),this.end=i.clone().add("days",4).valueOf(),this.body=t,this.defaultOptions={start:null,end:null,direction:"horizontal",moveable:!0,zoomable:!0,min:null,max:null,zoomMin:10,zoomMax:31536e10},this.options=r.extend({},this.defaultOptions),this.props={touch:{}},this.body.emitter.on("dragstart",this._onDragStart.bind(this)),this.body.emitter.on("drag",this._onDrag.bind(this)),this.body.emitter.on("dragend",this._onDragEnd.bind(this)),this.body.emitter.on("hold",this._onHold.bind(this)),this.body.emitter.on("mousewheel",this._onMouseWheel.bind(this)),this.body.emitter.on("DOMMouseScroll",this._onMouseWheel.bind(this)),this.body.emitter.on("touch",this._onTouch.bind(this)),this.body.emitter.on("pinch",this._onPinch.bind(this)),this.setOptions(e)}function o(t){if("horizontal"!=t&&"vertical"!=t)throw new TypeError('Unknown direction "'+t+'". Choose "horizontal" or "vertical".')}function n(t,e){return{x:t.pageX-r.getAbsoluteLeft(e),y:t.pageY-r.getAbsoluteTop(e)}}var r=i(1),a=i(43),h=i(40),d=i(18);s.prototype=new d,s.prototype.setOptions=function(t){if(t){var e=["direction","min","max","zoomMin","zoomMax","moveable","zoomable"];r.selectiveExtend(e,this.options,t),("start"in t||"end"in t)&&this.setRange(t.start,t.end)}},s.prototype.setRange=function(t,e){var i=this._applyRange(t,e);if(i){var s={start:new Date(this.start),end:new Date(this.end)};this.body.emitter.emit("rangechange",s),this.body.emitter.emit("rangechanged",s)}},s.prototype._applyRange=function(t,e){var i,s=null!=t?r.convert(t,"Date").valueOf():this.start,o=null!=e?r.convert(e,"Date").valueOf():this.end,n=null!=this.options.max?r.convert(this.options.max,"Date").valueOf():null,a=null!=this.options.min?r.convert(this.options.min,"Date").valueOf():null;if(isNaN(s)||null===s)throw new Error('Invalid start "'+t+'"');if(isNaN(o)||null===o)throw new Error('Invalid end "'+e+'"');if(s>o&&(o=s),null!==a&&a>s&&(i=a-s,s+=i,o+=i,null!=n&&o>n&&(o=n)),null!==n&&o>n&&(i=o-n,s-=i,o-=i,null!=a&&a>s&&(s=a)),null!==this.options.zoomMin){var h=parseFloat(this.options.zoomMin);0>h&&(h=0),h>o-s&&(this.end-this.start===h?(s=this.start,o=this.end):(i=h-(o-s),s-=i/2,o+=i/2))}if(null!==this.options.zoomMax){var d=parseFloat(this.options.zoomMax);0>d&&(d=0),o-s>d&&(this.end-this.start===d?(s=this.start,o=this.end):(i=o-s-d,s+=i/2,o-=i/2))}var l=this.start!=s||this.end!=o;return this.start=s,this.end=o,l},s.prototype.getRange=function(){return{start:this.start,end:this.end}},s.prototype.conversion=function(t){return s.conversion(this.start,this.end,t)},s.conversion=function(t,e,i){return 0!=i&&e-t!=0?{offset:t,scale:i/(e-t)}:{offset:0,scale:1}},s.prototype._onDragStart=function(){this.options.moveable&&this.props.touch.allowDragging&&(this.props.touch.start=this.start,this.props.touch.end=this.end,this.body.dom.root&&(this.body.dom.root.style.cursor="move"))},s.prototype._onDrag=function(t){if(this.options.moveable){var e=this.options.direction;if(o(e),this.props.touch.allowDragging){var i="horizontal"==e?t.gesture.deltaX:t.gesture.deltaY,s=this.props.touch.end-this.props.touch.start,n="horizontal"==e?this.body.domProps.center.width:this.body.domProps.center.height,r=-i/n*s;this._applyRange(this.props.touch.start+r,this.props.touch.end+r),this.body.emitter.emit("rangechange",{start:new Date(this.start),end:new Date(this.end)})}}},s.prototype._onDragEnd=function(){this.options.moveable&&this.props.touch.allowDragging&&(this.body.dom.root&&(this.body.dom.root.style.cursor="auto"),this.body.emitter.emit("rangechanged",{start:new Date(this.start),end:new Date(this.end)}))},s.prototype._onMouseWheel=function(t){if(this.options.zoomable&&this.options.moveable){var e=0;if(t.wheelDelta?e=t.wheelDelta/120:t.detail&&(e=-t.detail/3),e){var i;i=0>e?1-e/5:1/(1+e/5);var s=a.fakeGesture(this,t),o=n(s.center,this.body.dom.center),r=this._pointerToDate(o);this.zoom(i,r)}t.preventDefault()}},s.prototype._onTouch=function(){this.props.touch.start=this.start,this.props.touch.end=this.end,this.props.touch.allowDragging=!0,this.props.touch.center=null},s.prototype._onHold=function(){this.props.touch.allowDragging=!1},s.prototype._onPinch=function(t){if(this.options.zoomable&&this.options.moveable&&(this.props.touch.allowDragging=!1,t.gesture.touches.length>1)){this.props.touch.center||(this.props.touch.center=n(t.gesture.center,this.body.dom.center));var e=1/t.gesture.scale,i=this._pointerToDate(this.props.touch.center),s=parseInt(i+(this.props.touch.start-i)*e),o=parseInt(i+(this.props.touch.end-i)*e);this.setRange(s,o)}},s.prototype._pointerToDate=function(t){var e,i=this.options.direction;if(o(i),"horizontal"==i){var s=this.body.domProps.center.width;return e=this.conversion(s),t.x/e.scale+e.offset}var n=this.body.domProps.center.height;return e=this.conversion(n),t.y/e.scale+e.offset},s.prototype.zoom=function(t,e){null==e&&(e=(this.start+this.end)/2);var i=e+(this.start-e)*t,s=e+(this.end-e)*t;this.setRange(i,s)},s.prototype.move=function(t){var e=this.end-this.start,i=this.start+e*t,s=this.end+e*t;this.start=i,this.end=s},s.prototype.moveTo=function(t){var e=(this.start+this.end)/2,i=e-t,s=this.start-i,o=this.end-i;this.setRange(s,o)},t.exports=s},function(t,e){var i=.001;e.orderByStart=function(t){t.sort(function(t,e){return t.data.start-e.data.start})},e.orderByEnd=function(t){t.sort(function(t,e){var i="end"in t.data?t.data.end:t.data.start,s="end"in e.data?e.data.end:e.data.start;return i-s})},e.stack=function(t,i,s){var o,n;if(s)for(o=0,n=t.length;n>o;o++)t[o].top=null;for(o=0,n=t.length;n>o;o++){var r=t[o];if(null===r.top){r.top=i.axis;do{for(var a=null,h=0,d=t.length;d>h;h++){var l=t[h];if(null!==l.top&&l!==r&&e.collision(r,l,i.item)){a=l;break}}null!=a&&(r.top=a.top+a.height+i.item.vertical)}while(a)}}},e.nostack=function(t,e){var i,s;for(i=0,s=t.length;s>i;i++)t[i].top=e.axis},e.collision=function(t,e,s){return t.left-s.horizontal+ie.left&&t.top-s.vertical+ie.top}},function(t,e,i){function s(t,e,i){this.current=new Date,this._start=new Date,this._end=new Date,this.autoScale=!0,this.scale=s.SCALE.DAY,this.step=1,this.setRange(t,e,i)}var o=i(40);s.SCALE={MILLISECOND:1,SECOND:2,MINUTE:3,HOUR:4,DAY:5,WEEKDAY:6,MONTH:7,YEAR:8},s.prototype.setRange=function(t,e,i){if(!(t instanceof Date&&e instanceof Date))throw"No legal start or end date in method setRange";this._start=void 0!=t?new Date(t.valueOf()):new Date,this._end=void 0!=e?new Date(e.valueOf()):new Date,this.autoScale&&this.setMinimumStep(i)},s.prototype.first=function(){this.current=new Date(this._start.valueOf()),this.roundToMinor()},s.prototype.roundToMinor=function(){switch(this.scale){case s.SCALE.YEAR:this.current.setFullYear(this.step*Math.floor(this.current.getFullYear()/this.step)),this.current.setMonth(0);case s.SCALE.MONTH:this.current.setDate(1);case s.SCALE.DAY:case s.SCALE.WEEKDAY:this.current.setHours(0);case s.SCALE.HOUR:this.current.setMinutes(0);case s.SCALE.MINUTE:this.current.setSeconds(0);case s.SCALE.SECOND:this.current.setMilliseconds(0)}if(1!=this.step)switch(this.scale){case s.SCALE.MILLISECOND:this.current.setMilliseconds(this.current.getMilliseconds()-this.current.getMilliseconds()%this.step);break;case s.SCALE.SECOND:this.current.setSeconds(this.current.getSeconds()-this.current.getSeconds()%this.step);break;case s.SCALE.MINUTE:this.current.setMinutes(this.current.getMinutes()-this.current.getMinutes()%this.step);break;case s.SCALE.HOUR:this.current.setHours(this.current.getHours()-this.current.getHours()%this.step);break;case s.SCALE.WEEKDAY:case s.SCALE.DAY:this.current.setDate(this.current.getDate()-1-(this.current.getDate()-1)%this.step+1);break;case s.SCALE.MONTH:this.current.setMonth(this.current.getMonth()-this.current.getMonth()%this.step);break;case s.SCALE.YEAR:this.current.setFullYear(this.current.getFullYear()-this.current.getFullYear()%this.step)}},s.prototype.hasNext=function(){return this.current.valueOf()<=this._end.valueOf()},s.prototype.next=function(){var t=this.current.valueOf();if(this.current.getMonth()<6)switch(this.scale){case s.SCALE.MILLISECOND:this.current=new Date(this.current.valueOf()+this.step);break;case s.SCALE.SECOND:this.current=new Date(this.current.valueOf()+1e3*this.step);break;case s.SCALE.MINUTE:this.current=new Date(this.current.valueOf()+1e3*this.step*60);break;case s.SCALE.HOUR:this.current=new Date(this.current.valueOf()+1e3*this.step*60*60);var e=this.current.getHours();this.current.setHours(e-e%this.step);break;case s.SCALE.WEEKDAY:case s.SCALE.DAY:this.current.setDate(this.current.getDate()+this.step);break;case s.SCALE.MONTH:this.current.setMonth(this.current.getMonth()+this.step);break;case s.SCALE.YEAR:this.current.setFullYear(this.current.getFullYear()+this.step)}else switch(this.scale){case s.SCALE.MILLISECOND:this.current=new Date(this.current.valueOf()+this.step);break;case s.SCALE.SECOND:this.current.setSeconds(this.current.getSeconds()+this.step);break;case s.SCALE.MINUTE:this.current.setMinutes(this.current.getMinutes()+this.step);break;case s.SCALE.HOUR:this.current.setHours(this.current.getHours()+this.step);break;case s.SCALE.WEEKDAY:case s.SCALE.DAY:this.current.setDate(this.current.getDate()+this.step);break;case s.SCALE.MONTH:this.current.setMonth(this.current.getMonth()+this.step);break;case s.SCALE.YEAR:this.current.setFullYear(this.current.getFullYear()+this.step)}if(1!=this.step)switch(this.scale){case s.SCALE.MILLISECOND:this.current.getMilliseconds()0&&(this.step=e),this.autoScale=!1},s.prototype.setAutoScale=function(t){this.autoScale=t},s.prototype.setMinimumStep=function(t){if(void 0!=t){var e=31104e6,i=2592e6,o=864e5,n=36e5,r=6e4,a=1e3,h=1;1e3*e>t&&(this.scale=s.SCALE.YEAR,this.step=1e3),500*e>t&&(this.scale=s.SCALE.YEAR,this.step=500),100*e>t&&(this.scale=s.SCALE.YEAR,this.step=100),50*e>t&&(this.scale=s.SCALE.YEAR,this.step=50),10*e>t&&(this.scale=s.SCALE.YEAR,this.step=10),5*e>t&&(this.scale=s.SCALE.YEAR,this.step=5),e>t&&(this.scale=s.SCALE.YEAR,this.step=1),3*i>t&&(this.scale=s.SCALE.MONTH,this.step=3),i>t&&(this.scale=s.SCALE.MONTH,this.step=1),5*o>t&&(this.scale=s.SCALE.DAY,this.step=5),2*o>t&&(this.scale=s.SCALE.DAY,this.step=2),o>t&&(this.scale=s.SCALE.DAY,this.step=1),o/2>t&&(this.scale=s.SCALE.WEEKDAY,this.step=1),4*n>t&&(this.scale=s.SCALE.HOUR,this.step=4),n>t&&(this.scale=s.SCALE.HOUR,this.step=1),15*r>t&&(this.scale=s.SCALE.MINUTE,this.step=15),10*r>t&&(this.scale=s.SCALE.MINUTE,this.step=10),5*r>t&&(this.scale=s.SCALE.MINUTE,this.step=5),r>t&&(this.scale=s.SCALE.MINUTE,this.step=1),15*a>t&&(this.scale=s.SCALE.SECOND,this.step=15),10*a>t&&(this.scale=s.SCALE.SECOND,this.step=10),5*a>t&&(this.scale=s.SCALE.SECOND,this.step=5),a>t&&(this.scale=s.SCALE.SECOND,this.step=1),200*h>t&&(this.scale=s.SCALE.MILLISECOND,this.step=200),100*h>t&&(this.scale=s.SCALE.MILLISECOND,this.step=100),50*h>t&&(this.scale=s.SCALE.MILLISECOND,this.step=50),10*h>t&&(this.scale=s.SCALE.MILLISECOND,this.step=10),5*h>t&&(this.scale=s.SCALE.MILLISECOND,this.step=5),h>t&&(this.scale=s.SCALE.MILLISECOND,this.step=1)}},s.prototype.snap=function(t){var e=new Date(t.valueOf());if(this.scale==s.SCALE.YEAR){var i=e.getFullYear()+Math.round(e.getMonth()/12);e.setFullYear(Math.round(i/this.step)*this.step),e.setMonth(0),e.setDate(0),e.setHours(0),e.setMinutes(0),e.setSeconds(0),e.setMilliseconds(0)}else if(this.scale==s.SCALE.MONTH)e.getDate()>15?(e.setDate(1),e.setMonth(e.getMonth()+1)):e.setDate(1),e.setHours(0),e.setMinutes(0),e.setSeconds(0),e.setMilliseconds(0);else if(this.scale==s.SCALE.DAY){switch(this.step){case 5:case 2:e.setHours(24*Math.round(e.getHours()/24));break;default:e.setHours(12*Math.round(e.getHours()/12))}e.setMinutes(0),e.setSeconds(0),e.setMilliseconds(0)}else if(this.scale==s.SCALE.WEEKDAY){switch(this.step){case 5:case 2:e.setHours(12*Math.round(e.getHours()/12));break;default:e.setHours(6*Math.round(e.getHours()/6))}e.setMinutes(0),e.setSeconds(0),e.setMilliseconds(0)}else if(this.scale==s.SCALE.HOUR){switch(this.step){case 4:e.setMinutes(60*Math.round(e.getMinutes()/60));break;default:e.setMinutes(30*Math.round(e.getMinutes()/30))}e.setSeconds(0),e.setMilliseconds(0)}else if(this.scale==s.SCALE.MINUTE){switch(this.step){case 15:case 10:e.setMinutes(5*Math.round(e.getMinutes()/5)),e.setSeconds(0);break;case 5:e.setSeconds(60*Math.round(e.getSeconds()/60));break;default:e.setSeconds(30*Math.round(e.getSeconds()/30))}e.setMilliseconds(0)}else if(this.scale==s.SCALE.SECOND)switch(this.step){case 15:case 10:e.setSeconds(5*Math.round(e.getSeconds()/5)),e.setMilliseconds(0);break;case 5:e.setMilliseconds(1e3*Math.round(e.getMilliseconds()/1e3));break;default:e.setMilliseconds(500*Math.round(e.getMilliseconds()/500))}else if(this.scale==s.SCALE.MILLISECOND){var o=this.step>5?this.step/2:1;e.setMilliseconds(Math.round(e.getMilliseconds()/o)*o)}return e},s.prototype.isMajor=function(){switch(this.scale){case s.SCALE.MILLISECOND:return 0==this.current.getMilliseconds();case s.SCALE.SECOND:return 0==this.current.getSeconds();case s.SCALE.MINUTE:return 0==this.current.getHours()&&0==this.current.getMinutes();case s.SCALE.HOUR:return 0==this.current.getHours();case s.SCALE.WEEKDAY:case s.SCALE.DAY:return 1==this.current.getDate();case s.SCALE.MONTH:return 0==this.current.getMonth();case s.SCALE.YEAR:return!1;default:return!1}},s.prototype.getLabelMinor=function(t){switch(void 0==t&&(t=this.current),this.scale){case s.SCALE.MILLISECOND:return o(t).format("SSS");case s.SCALE.SECOND:return o(t).format("s");case s.SCALE.MINUTE:return o(t).format("HH:mm");case s.SCALE.HOUR:return o(t).format("HH:mm");case s.SCALE.WEEKDAY:return o(t).format("ddd D");case s.SCALE.DAY:return o(t).format("D");case s.SCALE.MONTH:return o(t).format("MMM");case s.SCALE.YEAR:return o(t).format("YYYY");default:return""}},s.prototype.getLabelMajor=function(t){switch(void 0==t&&(t=this.current),this.scale){case s.SCALE.MILLISECOND:return o(t).format("HH:mm:ss");case s.SCALE.SECOND:return o(t).format("D MMMM HH:mm");case s.SCALE.MINUTE:case s.SCALE.HOUR:return o(t).format("ddd D MMMM");case s.SCALE.WEEKDAY:case s.SCALE.DAY:return o(t).format("MMMM YYYY");case s.SCALE.MONTH:return o(t).format("YYYY");case s.SCALE.YEAR:return"";default:return""}},t.exports=s},function(t){function e(){this.options=null,this.props=null}e.prototype.setOptions=function(t){t&&util.extend(this.options,t)},e.prototype.redraw=function(){return!1},e.prototype.destroy=function(){},e.prototype._isResized=function(){var t=this.props._previousWidth!==this.props.width||this.props._previousHeight!==this.props.height;return this.props._previousWidth=this.props.width,this.props._previousHeight=this.props.height,t},t.exports=e},function(t,e,i){function s(t,e){this.body=t,this.defaultOptions={showCurrentTime:!0},this.options=o.extend({},this.defaultOptions),this._create(),this.setOptions(e)}var o=i(1),n=i(18);s.prototype=new n,s.prototype._create=function(){var t=document.createElement("div");t.className="currenttime",t.style.position="absolute",t.style.top="0px",t.style.height="100%",this.bar=t},s.prototype.destroy=function(){this.options.showCurrentTime=!1,this.redraw(),this.body=null},s.prototype.setOptions=function(t){t&&o.selectiveExtend(["showCurrentTime"],this.options,t)},s.prototype.redraw=function(){if(this.options.showCurrentTime){var t=this.body.dom.backgroundVertical;this.bar.parentNode!=t&&(this.bar.parentNode&&this.bar.parentNode.removeChild(this.bar),t.appendChild(this.bar),this.start());var e=new Date,i=this.body.util.toScreen(e);this.bar.style.left=i+"px",this.bar.title="Current time: "+e}else this.bar.parentNode&&this.bar.parentNode.removeChild(this.bar),this.stop();return!1},s.prototype.start=function(){function t(){e.stop();var i=e.body.range.conversion(e.body.domProps.center.width).scale,s=1/i/10;30>s&&(s=30),s>1e3&&(s=1e3),e.redraw(),e.currentTimeTimer=setTimeout(t,s)}var e=this;t()},s.prototype.stop=function(){void 0!==this.currentTimeTimer&&(clearTimeout(this.currentTimeTimer),delete this.currentTimeTimer)},t.exports=s},function(t,e,i){function s(t,e){this.body=t,this.defaultOptions={showCustomTime:!1},this.options=n.extend({},this.defaultOptions),this.customTime=new Date,this.eventParams={},this._create(),this.setOptions(e)}var o=i(41),n=i(1),r=i(18);s.prototype=new r,s.prototype.setOptions=function(t){t&&n.selectiveExtend(["showCustomTime"],this.options,t)},s.prototype._create=function(){var t=document.createElement("div");t.className="customtime",t.style.position="absolute",t.style.top="0px",t.style.height="100%",this.bar=t;var e=document.createElement("div");e.style.position="relative",e.style.top="0px",e.style.left="-10px",e.style.height="100%",e.style.width="20px",t.appendChild(e),this.hammer=o(t,{prevent_default:!0}),this.hammer.on("dragstart",this._onDragStart.bind(this)),this.hammer.on("drag",this._onDrag.bind(this)),this.hammer.on("dragend",this._onDragEnd.bind(this))},s.prototype.destroy=function(){this.options.showCustomTime=!1,this.redraw(),this.hammer.enable(!1),this.hammer=null,this.body=null},s.prototype.redraw=function(){if(this.options.showCustomTime){var t=this.body.dom.backgroundVertical;this.bar.parentNode!=t&&(this.bar.parentNode&&this.bar.parentNode.removeChild(this.bar),t.appendChild(this.bar));var e=this.body.util.toScreen(this.customTime);this.bar.style.left=e+"px",this.bar.title="Time: "+this.customTime}else this.bar.parentNode&&this.bar.parentNode.removeChild(this.bar);return!1},s.prototype.setCustomTime=function(t){this.customTime=new Date(t.valueOf()),this.redraw()},s.prototype.getCustomTime=function(){return new Date(this.customTime.valueOf())},s.prototype._onDragStart=function(t){this.eventParams.dragging=!0,this.eventParams.customTime=this.customTime,t.stopPropagation(),t.preventDefault()},s.prototype._onDrag=function(t){if(this.eventParams.dragging){var e=t.gesture.deltaX,i=this.body.util.toScreen(this.eventParams.customTime)+e,s=this.body.util.toTime(i);this.setCustomTime(s),this.body.emitter.emit("timechange",{time:new Date(this.customTime.valueOf())}),t.stopPropagation(),t.preventDefault()}},s.prototype._onDragEnd=function(t){this.eventParams.dragging&&(this.body.emitter.emit("timechanged",{time:new Date(this.customTime.valueOf())}),t.stopPropagation(),t.preventDefault())},t.exports=s},function(t,e,i){function s(t,e,i){this.id=o.randomUUID(),this.body=t,this.defaultOptions={orientation:"left",showMinorLabels:!0,showMajorLabels:!0,icons:!0,majorLinesOffset:7,minorLinesOffset:4,labelOffsetX:10,labelOffsetY:2,iconWidth:20,width:"40px",visible:!0},this.linegraphSVG=i,this.props={},this.DOMelements={lines:{},labels:{}},this.dom={},this.range={start:0,end:0},this.options=o.extend({},this.defaultOptions),this.conversionFactor=1,this.setOptions(e),this.width=Number((""+this.options.width).replace("px","")),this.minWidth=this.width,this.height=this.linegraphSVG.offsetHeight,this.stepPixels=25,this.stepPixelsForced=25,this.lineOffset=0,this.master=!0,this.svgElements={},this.groups={},this.amountOfGroups=0,this._create() +}var o=i(1),n=i(2),r=i(18),a=i(14);s.prototype=new r,s.prototype.addGroup=function(t,e){this.groups.hasOwnProperty(t)||(this.groups[t]=e),this.amountOfGroups+=1},s.prototype.updateGroup=function(t,e){this.groups[t]=e},s.prototype.removeGroup=function(t){this.groups.hasOwnProperty(t)&&(delete this.groups[t],this.amountOfGroups-=1)},s.prototype.setOptions=function(t){if(t){var e=!1;this.options.orientation!=t.orientation&&void 0!==t.orientation&&(e=!0);var i=["orientation","showMinorLabels","showMajorLabels","icons","majorLinesOffset","minorLinesOffset","labelOffsetX","labelOffsetY","iconWidth","width","visible"];o.selectiveExtend(i,this.options,t),this.minWidth=Number((""+this.options.width).replace("px","")),1==e&&this.dom.frame&&(this.hide(),this.show())}},s.prototype._create=function(){this.dom.frame=document.createElement("div"),this.dom.frame.style.width=this.options.width,this.dom.frame.style.height=this.height,this.dom.lineContainer=document.createElement("div"),this.dom.lineContainer.style.width="100%",this.dom.lineContainer.style.height=this.height,this.svg=document.createElementNS("http://www.w3.org/2000/svg","svg"),this.svg.style.position="absolute",this.svg.style.top="0px",this.svg.style.height="100%",this.svg.style.width="100%",this.svg.style.display="block",this.dom.frame.appendChild(this.svg)},s.prototype._redrawGroupIcons=function(){n.prepareElements(this.svgElements);var t,e=this.options.iconWidth,i=15,s=4,o=s+.5*i;t="left"==this.options.orientation?s:this.width-e-s;for(var r in this.groups)this.groups.hasOwnProperty(r)&&1==this.groups[r].visible&&(this.groups[r].drawIcon(t,o,this.svgElements,this.svg,e,i),o+=i+s);n.cleanupElements(this.svgElements)},s.prototype.show=function(){this.dom.frame.parentNode||("left"==this.options.orientation?this.body.dom.left.appendChild(this.dom.frame):this.body.dom.right.appendChild(this.dom.frame)),this.dom.lineContainer.parentNode||this.body.dom.backgroundHorizontal.appendChild(this.dom.lineContainer)},s.prototype.hide=function(){this.dom.frame.parentNode&&this.dom.frame.parentNode.removeChild(this.dom.frame),this.dom.lineContainer.parentNode&&this.dom.lineContainer.parentNode.removeChild(this.dom.lineContainer)},s.prototype.setRange=function(t,e){this.range.start=t,this.range.end=e},s.prototype.redraw=function(){var t=!1,e=0;for(var i in this.groups)this.groups.hasOwnProperty(i)&&1==this.groups[i].visible&&e++;if(0==this.amountOfGroups||0==e)this.hide();else{this.show(),this.height=Number(this.linegraphSVG.style.height.replace("px","")),this.dom.lineContainer.style.height=this.height+"px",this.width=1==this.options.visible?Number((""+this.options.width).replace("px","")):0;var s=this.props,o=this.dom.frame;o.className="dataaxis",this._calculateCharSize();var n=this.options.orientation,r=this.options.showMinorLabels,a=this.options.showMajorLabels;s.minorLabelHeight=r?s.minorCharHeight:0,s.majorLabelHeight=a?s.majorCharHeight:0,s.minorLineWidth=this.body.dom.backgroundHorizontal.offsetWidth-this.lineOffset-this.width+2*this.options.minorLinesOffset,s.minorLineHeight=1,s.majorLineWidth=this.body.dom.backgroundHorizontal.offsetWidth-this.lineOffset-this.width+2*this.options.majorLinesOffset,s.majorLineHeight=1,"left"==n?(o.style.top="0",o.style.left="0",o.style.bottom="",o.style.width=this.width+"px",o.style.height=this.height+"px"):(o.style.top="",o.style.bottom="0",o.style.left="0",o.style.width=this.width+"px",o.style.height=this.height+"px"),t=this._redrawLabels(),1==this.options.icons&&this._redrawGroupIcons()}return t},s.prototype._redrawLabels=function(){n.prepareElements(this.DOMelements.lines),n.prepareElements(this.DOMelements.labels);var t=this.options.orientation,e=this.master?this.props.majorCharHeight||10:this.stepPixelsForced,i=new a(this.range.start,this.range.end,e,this.dom.frame.offsetHeight);this.step=i,i.first();var s=this.dom.frame.offsetHeight/(i.marginRange/i.step+1);this.stepPixels=s;var o=this.height/s,r=0;if(0==this.master){s=this.stepPixelsForced,r=Math.round(this.height/s-o);for(var h=0;.5*r>h;h++)i.previous();o=this.height/s}this.valueAtZero=i.marginEnd;var d=0,l=1;i.next(),this.maxLabelSize=0;for(var c=0;l=0&&this._redrawLabel(c-2,i.getCurrent(),t,"yAxis major",this.props.majorCharHeight),this._redrawLine(c,t,"grid horizontal major",this.options.majorLinesOffset,this.props.majorLineWidth)):this._redrawLine(c,t,"grid horizontal minor",this.options.minorLinesOffset,this.props.minorLineWidth),i.next(),l++}this.conversionFactor=d/((o-1)*i.step);var u=1==this.options.icons?this.options.iconWidth+this.options.labelOffsetX+15:this.options.labelOffsetX+15;return this.maxLabelSize>this.width-u&&1==this.options.visible?(this.width=this.maxLabelSize+u,this.options.width=this.width+"px",n.cleanupElements(this.DOMelements.lines),n.cleanupElements(this.DOMelements.labels),this.redraw(),!0):this.maxLabelSizethis.minWidth?(this.width=Math.max(this.minWidth,this.maxLabelSize+u),this.options.width=this.width+"px",n.cleanupElements(this.DOMelements.lines),n.cleanupElements(this.DOMelements.labels),this.redraw(),!0):(n.cleanupElements(this.DOMelements.lines),n.cleanupElements(this.DOMelements.labels),!1)},s.prototype._redrawLabel=function(t,e,i,s,o){var r=n.getDOMElement("div",this.DOMelements.labels,this.dom.frame);r.className=s,r.innerHTML=e,"left"==i?(r.style.left="-"+this.options.labelOffsetX+"px",r.style.textAlign="right"):(r.style.right="-"+this.options.labelOffsetX+"px",r.style.textAlign="left"),r.style.top=t-.5*o+this.options.labelOffsetY+"px",e+="";var a=Math.max(this.props.majorCharWidth,this.props.minorCharWidth);this.maxLabelSizee.axis){var c=d-e.axis;l-=c,o.forEach(h,function(t){t.top-=c})}a=l+e.item.vertical/2}else a=e.axis+e.item.vertical;a=Math.max(a,this.props.label.height);var p=this.dom.foreground;this.top=p.offsetTop,this.left=p.offsetLeft,this.width=p.offsetWidth,s=o.updateProperty(this,"height",a)||s,s=o.updateProperty(this.props.label,"width",this.dom.inner.clientWidth)||s,s=o.updateProperty(this.props.label,"height",this.dom.inner.clientHeight)||s,this.dom.background.style.height=a+"px",this.dom.foreground.style.height=a+"px",this.dom.label.style.height=a+"px";for(var u=0,f=this.visibleItems.length;f>u;u++){var m=this.visibleItems[u];m.repositionY()}return s},s.prototype.show=function(){this.dom.label.parentNode||this.itemSet.dom.labelSet.appendChild(this.dom.label),this.dom.foreground.parentNode||this.itemSet.dom.foreground.appendChild(this.dom.foreground),this.dom.background.parentNode||this.itemSet.dom.background.appendChild(this.dom.background),this.dom.axis.parentNode||this.itemSet.dom.axis.appendChild(this.dom.axis)},s.prototype.hide=function(){var t=this.dom.label;t.parentNode&&t.parentNode.removeChild(t);var e=this.dom.foreground;e.parentNode&&e.parentNode.removeChild(e);var i=this.dom.background;i.parentNode&&i.parentNode.removeChild(i);var s=this.dom.axis;s.parentNode&&s.parentNode.removeChild(s)},s.prototype.add=function(t){if(this.items[t.id]=t,t.setParent(this),-1==this.visibleItems.indexOf(t)){var e=this.itemSet.body.range;this._checkIfVisible(t,this.visibleItems,e)}},s.prototype.remove=function(t){delete this.items[t.id],t.setParent(this.itemSet);var e=this.visibleItems.indexOf(t);-1!=e&&this.visibleItems.splice(e,1)},s.prototype.removeFromDataSet=function(t){this.itemSet.removeItem(t.id)},s.prototype.order=function(){var t=o.toArray(this.items);this.orderedItems.byStart=t,this.orderedItems.byEnd=this._constructByEndArray(t),n.orderByStart(this.orderedItems.byStart),n.orderByEnd(this.orderedItems.byEnd)},s.prototype._constructByEndArray=function(t){for(var e=[],i=0;i0)for(n=0;n=0&&!this._checkIfInvisible(t.byStart[n],r,i);n--);for(n=s+1;n=0&&!this._checkIfInvisible(t.byEnd[n],r,i);n--);for(n=a+1;ne;e++)s=this.selection[e],o=this.items[s],o&&o.unselect();for(this.selection=[],e=0,i=t.length;i>e;e++)s=t[e],o=this.items[s],o&&(this.selection.push(s),o.select())}},s.prototype.getSelection=function(){return this.selection.concat([])},s.prototype.getVisibleItems=function(){var t=this.body.range.getRange(),e=this.body.util.toScreen(t.start),i=this.body.util.toScreen(t.end),s=[];for(var o in this.groups)if(this.groups.hasOwnProperty(o))for(var n=this.groups[o],r=n.visibleItems,a=0;ae&&s.push(h.id)}return s},s.prototype._deselect=function(t){for(var e=this.selection,i=0,s=e.length;s>i;i++)if(e[i]==t){e.splice(i,1);break}},s.prototype.redraw=function(){var t=this.options.margin,e=this.body.range,i=r.option.asSize,s=this.options,o=s.orientation,n=!1,a=this.dom.frame,h=s.editable.updateTime||s.editable.updateGroup;a.className="itemset"+(h?" editable":""),n=this._orderGroups()||n;var d=e.end-e.start,l=d!=this.lastVisibleInterval||this.props.width!=this.props.lastWidth;l&&(this.stackDirty=!0),this.lastVisibleInterval=d,this.props.lastWidth=this.props.width;var c=this.stackDirty,p=this._firstGroup(),u={item:t.item,axis:t.axis},f={item:t.item,axis:t.item.vertical/2},m=0,g=t.axis+t.item.vertical;return r.forEach(this.groups,function(t){var i=t==p?u:f,s=t.redraw(e,i,c);n=s||n,m+=t.height}),m=Math.max(m,g),this.stackDirty=!1,a.style.height=i(m),this.props.top=a.offsetTop,this.props.left=a.offsetLeft,this.props.width=a.offsetWidth,this.props.height=m,this.dom.axis.style.top=i("top"==o?this.body.domProps.top.height+this.body.domProps.border.top:this.body.domProps.top.height+this.body.domProps.centerContainer.height),this.dom.axis.style.left=this.body.domProps.border.left+"px",n=this._isResized()||n},s.prototype._firstGroup=function(){var t="top"==this.options.orientation?0:this.groupIds.length-1,e=this.groupIds[t],i=this.groups[e]||this.groups[f];return i||null},s.prototype._updateUngrouped=function(){var t=this.groups[f];if(this.groupsData)t&&(t.hide(),delete this.groups[f]);else if(!t){var e=null,i=null;t=new l(e,i,this),this.groups[f]=t;for(var s in this.items)this.items.hasOwnProperty(s)&&t.add(this.items[s]);t.show()}},s.prototype.getLabelSet=function(){return this.dom.labelSet},s.prototype.setItems=function(t){var e,i=this,s=this.itemsData;if(t){if(!(t instanceof a||t instanceof h))throw new TypeError("Data must be an instance of DataSet or DataView");this.itemsData=t}else this.itemsData=null;if(s&&(r.forEach(this.itemListeners,function(t,e){s.off(e,t)}),e=s.getIds(),this._onRemove(e)),this.itemsData){var o=this.id;r.forEach(this.itemListeners,function(t,e){i.itemsData.on(e,t,o)}),e=this.itemsData.getIds(),this._onAdd(e),this._updateUngrouped()}},s.prototype.getItems=function(){return this.itemsData},s.prototype.setGroups=function(t){var e,i=this;if(this.groupsData&&(r.forEach(this.groupListeners,function(t,e){i.groupsData.unsubscribe(e,t)}),e=this.groupsData.getIds(),this.groupsData=null,this._onRemoveGroups(e)),t){if(!(t instanceof a||t instanceof h))throw new TypeError("Data must be an instance of DataSet or DataView");this.groupsData=t}else this.groupsData=null;if(this.groupsData){var s=this.id;r.forEach(this.groupListeners,function(t,e){i.groupsData.on(e,t,s)}),e=this.groupsData.getIds(),this._onAddGroups(e)}this._updateUngrouped(),this._order(),this.body.emitter.emit("change")},s.prototype.getGroups=function(){return this.groupsData},s.prototype.removeItem=function(t){var e=this.itemsData.get(t),i=this.itemsData.getDataSet();e&&this.options.onRemove(e,function(e){e&&i.remove(t)})},s.prototype._onUpdate=function(t){var e=this;t.forEach(function(t){var i=e.itemsData.get(t,e.itemOptions),o=e.items[t],n=i.type||e.options.type||(i.end?"range":"box"),r=s.types[n];if(o&&(r&&o instanceof r?e._updateItem(o,i):(e._removeItem(o),o=null)),!o){if(!r)throw new TypeError("rangeoverflow"==n?'Item type "rangeoverflow" is deprecated. Use css styling instead: .vis.timeline .item.range .content {overflow: visible;}':'Unknown item type "'+n+'"');o=new r(i,e.conversion,e.options),o.id=t,e._addItem(o)}}),this._order(),this.stackDirty=!0,this.body.emitter.emit("change")},s.prototype._onAdd=s.prototype._onUpdate,s.prototype._onRemove=function(t){var e=0,i=this;t.forEach(function(t){var s=i.items[t];s&&(e++,i._removeItem(s))}),e&&(this._order(),this.stackDirty=!0,this.body.emitter.emit("change"))},s.prototype._order=function(){r.forEach(this.groups,function(t){t.order()})},s.prototype._onUpdateGroups=function(t){this._onAddGroups(t)},s.prototype._onAddGroups=function(t){var e=this;t.forEach(function(t){var i=e.groupsData.get(t),s=e.groups[t];if(s)s.setData(i);else{if(t==f)throw new Error("Illegal group id. "+t+" is a reserved id.");var o=Object.create(e.options);r.extend(o,{height:null}),s=new l(t,i,e),e.groups[t]=s;for(var n in e.items)if(e.items.hasOwnProperty(n)){var a=e.items[n];a.data.group==t&&s.add(a)}s.order(),s.show()}}),this.body.emitter.emit("change")},s.prototype._onRemoveGroups=function(t){var e=this.groups;t.forEach(function(t){var i=e[t];i&&(i.hide(),delete e[t])}),this.markDirty(),this.body.emitter.emit("change")},s.prototype._orderGroups=function(){if(this.groupsData){var t=this.groupsData.getIds({order:this.options.groupOrder}),e=!r.equalArray(t,this.groupIds);if(e){var i=this.groups;t.forEach(function(t){i[t].hide()}),t.forEach(function(t){i[t].show()}),this.groupIds=t}return e}return!1},s.prototype._addItem=function(t){this.items[t.id]=t;var e=this.groupsData?t.data.group:f,i=this.groups[e];i&&i.add(t)},s.prototype._updateItem=function(t,e){var i=t.data.group;if(t.data=e,t.displayed&&t.redraw(),i!=t.data.group){var s=this.groups[i];s&&s.remove(t);var o=this.groupsData?t.data.group:f,n=this.groups[o];n&&n.add(t)}},s.prototype._removeItem=function(t){t.hide(),delete this.items[t.id];var e=this.selection.indexOf(t.id);-1!=e&&this.selection.splice(e,1);var i=this.groupsData?t.data.group:f,s=this.groups[i];s&&s.remove(t)},s.prototype._constructByEndArray=function(t){for(var e=[],i=0;i0||o.length>0)&&this.body.emitter.emit("select",{items:this.getSelection()}),t.stopPropagation()}},s.prototype._onAddItem=function(t){if(this.options.selectable&&this.options.editable.add){var e=this,i=this.body.util.snap||null,o=s.itemFromTarget(t);if(o){var n=e.itemsData.get(o.id);this.options.onUpdate(n,function(t){t&&e.itemsData.update(t)})}else{var a=r.getAbsoluteLeft(this.dom.frame),h=t.gesture.center.pageX-a,d=this.body.util.toTime(h),l={start:i?i(d):d,content:"new item"};if("range"===this.options.type){var c=this.body.util.toTime(h+this.props.width/5);l.end=i?i(c):c}l[this.itemsData.fieldId]=r.randomUUID();var p=s.groupFromTarget(t);p&&(l.group=p.groupId),this.options.onAdd(l,function(t){t&&e.itemsData.add(l)})}}},s.prototype._onMultiSelectItem=function(t){if(this.options.selectable){var e,i=s.itemFromTarget(t);if(i){e=this.getSelection();var o=e.indexOf(i.id);-1==o?e.push(i.id):e.splice(o,1),this.setSelection(e),this.body.emitter.emit("select",{items:this.getSelection()}),t.stopPropagation()}}},s.itemFromTarget=function(t){for(var e=t.target;e;){if(e.hasOwnProperty("timeline-item"))return e["timeline-item"];e=e.parentNode}return null},s.groupFromTarget=function(t){for(var e=t.target;e;){if(e.hasOwnProperty("timeline-group"))return e["timeline-group"];e=e.parentNode}return null},s.itemSetFromTarget=function(t){for(var e=t.target;e;){if(e.hasOwnProperty("timeline-itemset"))return e["timeline-itemset"];e=e.parentNode}return null},t.exports=s},function(t,e,i){function s(t,e,i){this.body=t,this.defaultOptions={enabled:!0,icons:!0,iconSize:20,iconSpacing:6,left:{visible:!0,position:"top-left"},right:{visible:!0,position:"top-left"}},this.side=i,this.options=o.extend({},this.defaultOptions),this.svgElements={},this.dom={},this.groups={},this.amountOfGroups=0,this._create(),this.setOptions(e)}var o=i(1),n=i(2),r=i(18);s.prototype=new r,s.prototype.addGroup=function(t,e){this.groups.hasOwnProperty(t)||(this.groups[t]=e),this.amountOfGroups+=1},s.prototype.updateGroup=function(t,e){this.groups[t]=e},s.prototype.removeGroup=function(t){this.groups.hasOwnProperty(t)&&(delete this.groups[t],this.amountOfGroups-=1)},s.prototype._create=function(){this.dom.frame=document.createElement("div"),this.dom.frame.className="legend",this.dom.frame.style.position="absolute",this.dom.frame.style.top="10px",this.dom.frame.style.display="block",this.dom.textArea=document.createElement("div"),this.dom.textArea.className="legendText",this.dom.textArea.style.position="relative",this.dom.textArea.style.top="0px",this.svg=document.createElementNS("http://www.w3.org/2000/svg","svg"),this.svg.style.position="absolute",this.svg.style.top="0px",this.svg.style.width=this.options.iconSize+5+"px",this.dom.frame.appendChild(this.svg),this.dom.frame.appendChild(this.dom.textArea)},s.prototype.hide=function(){this.dom.frame.parentNode&&this.dom.frame.parentNode.removeChild(this.dom.frame)},s.prototype.show=function(){this.dom.frame.parentNode||this.body.dom.center.appendChild(this.dom.frame)},s.prototype.setOptions=function(t){var e=["enabled","orientation","icons","left","right"];o.selectiveDeepExtend(e,this.options,t)},s.prototype.redraw=function(){var t=0;for(var e in this.groups)this.groups.hasOwnProperty(e)&&1==this.groups[e].visible&&t++;if(0==this.options[this.side].visible||0==this.amountOfGroups||0==this.options.enabled||0==t)this.hide();else{this.show(),"top-left"==this.options[this.side].position||"bottom-left"==this.options[this.side].position?(this.dom.frame.style.left="4px",this.dom.frame.style.textAlign="left",this.dom.textArea.style.textAlign="left",this.dom.textArea.style.left=this.options.iconSize+15+"px",this.dom.textArea.style.right="",this.svg.style.left="0px",this.svg.style.right=""):(this.dom.frame.style.right="4px",this.dom.frame.style.textAlign="right",this.dom.textArea.style.textAlign="right",this.dom.textArea.style.right=this.options.iconSize+15+"px",this.dom.textArea.style.left="",this.svg.style.right="0px",this.svg.style.left=""),"top-left"==this.options[this.side].position||"top-right"==this.options[this.side].position?(this.dom.frame.style.top=4-Number(this.body.dom.center.style.top.replace("px",""))+"px",this.dom.frame.style.bottom=""):(this.dom.frame.style.bottom=4-Number(this.body.dom.center.style.top.replace("px",""))+"px",this.dom.frame.style.top=""),0==this.options.icons?(this.dom.frame.style.width=this.dom.textArea.offsetWidth+10+"px",this.dom.textArea.style.right="",this.dom.textArea.style.left="",this.svg.style.width="0px"):(this.dom.frame.style.width=this.options.iconSize+15+this.dom.textArea.offsetWidth+10+"px",this.drawLegendIcons()); +var i="";for(var e in this.groups)this.groups.hasOwnProperty(e)&&1==this.groups[e].visible&&(i+=this.groups[e].content+"
");this.dom.textArea.innerHTML=i,this.dom.textArea.style.lineHeight=.75*this.options.iconSize+this.options.iconSpacing+"px"}},s.prototype.drawLegendIcons=function(){if(this.dom.frame.parentNode){n.prepareElements(this.svgElements);var t=window.getComputedStyle(this.dom.frame).paddingTop,e=Number(t.replace("px","")),i=e,s=this.options.iconSize,o=.75*this.options.iconSize,r=e+.5*o+3;this.svg.style.width=s+5+e+"px";for(var a in this.groups)this.groups.hasOwnProperty(a)&&1==this.groups[a].visible&&(this.groups[a].drawIcon(i,r,this.svgElements,this.svg,s,o),r+=o+this.options.iconSpacing);n.cleanupElements(this.svgElements)}},t.exports=s},function(t,e,i){function s(t,e){this.id=o.randomUUID(),this.body=t,this.defaultOptions={yAxisOrientation:"left",defaultGroup:"default",sort:!0,sampling:!0,graphHeight:"400px",shaded:{enabled:!1,orientation:"bottom"},style:"line",barChart:{width:50,allowOverlap:!0,align:"center"},catmullRom:{enabled:!0,parametrization:"centripetal",alpha:.5},drawPoints:{enabled:!0,size:6,style:"square"},dataAxis:{showMinorLabels:!0,showMajorLabels:!0,icons:!1,width:"40px",visible:!0},legend:{enabled:!1,icons:!0,left:{visible:!0,position:"top-left"},right:{visible:!0,position:"top-right"}}},this.options=o.extend({},this.defaultOptions),this.dom={},this.props={},this.hammer=null,this.groups={};var i=this;this.itemsData=null,this.groupsData=null,this.itemListeners={add:function(t,e){i._onAdd(e.items)},update:function(t,e){i._onUpdate(e.items)},remove:function(t,e){i._onRemove(e.items)}},this.groupListeners={add:function(t,e){i._onAddGroups(e.items)},update:function(t,e){i._onUpdateGroups(e.items)},remove:function(t,e){i._onRemoveGroups(e.items)}},this.items={},this.selection=[],this.lastStart=this.body.range.start,this.touchParams={},this.svgElements={},this.setOptions(e),this.groupsUsingDefaultStyles=[0],this.body.emitter.on("rangechange",function(){if(0!=i.lastStart){var t=i.body.range.start-i.lastStart,e=i.body.range.end-i.body.range.start;if(0!=i.width){var s=i.width/e,o=t*s;i.svg.style.left=-i.width-o+"px"}}}),this.body.emitter.on("rangechanged",function(){i.lastStart=i.body.range.start,i.svg.style.left=o.option.asSize(-i.width),i._updateGraph.apply(i)}),this._create(),this.body.emitter.emit("change")}var o=i(1),n=i(2),r=i(3),a=i(4),h=i(18),d=i(21),l=i(22),c=i(25),p="__ungrouped__";s.prototype=new h,s.prototype._create=function(){var t=document.createElement("div");t.className="LineGraph",this.dom.frame=t,this.svg=document.createElementNS("http://www.w3.org/2000/svg","svg"),this.svg.style.position="relative",this.svg.style.height=(""+this.options.graphHeight).replace("px","")+"px",this.svg.style.display="block",t.appendChild(this.svg),this.options.dataAxis.orientation="left",this.yAxisLeft=new d(this.body,this.options.dataAxis,this.svg),this.options.dataAxis.orientation="right",this.yAxisRight=new d(this.body,this.options.dataAxis,this.svg),delete this.options.dataAxis.orientation,this.legendLeft=new c(this.body,this.options.legend,"left"),this.legendRight=new c(this.body,this.options.legend,"right"),this.show()},s.prototype.setOptions=function(t){if(t){var e=["sampling","defaultGroup","graphHeight","yAxisOrientation","style","barChart","dataAxis","sort"];o.selectiveDeepExtend(e,this.options,t),o.mergeOptions(this.options,t,"catmullRom"),o.mergeOptions(this.options,t,"drawPoints"),o.mergeOptions(this.options,t,"shaded"),o.mergeOptions(this.options,t,"legend"),t.catmullRom&&"object"==typeof t.catmullRom&&t.catmullRom.parametrization&&("uniform"==t.catmullRom.parametrization?this.options.catmullRom.alpha=0:"chordal"==t.catmullRom.parametrization?this.options.catmullRom.alpha=1:(this.options.catmullRom.parametrization="centripetal",this.options.catmullRom.alpha=.5)),this.yAxisLeft&&void 0!==t.dataAxis&&(this.yAxisLeft.setOptions(this.options.dataAxis),this.yAxisRight.setOptions(this.options.dataAxis)),this.legendLeft&&void 0!==t.legend&&(this.legendLeft.setOptions(this.options.legend),this.legendRight.setOptions(this.options.legend)),this.groups.hasOwnProperty(p)&&this.groups[p].setOptions(t)}this.dom.frame&&this._updateGraph()},s.prototype.hide=function(){this.dom.frame.parentNode&&this.dom.frame.parentNode.removeChild(this.dom.frame)},s.prototype.show=function(){this.dom.frame.parentNode||this.body.dom.center.appendChild(this.dom.frame)},s.prototype.setItems=function(t){var e,i=this,s=this.itemsData;if(t){if(!(t instanceof r||t instanceof a))throw new TypeError("Data must be an instance of DataSet or DataView");this.itemsData=t}else this.itemsData=null;if(s&&(o.forEach(this.itemListeners,function(t,e){s.off(e,t)}),e=s.getIds(),this._onRemove(e)),this.itemsData){var n=this.id;o.forEach(this.itemListeners,function(t,e){i.itemsData.on(e,t,n)}),e=this.itemsData.getIds(),this._onAdd(e)}this._updateUngrouped(),this._updateGraph(),this.redraw()},s.prototype.setGroups=function(t){var e,i=this;if(this.groupsData&&(o.forEach(this.groupListeners,function(t,e){i.groupsData.unsubscribe(e,t)}),e=this.groupsData.getIds(),this.groupsData=null,this._onRemoveGroups(e)),t){if(!(t instanceof r||t instanceof a))throw new TypeError("Data must be an instance of DataSet or DataView");this.groupsData=t}else this.groupsData=null;if(this.groupsData){var s=this.id;o.forEach(this.groupListeners,function(t,e){i.groupsData.on(e,t,s)}),e=this.groupsData.getIds(),this._onAddGroups(e)}this._onUpdate()},s.prototype._onUpdate=function(){this._updateUngrouped(),this._updateAllGroupData(),this._updateGraph(),this.redraw()},s.prototype._onAdd=function(t){this._onUpdate(t)},s.prototype._onRemove=function(t){this._onUpdate(t)},s.prototype._onUpdateGroups=function(t){for(var e=0;e0){for(s=0;su){e.push(g);break}e.push(g)}}else for(var m=0;mp&&g.x0?(i=this._preprocessData(e,t),h.push({min:i.min,max:i.max}),r.push(i.data)):(h.push({}),r.push([]))}else h.push({}),r.push([]);if(d=this._updateYAxis(l,h),1==d)return n.cleanupElements(this.svgElements),void this.body.emitter.emit("change");for(s=0;s0){for(var p=0;pi?i:a,d=s>d?s:d):(r=!0,h=h>i?i:h,l=s>l?s:l))}1==n&&this.yAxisLeft.setRange(a,d),1==r&&this.yAxisRight.setRange(h,l)}return o=this._toggleAxisVisiblity(n,this.yAxisLeft)||o,o=this._toggleAxisVisiblity(r,this.yAxisRight)||o,1==r&&1==n?(this.yAxisLeft.drawIcons=!0,this.yAxisRight.drawIcons=!0):(this.yAxisLeft.drawIcons=!1,this.yAxisRight.drawIcons=!1),this.yAxisRight.master=!n,0==this.yAxisRight.master?(this.yAxisLeft.lineOffset=1==r?this.yAxisRight.width:0,o=this.yAxisLeft.redraw()||o,this.yAxisRight.stepPixelsForced=this.yAxisLeft.stepPixels,o=this.yAxisRight.redraw()||o):o=this.yAxisRight.redraw()||o,o},s.prototype._toggleAxisVisiblity=function(t,e){var i=!1;return 0==t?e.dom.frame.parentNode&&(e.hide(),i=!0):e.dom.frame.parentNode||(e.show(),i=!0),i},s.prototype._drawBarGraph=function(t,e){if(null!=t&&t.length>0){for(var i,s=.1*e.options.barChart.width,o=0,r={},a=0;a0&&(i=Math.min(i,Math.abs(t[a-1].x-t[a].x))),0==i&&(void 0===r[t[a].x]&&(r[t[a].x]={amount:0,resolved:0}),r[t[a].x].amount+=1);for(var h,a=0;a0&&(i=Math.min(i,Math.abs(t[a-1].x-h)));var d=this._getSafeDrawData(i,e,s)}else{var l=a+(r[h].amount-r[h].resolved),c=a-(r[h].resolved+1);l0&&(i=Math.min(i,Math.abs(t[c].x-h)));var d=this._getSafeDrawData(i,e,s);r[h].resolved+=1,0==e.options.barChart.allowOverlap&&(d.width=d.width/r[h].amount,d.offset+=r[h].resolved*d.width-.5*d.width*(r[h].amount+1),"left"==e.options.barChart.align?o-=.5*d.width:"right"==e.options.barChart.align&&(o+=.5*d.width))}n.drawBar(t[a].x+d.offset,t[a].y,d.width,e.zeroPosition-t[a].y,e.className+" bar",this.svgElements,this.svg),1==e.options.drawPoints.enabled&&n.drawPoint(t[a].x+d.offset,t[a].y,e,this.svgElements,this.svg)}}},s.prototype._getSafeDrawData=function(t,e,i){var s,o;return t0?(s=i>t?i:t,o=0,e.options.slots&&(s/=e.options.slots.total,o=e.options.slots.slot*s-.5*s*(e.options.slots.total+1)),"left"==e.options.barChart.align?o-=.5*t:"right"==e.options.barChart.align&&(o+=.5*t)):(s=e.options.barChart.width,o=0,e.options.slots&&(s/=e.options.slots.total,o=e.options.slots.slot*s-.5*s*(e.options.slots.total+1)),"left"==e.options.barChart.align?o-=.5*e.options.barChart.width:"right"==e.options.barChart.align&&(o+=.5*e.options.barChart.width)),{width:s,offset:o}},s.prototype._drawLineGraph=function(t,e){if(null!=t&&t.length>0){var i,s,o=Number(this.svg.style.height.replace("px",""));if(i=n.getSVGElement("path",this.svgElements,this.svg),i.setAttributeNS(null,"class",e.className),s=1==e.options.catmullRom.enabled?this._catmullRom(t,e):this._linear(t),1==e.options.shaded.enabled){var r,a=n.getSVGElement("path",this.svgElements,this.svg);r="top"==e.options.shaded.orientation?"M"+t[0].x+",0 "+s+"L"+t[t.length-1].x+",0":"M"+t[0].x+","+o+" "+s+"L"+t[t.length-1].x+","+o,a.setAttributeNS(null,"class",e.className+" fill"),a.setAttributeNS(null,"d",r)}i.setAttributeNS(null,"d","M"+s),1==e.options.drawPoints.enabled&&this._drawPoints(t,e,this.svgElements,this.svg)}},s.prototype._drawPoints=function(t,e,i,s,o){void 0===o&&(o=0);for(var r=0;rp;p+=r)i=n(t[p].x)+this.width-1,s=t[p].y,o.push({x:i,y:s}),h=h>s?s:h,d=s>d?s:d;return{min:h,max:d,data:o}},s.prototype._convertYvalues=function(t,e){var i,s,o=[],n=this.yAxisLeft,r=Number(this.svg.style.height.replace("px",""));"right"==e.options.yAxisOrientation&&(n=this.yAxisRight);for(var a=0;al;l++)e=0==l?t[0]:t[l-1],i=t[l],s=t[l+1],o=d>l+2?t[l+2]:s,n={x:(-e.x+6*i.x+s.x)*h,y:(-e.y+6*i.y+s.y)*h},r={x:(i.x+6*s.x-o.x)*h,y:(i.y+6*s.y-o.y)*h},a+="C"+n.x+","+n.y+" "+r.x+","+r.y+" "+s.x+","+s.y+" ";return a},s.prototype._catmullRom=function(t,e){var i=e.options.catmullRom.alpha;if(0==i||void 0===i)return this._catmullRomUniform(t);for(var s,o,n,r,a,h,d,l,c,p,u,f,m,g,v,y,b,_,x,w=Math.round(t[0].x)+","+Math.round(t[0].y)+" ",S=t.length,M=0;S-1>M;M++)s=0==M?t[0]:t[M-1],o=t[M],n=t[M+1],r=S>M+2?t[M+2]:n,d=Math.sqrt(Math.pow(s.x-o.x,2)+Math.pow(s.y-o.y,2)),l=Math.sqrt(Math.pow(o.x-n.x,2)+Math.pow(o.y-n.y,2)),c=Math.sqrt(Math.pow(n.x-r.x,2)+Math.pow(n.y-r.y,2)),g=Math.pow(c,i),y=Math.pow(c,2*i),v=Math.pow(l,i),b=Math.pow(l,2*i),x=Math.pow(d,i),_=Math.pow(d,2*i),p=2*_+3*x*v+b,u=2*y+3*g*v+b,f=3*x*(x+v),f>0&&(f=1/f),m=3*g*(g+v),m>0&&(m=1/m),a={x:(-b*s.x+p*o.x+_*n.x)*f,y:(-b*s.y+p*o.y+_*n.y)*f},h={x:(y*o.x+u*n.x-b*r.x)*m,y:(y*o.y+u*n.y-b*r.y)*m},0==a.x&&0==a.y&&(a=o),0==h.x&&0==h.y&&(h=n),w+="C"+a.x+","+a.y+" "+h.x+","+h.y+" "+n.x+","+n.y+" ";return w},s.prototype._linear=function(t){for(var e="",i=0;id;){d++;var l=n.getCurrent(),c=this.body.util.toScreen(l),p=n.isMajor();this.options.showMinorLabels&&this._repaintMinorText(c,n.getLabelMinor(),t),p&&this.options.showMajorLabels?(c>0&&(void 0==h&&(h=c),this._repaintMajorText(c,n.getLabelMajor(),t)),this._repaintMajorLine(c,t)):this._repaintMinorLine(c,t),n.next()}if(this.options.showMajorLabels){var u=this.body.util.toTime(0),f=n.getLabelMajor(u),m=f.length*(this.props.majorCharWidth||10)+10;(void 0==h||h>m)&&this._repaintMajorText(0,f,t)}o.forEach(this.dom.redundant,function(t){for(;t.length;){var e=t.pop();e&&e.parentNode&&e.parentNode.removeChild(e)}})},s.prototype._repaintMinorText=function(t,e,i){var s=this.dom.redundant.minorTexts.shift();if(!s){var o=document.createTextNode("");s=document.createElement("div"),s.appendChild(o),s.className="text minor",this.dom.foreground.appendChild(s)}this.dom.minorTexts.push(s),s.childNodes[0].nodeValue=e,s.style.top="top"==i?this.props.majorLabelHeight+"px":"0",s.style.left=t+"px"},s.prototype._repaintMajorText=function(t,e,i){var s=this.dom.redundant.majorTexts.shift();if(!s){var o=document.createTextNode(e);s=document.createElement("div"),s.className="text major",s.appendChild(o),this.dom.foreground.appendChild(s)}this.dom.majorTexts.push(s),s.childNodes[0].nodeValue=e,s.style.top="top"==i?"0":this.props.minorLabelHeight+"px",s.style.left=t+"px"},s.prototype._repaintMinorLine=function(t,e){var i=this.dom.redundant.minorLines.shift();i||(i=document.createElement("div"),i.className="grid vertical minor",this.dom.background.appendChild(i)),this.dom.minorLines.push(i);var s=this.props;i.style.top="top"==e?s.majorLabelHeight+"px":this.body.domProps.top.height+"px",i.style.height=s.minorLineHeight+"px",i.style.left=t-s.minorLineWidth/2+"px"},s.prototype._repaintMajorLine=function(t,e){var i=this.dom.redundant.majorLines.shift();i||(i=document.createElement("DIV"),i.className="grid vertical major",this.dom.background.appendChild(i)),this.dom.majorLines.push(i);var s=this.props;i.style.top="top"==e?"0":this.body.domProps.top.height+"px",i.style.left=t-s.majorLineWidth/2+"px",i.style.height=s.majorLineHeight+"px"},s.prototype._calculateCharSize=function(){this.dom.measureCharMinor||(this.dom.measureCharMinor=document.createElement("DIV"),this.dom.measureCharMinor.className="text minor measure",this.dom.measureCharMinor.style.position="absolute",this.dom.measureCharMinor.appendChild(document.createTextNode("0")),this.dom.foreground.appendChild(this.dom.measureCharMinor)),this.props.minorCharHeight=this.dom.measureCharMinor.clientHeight,this.props.minorCharWidth=this.dom.measureCharMinor.clientWidth,this.dom.measureCharMajor||(this.dom.measureCharMajor=document.createElement("DIV"),this.dom.measureCharMajor.className="text minor measure",this.dom.measureCharMajor.style.position="absolute",this.dom.measureCharMajor.appendChild(document.createTextNode("0")),this.dom.foreground.appendChild(this.dom.measureCharMajor)),this.props.majorCharHeight=this.dom.measureCharMajor.clientHeight,this.props.majorCharWidth=this.dom.measureCharMajor.clientWidth},s.prototype.snap=function(t){return this.step.snap(t)},t.exports=s},function(t,e,i){function s(t,e,i){this.id=null,this.parent=null,this.data=t,this.dom=null,this.conversion=e||{},this.options=i||{},this.selected=!1,this.displayed=!1,this.dirty=!0,this.top=null,this.left=null,this.width=null,this.height=null}var o=i(41);s.prototype.select=function(){this.selected=!0,this.displayed&&this.redraw()},s.prototype.unselect=function(){this.selected=!1,this.displayed&&this.redraw()},s.prototype.setParent=function(t){this.displayed?(this.hide(),this.parent=t,this.parent&&this.show()):this.parent=t},s.prototype.isVisible=function(){return!1},s.prototype.show=function(){return!1},s.prototype.hide=function(){return!1},s.prototype.redraw=function(){},s.prototype.repositionX=function(){},s.prototype.repositionY=function(){},s.prototype._repaintDeleteButton=function(t){if(this.selected&&this.options.editable.remove&&!this.dom.deleteButton){var e=this,i=document.createElement("div");i.className="delete",i.title="Delete this item",o(i,{preventDefault:!0}).on("tap",function(t){e.parent.removeFromDataSet(e),t.stopPropagation()}),t.appendChild(i),this.dom.deleteButton=i}else!this.selected&&this.dom.deleteButton&&(this.dom.deleteButton.parentNode&&this.dom.deleteButton.parentNode.removeChild(this.dom.deleteButton),this.dom.deleteButton=null)},t.exports=s},function(t,e,i){function s(t,e,i){if(this.props={dot:{width:0,height:0},line:{width:0,height:0}},t&&void 0==t.start)throw new Error('Property "start" missing in item '+t);o.call(this,t,e,i)}var o=i(28);s.prototype=new o(null,null,null),s.prototype.isVisible=function(t){var e=(t.end-t.start)/4;return this.data.start>t.start-e&&this.data.startt.start-e&&this.data.startt.start},s.prototype.redraw=function(){var t=this.dom;if(t||(this.dom={},t=this.dom,t.box=document.createElement("div"),t.content=document.createElement("div"),t.content.className="content",t.box.appendChild(t.content),t.box["timeline-item"]=this),!this.parent)throw new Error("Cannot redraw item: no parent attached");if(!t.box.parentNode){var e=this.parent.dom.foreground;if(!e)throw new Error("Cannot redraw time axis: parent has no foreground container element");e.appendChild(t.box)}if(this.displayed=!0,this.data.content!=this.content){if(this.content=this.data.content,this.content instanceof Element)t.content.innerHTML="",t.content.appendChild(this.content);else{if(void 0==this.data.content)throw new Error('Property "content" missing in item '+this.data.id);t.content.innerHTML=this.content}this.dirty=!0}this.data.title!=this.title&&(t.box.title=this.data.title,this.title=this.data.title);var i=(this.data.className?" "+this.data.className:"")+(this.selected?" selected":"");this.className!=i&&(this.className=i,t.box.className=this.baseClassName+i,this.dirty=!0),this.dirty&&(this.overflow="hidden"!==window.getComputedStyle(t.content).overflow,this.props.content.width=this.dom.content.offsetWidth,this.height=this.dom.box.offsetHeight,this.dirty=!1),this._repaintDeleteButton(t.box),this._repaintDragLeft(),this._repaintDragRight()},s.prototype.show=function(){this.displayed||this.redraw()},s.prototype.hide=function(){if(this.displayed){var t=this.dom.box;t.parentNode&&t.parentNode.removeChild(t),this.top=null,this.left=null,this.displayed=!1}},s.prototype.repositionX=function(){var t,e=this.props,i=this.parent.width,s=this.conversion.toScreen(this.data.start),o=this.conversion.toScreen(this.data.end),n=this.options.padding;-i>s&&(s=-i),o>2*i&&(o=2*i);var r=Math.max(o-s,1);this.overflow?(t=Math.max(-s,0),this.left=s,this.width=r+this.props.content.width):(t=0>s?Math.min(-s,o-s-e.content.width-2*n):0,this.left=s,this.width=r),this.dom.box.style.left=this.left+"px",this.dom.box.style.width=r+"px",this.dom.content.style.left=t+"px"},s.prototype.repositionY=function(){var t=this.options.orientation,e=this.dom.box;e.style.top="top"==t?this.top+"px":this.parent.height-this.top-this.height+"px"},s.prototype._repaintDragLeft=function(){if(this.selected&&this.options.editable.updateTime&&!this.dom.dragLeft){var t=document.createElement("div");t.className="drag-left",t.dragLeftItem=this,o(t,{preventDefault:!0}).on("drag",function(){}),this.dom.box.appendChild(t),this.dom.dragLeft=t}else!this.selected&&this.dom.dragLeft&&(this.dom.dragLeft.parentNode&&this.dom.dragLeft.parentNode.removeChild(this.dom.dragLeft),this.dom.dragLeft=null)},s.prototype._repaintDragRight=function(){if(this.selected&&this.options.editable.updateTime&&!this.dom.dragRight){var t=document.createElement("div");t.className="drag-right",t.dragRightItem=this,o(t,{preventDefault:!0}).on("drag",function(){}),this.dom.box.appendChild(t),this.dom.dragRight=t}else!this.selected&&this.dom.dragRight&&(this.dom.dragRight.parentNode&&this.dom.dragRight.parentNode.removeChild(this.dom.dragRight),this.dom.dragRight=null) +},t.exports=s},function(t,e,i){function s(t,e,i){if(!(this instanceof s))throw new SyntaxError("Constructor must be called with the new operator");this._initializeMixinLoaders(),this.containerElement=t,this.renderRefreshRate=60,this.renderTimestep=1e3/this.renderRefreshRate,this.renderTime=.5*this.renderTimestep,this.maxPhysicsTicksPerRender=3,this.physicsDiscreteStepsize=.5,this.initializing=!0,this.triggerFunctions={add:null,edit:null,editEdge:null,connect:null,del:null},this.defaultOptions={nodes:{mass:1,radiusMin:10,radiusMax:30,radius:10,shape:"ellipse",image:void 0,widthMin:16,widthMax:64,fixed:!1,fontColor:"black",fontSize:14,fontFace:"verdana",level:-1,color:{border:"#2B7CE9",background:"#97C2FC",highlight:{border:"#2B7CE9",background:"#D2E5FF"},hover:{border:"#2B7CE9",background:"#D2E5FF"}},borderColor:"#2B7CE9",backgroundColor:"#97C2FC",highlightColor:"#D2E5FF",group:void 0,borderWidth:1},edges:{widthMin:1,widthMax:15,width:1,widthSelectionMultiplier:2,hoverWidth:1.5,style:"line",color:{color:"#848484",highlight:"#848484",hover:"#848484"},fontColor:"#343434",fontSize:14,fontFace:"arial",fontFill:"white",arrowScaleFactor:1,dash:{length:10,gap:5,altLength:void 0},inheritColor:"from"},configurePhysics:!1,physics:{barnesHut:{enabled:!0,theta:1/.6,gravitationalConstant:-2e3,centralGravity:.3,springLength:95,springConstant:.04,damping:.09},repulsion:{centralGravity:0,springLength:200,springConstant:.05,nodeDistance:100,damping:.09},hierarchicalRepulsion:{enabled:!1,centralGravity:0,springLength:100,springConstant:.01,nodeDistance:150,damping:.09},damping:null,centralGravity:null,springLength:null,springConstant:null},clustering:{enabled:!1,initialMaxNodes:100,clusterThreshold:500,reduceToNodes:300,chainThreshold:.4,clusterEdgeThreshold:20,sectorThreshold:100,screenSizeThreshold:.2,fontSizeMultiplier:4,maxFontSize:1e3,forceAmplification:.1,distanceAmplification:.1,edgeGrowth:20,nodeScaling:{width:1,height:1,radius:1},maxNodeSizeIncrements:600,activeAreaBoxSize:80,clusterLevelDifference:2},navigation:{enabled:!1},keyboard:{enabled:!1,speed:{x:10,y:10,zoom:.02}},dataManipulation:{enabled:!1,initiallyVisible:!1},hierarchicalLayout:{enabled:!1,levelSeparation:150,nodeSpacing:100,direction:"UD"},freezeForStabilization:!1,smoothCurves:{enabled:!0,dynamic:!0,type:"continuous",roundness:.5},dynamicSmoothCurves:!0,maxVelocity:30,minVelocity:.1,stabilize:!0,stabilizationIterations:1e3,labels:{add:"Add Node",edit:"Edit",link:"Add Link",del:"Delete selected",editNode:"Edit Node",editEdge:"Edit Edge",back:"Back",addDescription:"Click in an empty space to place a new node.",linkDescription:"Click on a node and drag the edge to another node to connect them.",editEdgeDescription:"Click on the control points and drag them to a node to connect to it.",addError:"The function for add does not support two arguments (data,callback).",linkError:"The function for connect does not support two arguments (data,callback).",editError:"The function for edit does not support two arguments (data, callback).",editBoundError:"No edit function has been bound to this button.",deleteError:"The function for delete does not support two arguments (data, callback).",deleteClusterError:"Clusters cannot be deleted."},tooltip:{delay:300,fontColor:"black",fontSize:14,fontFace:"verdana",color:{border:"#666",background:"#FFFFC6"}},dragNetwork:!0,dragNodes:!0,zoomable:!0,hover:!1,hideEdgesOnDrag:!1,hideNodesOnDrag:!1,width:"100%",height:"100%",selectable:!0},this.constants=a.extend({},this.defaultOptions),this.hoverObj={nodes:{},edges:{}},this.controlNodesActive=!1;var o=this;this.groups=new u,this.images=new f,this.images.setOnloadCallback(function(){o._redraw()}),this.xIncrement=0,this.yIncrement=0,this.zoomIncrement=0,this._loadPhysicsSystem(),this._create(),this._loadSectorSystem(),this._loadClusterSystem(),this._loadSelectionSystem(),this._loadHierarchySystem(),this._setTranslation(this.frame.clientWidth/2,this.frame.clientHeight/2),this._setScale(1),this.setOptions(i),this.freezeSimulation=!1,this.cachedFunctions={},this.calculationNodes={},this.calculationNodeIndices=[],this.nodeIndices=[],this.nodes={},this.edges={},this.canvasTopLeft={x:0,y:0},this.canvasBottomRight={x:0,y:0},this.pointerPosition={x:0,y:0},this.areaCenter={},this.scale=1,this.previousScale=this.scale,this.nodesData=null,this.edgesData=null,this.nodesListeners={add:function(t,e){o._addNodes(e.items),o.start()},update:function(t,e){o._updateNodes(e.items),o.start()},remove:function(t,e){o._removeNodes(e.items),o.start()}},this.edgesListeners={add:function(t,e){o._addEdges(e.items),o.start()},update:function(t,e){o._updateEdges(e.items),o.start()},remove:function(t,e){o._removeEdges(e.items),o.start()}},this.moving=!0,this.timer=void 0,this.setData(e,this.constants.clustering.enabled||this.constants.hierarchicalLayout.enabled),this.initializing=!1,1==this.constants.hierarchicalLayout.enabled?this._setupHierarchicalLayout():0==this.constants.stabilize&&this.zoomExtent(!0,this.constants.clustering.enabled),this.constants.clustering.enabled&&this.startWithClustering()}var o=i(46),n=i(41),r=i(49),a=i(1),h=i(43),d=i(3),l=i(4),c=i(38),p=i(39),u=i(34),f=i(35),m=i(36),g=i(33),v=i(37),y=i(45);i(44),o(s.prototype),s.prototype._getScriptPath=function(){for(var t=document.getElementsByTagName("script"),e=0;et.x&&(s=t.x),ot.y&&(e=t.y),i=this.constants.clustering.initialMaxNodes?49.07548/(o+142.05338)+91444e-8:12.662/(o+7.4147)+.0964822:1==this.constants.clustering.enabled&&o>=this.constants.clustering.initialMaxNodes?77.5271985/(o+187.266146)+476710517e-13:30.5062972/(o+19.93597763)+.08413486;var n=Math.min(this.frame.canvas.clientWidth/600,this.frame.canvas.clientHeight/600);i*=n}else{var r=1.1*(Math.abs(s.minX)+Math.abs(s.maxX)),a=1.1*(Math.abs(s.minY)+Math.abs(s.maxY)),h=this.frame.canvas.clientWidth/r,d=this.frame.canvas.clientHeight/a;i=d>=h?h:d}i>1&&(i=1),this._setScale(i),this._centerNetwork(s),0==e&&(this.moving=!0,this.start())},s.prototype._updateNodeIndexList=function(){this._clearNodeIndexList();for(var t in this.nodes)this.nodes.hasOwnProperty(t)&&this.nodeIndices.push(t)},s.prototype.setData=function(t,e){if(void 0===e&&(e=!1),t&&t.dot&&(t.nodes||t.edges))throw new SyntaxError('Data must contain either parameter "dot" or parameter pair "nodes" and "edges", but not both.');if(this.setOptions(t&&t.options),t&&t.dot){if(t&&t.dot){var i=c.DOTToGraph(t.dot);return void this.setData(i)}}else if(t&&t.gephi){if(t&&t.gephi){var s=p.parseGephi(t.gephi);return void this.setData(s)}}else this._setNodes(t&&t.nodes),this._setEdges(t&&t.edges);if(this._putDataInSector(),!e)if(this.constants.stabilize){var o=this;setTimeout(function(){o._stabilize(),o.start()},0)}else this.start()},s.prototype.setOptions=function(t){if(t){var e,i=["nodes","edges","smoothCurves","hierarchicalLayout","clustering","navigation","keyboard","dataManipulation","onAdd","onEdit","onEditEdge","onConnect","onDelete"];if(a.selectiveNotDeepExtend(i,this.constants,t),a.selectiveNotDeepExtend(["color"],this.constants.nodes,t.nodes),a.selectiveNotDeepExtend(["color","length"],this.constants.edges,t.edges),t.physics&&(a.mergeOptions(this.constants.physics,t.physics,"barnesHut"),a.mergeOptions(this.constants.physics,t.physics,"repulsion"),t.physics.hierarchicalRepulsion)){this.constants.hierarchicalLayout.enabled=!0,this.constants.physics.hierarchicalRepulsion.enabled=!0,this.constants.physics.barnesHut.enabled=!1;for(e in t.physics.hierarchicalRepulsion)t.physics.hierarchicalRepulsion.hasOwnProperty(e)&&(this.constants.physics.hierarchicalRepulsion[e]=t.physics.hierarchicalRepulsion[e])}if(t.onAdd&&(this.triggerFunctions.add=t.onAdd),t.onEdit&&(this.triggerFunctions.edit=t.onEdit),t.onEditEdge&&(this.triggerFunctions.editEdge=t.onEditEdge),t.onConnect&&(this.triggerFunctions.connect=t.onConnect),t.onDelete&&(this.triggerFunctions.del=t.onDelete),a.mergeOptions(this.constants,t,"smoothCurves"),a.mergeOptions(this.constants,t,"hierarchicalLayout"),a.mergeOptions(this.constants,t,"clustering"),a.mergeOptions(this.constants,t,"navigation"),a.mergeOptions(this.constants,t,"keyboard"),a.mergeOptions(this.constants,t,"dataManipulation"),t.dataManipulation&&(this.editMode=this.constants.dataManipulation.initiallyVisible),t.edges&&(void 0!==t.edges.color&&(a.isString(t.edges.color)?(this.constants.edges.color={},this.constants.edges.color.color=t.edges.color,this.constants.edges.color.highlight=t.edges.color,this.constants.edges.color.hover=t.edges.color):(void 0!==t.edges.color.color&&(this.constants.edges.color.color=t.edges.color.color),void 0!==t.edges.color.highlight&&(this.constants.edges.color.highlight=t.edges.color.highlight),void 0!==t.edges.color.hover&&(this.constants.edges.color.hover=t.edges.color.hover))),t.edges.fontColor||void 0!==t.edges.color&&(a.isString(t.edges.color)?this.constants.edges.fontColor=t.edges.color:void 0!==t.edges.color.color&&(this.constants.edges.fontColor=t.edges.color.color))),t.nodes&&t.nodes.color){var s=a.parseColor(t.nodes.color);this.constants.nodes.color.background=s.background,this.constants.nodes.color.border=s.border,this.constants.nodes.color.highlight.background=s.highlight.background,this.constants.nodes.color.highlight.border=s.highlight.border,this.constants.nodes.color.hover.background=s.hover.background,this.constants.nodes.color.hover.border=s.hover.border}if(t.groups)for(var o in t.groups)if(t.groups.hasOwnProperty(o)){var n=t.groups[o];this.groups.add(o,n)}if(t.tooltip){for(e in t.tooltip)t.tooltip.hasOwnProperty(e)&&(this.constants.tooltip[e]=t.tooltip[e]);t.tooltip.color&&(this.constants.tooltip.color=a.parseColor(t.tooltip.color))}}this._loadPhysicsSystem(),this._loadNavigationControls(),this._loadManipulationSystem(),this._configureSmoothCurves(),this._createKeyBinds(),this.setSize(this.constants.width,this.constants.height),this.moving=!0,this.start()},s.prototype._create=function(){for(;this.containerElement.hasChildNodes();)this.containerElement.removeChild(this.containerElement.firstChild);if(this.frame=document.createElement("div"),this.frame.className="network-frame",this.frame.style.position="relative",this.frame.style.overflow="hidden",this.frame.canvas=document.createElement("canvas"),this.frame.canvas.style.position="relative",this.frame.appendChild(this.frame.canvas),!this.frame.canvas.getContext){var t=document.createElement("DIV");t.style.color="red",t.style.fontWeight="bold",t.style.padding="10px",t.innerHTML="Error: your browser does not support HTML canvas",this.frame.canvas.appendChild(t)}var e=this;this.drag={},this.pinch={},this.hammer=n(this.frame.canvas,{prevent_default:!0}),this.hammer.on("tap",e._onTap.bind(e)),this.hammer.on("doubletap",e._onDoubleTap.bind(e)),this.hammer.on("hold",e._onHold.bind(e)),this.hammer.on("pinch",e._onPinch.bind(e)),this.hammer.on("touch",e._onTouch.bind(e)),this.hammer.on("dragstart",e._onDragStart.bind(e)),this.hammer.on("drag",e._onDrag.bind(e)),this.hammer.on("dragend",e._onDragEnd.bind(e)),this.hammer.on("release",e._onRelease.bind(e)),this.hammer.on("mousewheel",e._onMouseWheel.bind(e)),this.hammer.on("DOMMouseScroll",e._onMouseWheel.bind(e)),this.hammer.on("mousemove",e._onMouseMoveTitle.bind(e)),this.containerElement.appendChild(this.frame)},s.prototype._createKeyBinds=function(){var t=this;this.mousetrap=r,this.mousetrap.reset(),1==this.constants.keyboard.enabled&&(this.mousetrap.bind("up",this._moveUp.bind(t),"keydown"),this.mousetrap.bind("up",this._yStopMoving.bind(t),"keyup"),this.mousetrap.bind("down",this._moveDown.bind(t),"keydown"),this.mousetrap.bind("down",this._yStopMoving.bind(t),"keyup"),this.mousetrap.bind("left",this._moveLeft.bind(t),"keydown"),this.mousetrap.bind("left",this._xStopMoving.bind(t),"keyup"),this.mousetrap.bind("right",this._moveRight.bind(t),"keydown"),this.mousetrap.bind("right",this._xStopMoving.bind(t),"keyup"),this.mousetrap.bind("=",this._zoomIn.bind(t),"keydown"),this.mousetrap.bind("=",this._stopZoom.bind(t),"keyup"),this.mousetrap.bind("-",this._zoomOut.bind(t),"keydown"),this.mousetrap.bind("-",this._stopZoom.bind(t),"keyup"),this.mousetrap.bind("[",this._zoomIn.bind(t),"keydown"),this.mousetrap.bind("[",this._stopZoom.bind(t),"keyup"),this.mousetrap.bind("]",this._zoomOut.bind(t),"keydown"),this.mousetrap.bind("]",this._stopZoom.bind(t),"keyup"),this.mousetrap.bind("pageup",this._zoomIn.bind(t),"keydown"),this.mousetrap.bind("pageup",this._stopZoom.bind(t),"keyup"),this.mousetrap.bind("pagedown",this._zoomOut.bind(t),"keydown"),this.mousetrap.bind("pagedown",this._stopZoom.bind(t),"keyup")),1==this.constants.dataManipulation.enabled&&(this.mousetrap.bind("escape",this._createManipulatorBar.bind(t)),this.mousetrap.bind("del",this._deleteSelected.bind(t)))},s.prototype._getPointer=function(t){return{x:t.pageX-a.getAbsoluteLeft(this.frame.canvas),y:t.pageY-a.getAbsoluteTop(this.frame.canvas)}},s.prototype._onTouch=function(t){this.drag.pointer=this._getPointer(t.gesture.center),this.drag.pinched=!1,this.pinch.scale=this._getScale(),this._handleTouch(this.drag.pointer)},s.prototype._onDragStart=function(){this._handleDragStart()},s.prototype._handleDragStart=function(){var t=this.drag,e=this._getNodeAt(t.pointer);if(t.dragging=!0,t.selection=[],t.translation=this._getTranslation(),t.nodeId=null,null!=e){t.nodeId=e.id,e.isSelected()||this._selectObject(e,!1);for(var i in this.selectionObj.nodes)if(this.selectionObj.nodes.hasOwnProperty(i)){var s=this.selectionObj.nodes[i],o={id:s.id,node:s,x:s.x,y:s.y,xFixed:s.xFixed,yFixed:s.yFixed};s.xFixed=!0,s.yFixed=!0,t.selection.push(o)}}},s.prototype._onDrag=function(t){this._handleOnDrag(t)},s.prototype._handleOnDrag=function(t){if(!this.drag.pinched){var e=this._getPointer(t.gesture.center),i=this,s=this.drag,o=s.selection;if(o&&o.length&&1==this.constants.dragNodes){var n=e.x-s.pointer.x,r=e.y-s.pointer.y;o.forEach(function(t){var e=t.node;t.xFixed||(e.x=i._XconvertDOMtoCanvas(i._XconvertCanvasToDOM(t.x)+n)),t.yFixed||(e.y=i._YconvertDOMtoCanvas(i._YconvertCanvasToDOM(t.y)+r))}),this.moving||(this.moving=!0,this.start())}else if(1==this.constants.dragNetwork){var a=e.x-this.drag.pointer.x,h=e.y-this.drag.pointer.y;this._setTranslation(this.drag.translation.x+a,this.drag.translation.y+h),this._redraw()}}},s.prototype._onDragEnd=function(){this.drag.dragging=!1;var t=this.drag.selection;t&&t.length?(t.forEach(function(t){t.node.xFixed=t.xFixed,t.node.yFixed=t.yFixed}),this.moving=!0,this.start()):this._redraw()},s.prototype._onTap=function(t){var e=this._getPointer(t.gesture.center);this.pointerPosition=e,this._handleTap(e)},s.prototype._onDoubleTap=function(t){var e=this._getPointer(t.gesture.center);this._handleDoubleTap(e)},s.prototype._onHold=function(t){var e=this._getPointer(t.gesture.center);this.pointerPosition=e,this._handleOnHold(e)},s.prototype._onRelease=function(t){var e=this._getPointer(t.gesture.center);this._handleOnRelease(e)},s.prototype._onPinch=function(t){var e=this._getPointer(t.gesture.center);this.drag.pinched=!0,"scale"in this.pinch||(this.pinch.scale=1);var i=this.pinch.scale*t.gesture.scale;this._zoom(i,e)},s.prototype._zoom=function(t,e){if(1==this.constants.zoomable){var i=this._getScale();1e-5>t&&(t=1e-5),t>10&&(t=10);var s=null;void 0!==this.drag&&1==this.drag.dragging&&(s=this.DOMtoCanvas(this.drag.pointer));var o=this._getTranslation(),n=t/i,r=(1-n)*e.x+o.x*n,a=(1-n)*e.y+o.y*n;if(this.areaCenter={x:this._XconvertDOMtoCanvas(e.x),y:this._YconvertDOMtoCanvas(e.y)},this._setScale(t),this._setTranslation(r,a),this.updateClustersDefault(),null!=s){var h=this.canvasToDOM(s);this.drag.pointer.x=h.x,this.drag.pointer.y=h.y}return this._redraw(),t>i?this.emit("zoom",{direction:"+"}):this.emit("zoom",{direction:"-"}),t}},s.prototype._onMouseWheel=function(t){var e=0;if(t.wheelDelta?e=t.wheelDelta/120:t.detail&&(e=-t.detail/3),e){var i=this._getScale(),s=e/10;0>e&&(s/=1-s),i*=1+s;var o=h.fakeGesture(this,t),n=this._getPointer(o.center);this._zoom(i,n)}t.preventDefault()},s.prototype._onMouseMoveTitle=function(t){var e=h.fakeGesture(this,t),i=this._getPointer(e.center);this.popupObj&&this._checkHidePopup(i);var s=this,o=function(){s._checkShowPopup(i)};if(this.popupTimer&&clearInterval(this.popupTimer),this.drag.dragging||(this.popupTimer=setTimeout(o,this.constants.tooltip.delay)),1==this.constants.hover){for(var n in this.hoverObj.edges)this.hoverObj.edges.hasOwnProperty(n)&&(this.hoverObj.edges[n].hover=!1,delete this.hoverObj.edges[n]);var r=this._getNodeAt(i);null==r&&(r=this._getEdgeAt(i)),null!=r&&this._hoverObject(r);for(var a in this.hoverObj.nodes)this.hoverObj.nodes.hasOwnProperty(a)&&(r instanceof m&&r.id!=a||r instanceof g||null==r)&&(this._blurObject(this.hoverObj.nodes[a]),delete this.hoverObj.nodes[a]);this.redraw()}},s.prototype._checkShowPopup=function(t){var e,i={left:this._XconvertDOMtoCanvas(t.x),top:this._YconvertDOMtoCanvas(t.y),right:this._XconvertDOMtoCanvas(t.x),bottom:this._YconvertDOMtoCanvas(t.y)},s=this.popupObj;if(void 0==this.popupObj){var o=this.nodes;for(e in o)if(o.hasOwnProperty(e)){var n=o[e];if(void 0!==n.getTitle()&&n.isOverlappingWith(i)){this.popupObj=n;break}}}if(void 0===this.popupObj){var r=this.edges;for(e in r)if(r.hasOwnProperty(e)){var a=r[e];if(a.connected&&void 0!==a.getTitle()&&a.isOverlappingWith(i)){this.popupObj=a;break}}}if(this.popupObj){if(this.popupObj!=s){var h=this;h.popup||(h.popup=new v(h.frame,h.constants.tooltip)),h.popup.setPosition(t.x-3,t.y-3),h.popup.setText(h.popupObj.getTitle()),h.popup.show()}}else this.popup&&this.popup.hide()},s.prototype._checkHidePopup=function(t){this.popupObj&&this._getNodeAt(t)||(this.popupObj=void 0,this.popup&&this.popup.hide())},s.prototype.setSize=function(t,e){this.frame.style.width=t,this.frame.style.height=e,this.frame.canvas.style.width="100%",this.frame.canvas.style.height="100%",this.frame.canvas.width=this.frame.canvas.clientWidth,this.frame.canvas.height=this.frame.canvas.clientHeight,void 0!==this.manipulationDiv&&(this.manipulationDiv.style.width=this.frame.canvas.clientWidth+"px"),void 0!==this.navigationDivs&&void 0!==this.navigationDivs.wrapper&&(this.navigationDivs.wrapper.style.width=this.frame.canvas.clientWidth+"px",this.navigationDivs.wrapper.style.height=this.frame.canvas.clientHeight+"px"),this.emit("resize",{width:this.frame.canvas.width,height:this.frame.canvas.height})},s.prototype._setNodes=function(t){var e=this.nodesData;if(t instanceof d||t instanceof l)this.nodesData=t;else if(t instanceof Array)this.nodesData=new d,this.nodesData.add(t);else{if(t)throw new TypeError("Array or DataSet expected");this.nodesData=new d}if(e&&a.forEach(this.nodesListeners,function(t,i){e.off(i,t)}),this.nodes={},this.nodesData){var i=this;a.forEach(this.nodesListeners,function(t,e){i.nodesData.on(e,t)});var s=this.nodesData.getIds();this._addNodes(s)}this._updateSelection()},s.prototype._addNodes=function(t){for(var e,i=0,s=t.length;s>i;i++){e=t[i];var o=this.nodesData.get(e),n=new m(o,this.images,this.groups,this.constants);if(this.nodes[e]=n,!(0!=n.xFixed&&0!=n.yFixed||null!==n.x&&null!==n.y)){var r=1*t.length+10,a=2*Math.PI*Math.random();0==n.xFixed&&(n.x=r*Math.cos(a)),0==n.yFixed&&(n.y=r*Math.sin(a))}this.moving=!0}this._updateNodeIndexList(),1==this.constants.hierarchicalLayout.enabled&&0==this.initializing&&(this._resetLevels(),this._setupHierarchicalLayout()),this._updateCalculationNodes(),this._reconnectEdges(),this._updateValueRange(this.nodes),this.updateLabels()},s.prototype._updateNodes=function(t){for(var e=this.nodes,i=this.nodesData,s=0,o=t.length;o>s;s++){var n=t[s],r=e[n],a=i.get(n);r?r.setProperties(a,this.constants):(r=new m(properties,this.images,this.groups,this.constants),e[n]=r)}this.moving=!0,1==this.constants.hierarchicalLayout.enabled&&0==this.initializing&&(this._resetLevels(),this._setupHierarchicalLayout()),this._updateNodeIndexList(),this._reconnectEdges(),this._updateValueRange(e)},s.prototype._removeNodes=function(t){for(var e=this.nodes,i=0,s=t.length;s>i;i++){var o=t[i];delete e[o]}this._updateNodeIndexList(),1==this.constants.hierarchicalLayout.enabled&&0==this.initializing&&(this._resetLevels(),this._setupHierarchicalLayout()),this._updateCalculationNodes(),this._reconnectEdges(),this._updateSelection(),this._updateValueRange(e)},s.prototype._setEdges=function(t){var e=this.edgesData;if(t instanceof d||t instanceof l)this.edgesData=t;else if(t instanceof Array)this.edgesData=new d,this.edgesData.add(t);else{if(t)throw new TypeError("Array or DataSet expected");this.edgesData=new d}if(e&&a.forEach(this.edgesListeners,function(t,i){e.off(i,t)}),this.edges={},this.edgesData){var i=this;a.forEach(this.edgesListeners,function(t,e){i.edgesData.on(e,t)});var s=this.edgesData.getIds();this._addEdges(s)}this._reconnectEdges()},s.prototype._addEdges=function(t){for(var e=this.edges,i=this.edgesData,s=0,o=t.length;o>s;s++){var n=t[s],r=e[n];r&&r.disconnect();var a=i.get(n,{showInternalIds:!0});e[n]=new g(a,this,this.constants)}this.moving=!0,this._updateValueRange(e),this._createBezierNodes(),1==this.constants.hierarchicalLayout.enabled&&0==this.initializing&&(this._resetLevels(),this._setupHierarchicalLayout()),this._updateCalculationNodes()},s.prototype._updateEdges=function(t){for(var e=this.edges,i=this.edgesData,s=0,o=t.length;o>s;s++){var n=t[s],r=i.get(n),a=e[n];a?(a.disconnect(),a.setProperties(r,this.constants),a.connect()):(a=new g(r,this,this.constants),this.edges[n]=a)}this._createBezierNodes(),1==this.constants.hierarchicalLayout.enabled&&0==this.initializing&&(this._resetLevels(),this._setupHierarchicalLayout()),this.moving=!0,this._updateValueRange(e)},s.prototype._removeEdges=function(t){for(var e=this.edges,i=0,s=t.length;s>i;i++){var o=t[i],n=e[o];n&&(null!=n.via&&delete this.sectors.support.nodes[n.via.id],n.disconnect(),delete e[o])}this.moving=!0,this._updateValueRange(e),1==this.constants.hierarchicalLayout.enabled&&0==this.initializing&&(this._resetLevels(),this._setupHierarchicalLayout()),this._updateCalculationNodes()},s.prototype._reconnectEdges=function(){var t,e=this.nodes,i=this.edges;for(t in e)e.hasOwnProperty(t)&&(e[t].edges=[]);for(t in i)if(i.hasOwnProperty(t)){var s=i[t];s.from=null,s.to=null,s.connect()}},s.prototype._updateValueRange=function(t){var e,i=void 0,s=void 0;for(e in t)if(t.hasOwnProperty(e)){var o=t[e].getValue();void 0!==o&&(i=void 0===i?o:Math.min(o,i),s=void 0===s?o:Math.max(o,s))}if(void 0!==i&&void 0!==s)for(e in t)t.hasOwnProperty(e)&&t[e].setValueRange(i,s)},s.prototype.redraw=function(){this.setSize(this.constants.width,this.constants.height),this._redraw()},s.prototype._redraw=function(){var t=this.frame.canvas.getContext("2d"),e=this.frame.canvas.width,i=this.frame.canvas.height;t.clearRect(0,0,e,i),t.save(),t.translate(this.translation.x,this.translation.y),t.scale(this.scale,this.scale),this.canvasTopLeft={x:this._XconvertDOMtoCanvas(0),y:this._YconvertDOMtoCanvas(0)},this.canvasBottomRight={x:this._XconvertDOMtoCanvas(this.frame.canvas.clientWidth),y:this._YconvertDOMtoCanvas(this.frame.canvas.clientHeight)},this._doInAllSectors("_drawAllSectorNodes",t),(0==this.drag.dragging||void 0===this.drag.dragging||0==this.constants.hideEdgesOnDrag)&&this._doInAllSectors("_drawEdges",t),(0==this.drag.dragging||void 0===this.drag.dragging||0==this.constants.hideNodesOnDrag)&&this._doInAllSectors("_drawNodes",t,!1),1==this.controlNodesActive&&this._doInAllSectors("_drawControlNodes",t),t.restore()},s.prototype._setTranslation=function(t,e){void 0===this.translation&&(this.translation={x:0,y:0}),void 0!==t&&(this.translation.x=t),void 0!==e&&(this.translation.y=e),this.emit("viewChanged")},s.prototype._getTranslation=function(){return{x:this.translation.x,y:this.translation.y}},s.prototype._setScale=function(t){this.scale=t},s.prototype._getScale=function(){return this.scale},s.prototype._XconvertDOMtoCanvas=function(t){return(t-this.translation.x)/this.scale},s.prototype._XconvertCanvasToDOM=function(t){return t*this.scale+this.translation.x},s.prototype._YconvertDOMtoCanvas=function(t){return(t-this.translation.y)/this.scale},s.prototype._YconvertCanvasToDOM=function(t){return t*this.scale+this.translation.y},s.prototype.canvasToDOM=function(t){return{x:this._XconvertCanvasToDOM(t.x),y:this._YconvertCanvasToDOM(t.y)}},s.prototype.DOMtoCanvas=function(t){return{x:this._XconvertDOMtoCanvas(t.x),y:this._YconvertDOMtoCanvas(t.y)}},s.prototype._drawNodes=function(t,e){void 0===e&&(e=!1);var i=this.nodes,s=[];for(var o in i)i.hasOwnProperty(o)&&(i[o].setScaleAndPos(this.scale,this.canvasTopLeft,this.canvasBottomRight),i[o].isSelected()?s.push(o):(i[o].inArea()||e)&&i[o].draw(t));for(var n=0,r=s.length;r>n;n++)(i[s[n]].inArea()||e)&&i[s[n]].draw(t)},s.prototype._drawEdges=function(t){var e=this.edges;for(var i in e)if(e.hasOwnProperty(i)){var s=e[i];s.setScale(this.scale),s.connected&&e[i].draw(t)}},s.prototype._drawControlNodes=function(t){var e=this.edges;for(var i in e)e.hasOwnProperty(i)&&e[i]._drawControlNodes(t)},s.prototype._stabilize=function(){1==this.constants.freezeForStabilization&&this._freezeDefinedNodes();for(var t=0;this.moving&&t0)for(e in s)s.hasOwnProperty(e)&&(s[e].discreteStepLimited(i,this.constants.maxVelocity),o=!0);else for(e in s)s.hasOwnProperty(e)&&(s[e].discreteStep(i),o=!0);if(1==o&&(void 0===t||1==t)){var n=this.constants.minVelocity/Math.max(this.scale,.05);n>.5*this.constants.maxVelocity?this.moving=!0:(this.moving=this._isMoving(n),0==this.moving&&this.emit("stabilized",{iterations:null}),this.moving=this.moving||this.configurePhysics)}},s.prototype._physicsTick=function(){this.freezeSimulation||1==this.moving&&(this._doInAllActiveSectors("_initializeForceCalculation"),this._doInAllActiveSectors("_discreteStepNodes"),1==this.constants.smoothCurves.enabled&&1==this.constants.smoothCurves.dynamic&&this._doInSupportSector("_discreteStepNodes",!1),this._findCenter(this._getRange()))},s.prototype._animationStep=function(){this.timer=void 0,this._handleNavigation(),this.start();var t=Date.now(),e=1;this._physicsTick();for(var i=Date.now()-t;i<.9*(this.renderTimestep-this.renderTime)&&eh}return!1},s.prototype._getColor=function(){var t=this.options.color;return"to"==this.options.inheritColor?t={highlight:this.to.options.color.highlight.border,hover:this.to.options.color.hover.border,color:this.to.options.color.border}:("from"==this.options.inheritColor||1==this.options.inheritColor)&&(t={highlight:this.from.options.color.highlight.border,hover:this.from.options.color.hover.border,color:this.from.options.color.border}),1==this.selected?t.highlight:1==this.hover?t.hover:t.color},s.prototype._drawLine=function(t){if(t.strokeStyle=this._getColor(),t.lineWidth=this._getLineWidth(),this.from!=this.to){var e,i=this._line(t);if(this.label){if(1==this.options.smoothCurves.enabled&&null!=i){var s=.5*(.5*(this.from.x+i.x)+.5*(this.to.x+i.x)),o=.5*(.5*(this.from.y+i.y)+.5*(this.to.y+i.y));e={x:s,y:o}}else e=this._pointOnLine(.5);this._label(t,this.label,e.x,e.y)}}else{var n,r,a=this.physics.springLength/4,h=this.from;h.width||h.resize(t),h.width>h.height?(n=h.x+h.width/2,r=h.y-a):(n=h.x+a,r=h.y-h.height/2),this._circle(t,n,r,a),e=this._pointOnCircle(n,r,a,.5),this._label(t,this.label,e.x,e.y)}},s.prototype._getLineWidth=function(){return 1==this.selected?Math.min(this.widthSelected,this.options.widthMax)*this.networkScaleInv:1==this.hover?Math.min(this.options.hoverWidth,this.options.widthMax)*this.networkScaleInv:this.options.width*this.networkScaleInv},s.prototype._getViaCoordinates=function(){var t=null,e=null,i=this.options.smoothCurves.roundness,s=this.options.smoothCurves.type,o=Math.abs(this.from.x-this.to.x),n=Math.abs(this.from.y-this.to.y);return"discrete"==s||"diagonalCross"==s?Math.abs(this.from.x-this.to.x)this.to.y?this.from.xthis.to.x&&(t=this.from.x-i*n,e=this.from.y-i*n):this.from.ythis.to.x&&(t=this.from.x-i*n,e=this.from.y+i*n)),"discrete"==s&&(t=i*n>o?this.from.x:t)):Math.abs(this.from.x-this.to.x)>Math.abs(this.from.y-this.to.y)&&(this.from.y>this.to.y?this.from.xthis.to.x&&(t=this.from.x-i*o,e=this.from.y-i*o):this.from.ythis.to.x&&(t=this.from.x-i*o,e=this.from.y+i*o)),"discrete"==s&&(e=i*o>n?this.from.y:e)):"straightCross"==s?Math.abs(this.from.x-this.to.x)Math.abs(this.from.y-this.to.y)&&(t=this.from.xthis.to.y?this.from.xthis.to.x&&(t=this.from.x-i*n,e=this.from.y-i*n,t=this.to.x>t?this.to.x:t):this.from.ythis.to.x&&(t=this.from.x-i*n,e=this.from.y+i*n,t=this.to.x>t?this.to.x:t)):Math.abs(this.from.x-this.to.x)>Math.abs(this.from.y-this.to.y)&&(this.from.y>this.to.y?this.from.xe?this.to.y:e):this.from.x>this.to.x&&(t=this.from.x-i*o,e=this.from.y-i*o,e=this.to.y>e?this.to.y:e):this.from.ythis.to.x&&(t=this.from.x-i*o,e=this.from.y+i*o,e=this.to.yl.height?(a=l.x+.5*l.width,h=l.y-d):(a=l.x+d,h=l.y-.5*l.height),this._circle(t,a,h,d);var s=.2*Math.PI,o=(10+5*this.options.width)*this.options.arrowScaleFactor;e=this._pointOnCircle(a,h,d,.5),t.arrow(e.x,e.y,s,o),t.fill(),t.stroke(),this.label&&(e=this._pointOnCircle(a,h,d,.5),this._label(t,this.label,e.x,e.y))}},s.prototype._drawArrow=function(t){1==this.selected?(t.strokeStyle=this.options.color.highlight,t.fillStyle=this.options.color.highlight):1==this.hover?(t.strokeStyle=this.options.color.hover,t.fillStyle=this.options.color.hover):(t.strokeStyle=this.options.color.color,t.fillStyle=this.options.color.color),t.lineWidth=this._getLineWidth();var e,i;if(this.from!=this.to){e=Math.atan2(this.to.y-this.from.y,this.to.x-this.from.x);var s,o=this.to.x-this.from.x,n=this.to.y-this.from.y,r=Math.sqrt(o*o+n*n),a=this.from.distanceToBorder(t,e+Math.PI),h=(r-a)/r,d=h*this.from.x+(1-h)*this.to.x,l=h*this.from.y+(1-h)*this.to.y;1==this.options.smoothCurves.dynamic&&1==this.options.smoothCurves.enabled?s=this.via:1==this.options.smoothCurves.enabled&&(s=this._getViaCoordinates()),1==this.options.smoothCurves.enabled&&null!=s.x&&(e=Math.atan2(this.to.y-s.y,this.to.x-s.x),o=this.to.x-s.x,n=this.to.y-s.y,r=Math.sqrt(o*o+n*n));var c,p,u=this.to.distanceToBorder(t,e),f=(r-u)/r;if(1==this.options.smoothCurves.enabled&&null!=s.x?(c=(1-f)*s.x+f*this.to.x,p=(1-f)*s.y+f*this.to.y):(c=(1-f)*this.from.x+f*this.to.x,p=(1-f)*this.from.y+f*this.to.y),t.beginPath(),t.moveTo(d,l),1==this.options.smoothCurves.enabled&&null!=s.x?t.quadraticCurveTo(s.x,s.y,c,p):t.lineTo(c,p),t.stroke(),i=(10+5*this.options.width)*this.options.arrowScaleFactor,t.arrow(c,p,e,i),t.fill(),t.stroke(),this.label){var m;if(1==this.options.smoothCurves.enabled&&null!=s){var g=.5*(.5*(this.from.x+s.x)+.5*(this.to.x+s.x)),v=.5*(.5*(this.from.y+s.y)+.5*(this.to.y+s.y));m={x:g,y:v}}else m=this._pointOnLine(.5);this._label(t,this.label,m.x,m.y)}}else{var y,b,_,x=this.from,w=.25*Math.max(100,this.physics.springLength);x.width||x.resize(t),x.width>x.height?(y=x.x+.5*x.width,b=x.y-w,_={x:y,y:x.y,angle:.9*Math.PI}):(y=x.x+w,b=x.y-.5*x.height,_={x:x.x,y:b,angle:.6*Math.PI}),t.beginPath(),t.arc(y,b,w,0,2*Math.PI,!1),t.stroke();var i=(10+5*this.options.width)*this.options.arrowScaleFactor;t.arrow(_.x,_.y,_.angle,i),t.fill(),t.stroke(),this.label&&(m=this._pointOnCircle(y,b,w,.5),this._label(t,this.label,m.x,m.y))}},s.prototype._getDistanceToEdge=function(t,e,i,s,o,n){if(this.from!=this.to){if(1==this.options.smoothCurves.enabled){var r,a;if(1==this.options.smoothCurves.enabled&&1==this.options.smoothCurves.dynamic)r=this.via.x,a=this.via.y;else{var h=this._getViaCoordinates();r=h.x,a=h.y}var d,l,c,p,u,f,m,g=1e9;for(l=0;10>l;l++)c=.1*l,p=Math.pow(1-c,2)*t+2*c*(1-c)*r+Math.pow(c,2)*i,u=Math.pow(1-c,2)*e+2*c*(1-c)*a+Math.pow(c,2)*s,l>0&&(d=this._getDistanceToLine(f,m,p,u,o,n),g=g>d?d:g),f=p,m=u;return g}return this._getDistanceToLine(t,e,i,s,o,n)}var p,u,v,y,b=this.physics.springLength/4,_=this.from;return _.width||_.resize(ctx),_.width>_.height?(p=_.x+_.width/2,u=_.y-b):(p=_.x+b,u=_.y-_.height/2),v=p-o,y=u-n,Math.abs(Math.sqrt(v*v+y*y)-b)},s.prototype._getDistanceToLine=function(t,e,i,s,o,n){var r=i-t,a=s-e,h=r*r+a*a,d=((o-t)*r+(n-e)*a)/h;d>1?d=1:0>d&&(d=0);var l=t+d*r,c=e+d*a,p=l-o,u=c-n;return Math.sqrt(p*p+u*u)},s.prototype.setScale=function(t){this.networkScaleInv=1/t},s.prototype.select=function(){this.selected=!0},s.prototype.unselect=function(){this.selected=!1},s.prototype.positionBezierNode=function(){null!==this.via&&null!==this.from&&null!==this.to&&(this.via.x=.5*(this.from.x+this.to.x),this.via.y=.5*(this.from.y+this.to.y))},s.prototype._drawControlNodes=function(t){if(1==this.controlNodesEnabled){if(null===this.controlNodes.from&&null===this.controlNodes.to){var e="edgeIdFrom:".concat(this.id),i="edgeIdTo:".concat(this.id),s={nodes:{group:"",radius:8},physics:{damping:0},clustering:{maxNodeSizeIncrements:0,nodeScaling:{width:0,height:0,radius:0}}};this.controlNodes.from=new n({id:e,shape:"dot",color:{background:"#ff4e00",border:"#3c3c3c",highlight:{background:"#07f968"}}},{},{},s),this.controlNodes.to=new n({id:i,shape:"dot",color:{background:"#ff4e00",border:"#3c3c3c",highlight:{background:"#07f968"}}},{},{},s)}0==this.controlNodes.from.selected&&0==this.controlNodes.to.selected&&(this.controlNodes.positions=this.getControlNodePositions(t),this.controlNodes.from.x=this.controlNodes.positions.from.x,this.controlNodes.from.y=this.controlNodes.positions.from.y,this.controlNodes.to.x=this.controlNodes.positions.to.x,this.controlNodes.to.y=this.controlNodes.positions.to.y),this.controlNodes.from.draw(t),this.controlNodes.to.draw(t)}else this.controlNodes={from:null,to:null,positions:{}}},s.prototype._enableControlNodes=function(){this.controlNodesEnabled=!0},s.prototype._disableControlNodes=function(){this.controlNodesEnabled=!1},s.prototype._getSelectedControlNode=function(t,e){var i=this.controlNodes.positions,s=Math.sqrt(Math.pow(t-i.from.x,2)+Math.pow(e-i.from.y,2)),o=Math.sqrt(Math.pow(t-i.to.x,2)+Math.pow(e-i.to.y,2));return 15>s?(this.connectedNode=this.from,this.from=this.controlNodes.from,this.controlNodes.from):15>o?(this.connectedNode=this.to,this.to=this.controlNodes.to,this.controlNodes.to):null},s.prototype._restoreControlNodes=function(){1==this.controlNodes.from.selected&&(this.from=this.connectedNode,this.connectedNode=null,this.controlNodes.from.unselect()),1==this.controlNodes.to.selected&&(this.to=this.connectedNode,this.connectedNode=null,this.controlNodes.to.unselect())},s.prototype.getControlNodePositions=function(t){var e,i=Math.atan2(this.to.y-this.from.y,this.to.x-this.from.x),s=this.to.x-this.from.x,o=this.to.y-this.from.y,n=Math.sqrt(s*s+o*o),r=this.from.distanceToBorder(t,i+Math.PI),a=(n-r)/n,h=a*this.from.x+(1-a)*this.to.x,d=a*this.from.y+(1-a)*this.to.y;1==this.options.smoothCurves.dynamic&&1==this.options.smoothCurves.enabled?e=this.via:1==this.options.smoothCurves.enabled&&(e=this._getViaCoordinates()),1==this.options.smoothCurves.enabled&&null!=e.x&&(i=Math.atan2(this.to.y-e.y,this.to.x-e.x),s=this.to.x-e.x,o=this.to.y-e.y,n=Math.sqrt(s*s+o*o));var l,c,p=this.to.distanceToBorder(t,i),u=(n-p)/n;return 1==this.options.smoothCurves.enabled&&null!=e.x?(l=(1-u)*e.x+u*this.to.x,c=(1-u)*e.y+u*this.to.y):(l=(1-u)*this.from.x+u*this.to.x,c=(1-u)*this.from.y+u*this.to.y),{from:{x:h,y:d},to:{x:l,y:c}}},t.exports=s},function(t,e,i){function s(){this.clear(),this.defaultIndex=0}var o=i(1);s.DEFAULT=[{border:"#2B7CE9",background:"#97C2FC",highlight:{border:"#2B7CE9",background:"#D2E5FF"},hover:{border:"#2B7CE9",background:"#D2E5FF"}},{border:"#FFA500",background:"#FFFF00",highlight:{border:"#FFA500",background:"#FFFFA3"},hover:{border:"#FFA500",background:"#FFFFA3"}},{border:"#FA0A10",background:"#FB7E81",highlight:{border:"#FA0A10",background:"#FFAFB1"},hover:{border:"#FA0A10",background:"#FFAFB1"}},{border:"#41A906",background:"#7BE141",highlight:{border:"#41A906",background:"#A1EC76"},hover:{border:"#41A906",background:"#A1EC76"}},{border:"#E129F0",background:"#EB7DF4",highlight:{border:"#E129F0",background:"#F0B3F5"},hover:{border:"#E129F0",background:"#F0B3F5"}},{border:"#7C29F0",background:"#AD85E4",highlight:{border:"#7C29F0",background:"#D3BDF0"},hover:{border:"#7C29F0",background:"#D3BDF0"}},{border:"#C37F00",background:"#FFA807",highlight:{border:"#C37F00",background:"#FFCA66"},hover:{border:"#C37F00",background:"#FFCA66"}},{border:"#4220FB",background:"#6E6EFD",highlight:{border:"#4220FB",background:"#9B9BFD"},hover:{border:"#4220FB",background:"#9B9BFD"}},{border:"#FD5A77",background:"#FFC0CB",highlight:{border:"#FD5A77",background:"#FFD1D9"},hover:{border:"#FD5A77",background:"#FFD1D9"}},{border:"#4AD63A",background:"#C2FABC",highlight:{border:"#4AD63A",background:"#E6FFE3"},hover:{border:"#4AD63A",background:"#E6FFE3"}}],s.prototype.clear=function(){this.groups={},this.groups.length=function(){var t=0;for(var e in this)this.hasOwnProperty(e)&&t++;return t}},s.prototype.get=function(t){var e=this.groups[t];if(void 0==e){var i=this.defaultIndex%s.DEFAULT.length;this.defaultIndex++,e={},e.color=s.DEFAULT[i],this.groups[t]=e}return e},s.prototype.add=function(t,e){return this.groups[t]=e,e.color&&(e.color=o.parseColor(e.color)),e},t.exports=s},function(t){function e(){this.images={},this.callback=void 0}e.prototype.setOnloadCallback=function(t){this.callback=t},e.prototype.load=function(t){var e=this.images[t];if(void 0==e){var i=this;e=new Image,this.images[t]=e,e.onload=function(){i.callback&&i.callback(this)},e.src=t}return e},t.exports=e},function(t,e,i){function s(t,e,i,s){var n=o.selectiveBridgeObject(["nodes"],s);this.options=n.nodes,this.selected=!1,this.hover=!1,this.edges=[],this.dynamicEdges=[],this.reroutedEdges={},this.fontDrawThreshold=3,this.id=void 0,this.x=null,this.y=null,this.xFixed=!1,this.yFixed=!1,this.horizontalAlignLeft=!0,this.verticalAlignTop=!0,this.baseRadiusValue=s.nodes.radius,this.radiusFixed=!1,this.level=-1,this.preassignedLevel=!1,this.imagelist=e,this.grouplist=i,this.fx=0,this.fy=0,this.vx=0,this.vy=0,this.damping=s.physics.damping,this.fixedData={x:null,y:null},this.setProperties(t,n),this.resetCluster(),this.dynamicEdgesLength=0,this.clusterSession=0,this.clusterSizeWidthFactor=s.clustering.nodeScaling.width,this.clusterSizeHeightFactor=s.clustering.nodeScaling.height,this.clusterSizeRadiusFactor=s.clustering.nodeScaling.radius,this.maxNodeSizeIncrements=s.clustering.maxNodeSizeIncrements,this.growthIndicator=0,this.networkScaleInv=1,this.networkScale=1,this.canvasTopLeft={x:-300,y:-300},this.canvasBottomRight={x:300,y:300},this.parentEdgeId=null}var o=i(1);s.prototype.resetCluster=function(){this.formationScale=void 0,this.clusterSize=1,this.containedNodes={},this.containedEdges={},this.clusterSessions=[]},s.prototype.attachEdge=function(t){-1==this.edges.indexOf(t)&&this.edges.push(t),-1==this.dynamicEdges.indexOf(t)&&this.dynamicEdges.push(t),this.dynamicEdgesLength=this.dynamicEdges.length},s.prototype.detachEdge=function(t){var e=this.edges.indexOf(t);-1!=e&&(this.edges.splice(e,1),this.dynamicEdges.splice(e,1)),this.dynamicEdgesLength=this.dynamicEdges.length},s.prototype.setProperties=function(t,e){if(t){var i=["borderWidth","borderWidthSelected","shape","image","radius","fontColor","fontSize","fontFace","group","mass"];if(o.selectiveDeepExtend(i,this.options,t),this.originalLabel=void 0,void 0!==t.id&&(this.id=t.id),void 0!==t.label&&(this.label=t.label,this.originalLabel=t.label),void 0!==t.title&&(this.title=t.title),void 0!==t.x&&(this.x=t.x),void 0!==t.y&&(this.y=t.y),void 0!==t.value&&(this.value=t.value),void 0!==t.level&&(this.level=t.level,this.preassignedLevel=!0),void 0!==t.horizontalAlignLeft&&(this.horizontalAlignLeft=t.horizontalAlignLeft),void 0!==t.verticalAlignTop&&(this.verticalAlignTop=t.verticalAlignTop),void 0!==t.triggerFunction&&(this.triggerFunction=t.triggerFunction),void 0===this.id)throw"Node must have an id";if("number"==typeof this.options.group||"string"==typeof this.options.group&&""!=this.options.group){var s=this.grouplist.get(this.options.group);for(var n in s)s.hasOwnProperty(n)&&(this.options[n]=s[n])}if(void 0!==t.radius&&(this.baseRadiusValue=this.options.radius),void 0!==t.color&&(this.options.color=o.parseColor(t.color)),void 0!==this.options.image&&""!=this.options.image){if(!this.imagelist)throw"No imagelist provided";this.imageObj=this.imagelist.load(this.options.image)}switch(this.xFixed=this.xFixed||void 0!==t.x&&!t.allowedToMoveX,this.yFixed=this.yFixed||void 0!==t.y&&!t.allowedToMoveY,this.radiusFixed=this.radiusFixed||void 0!==t.radius,"image"==this.options.shape&&(this.options.radiusMin=e.nodes.widthMin,this.options.radiusMax=e.nodes.widthMax),this.options.shape){case"database":this.draw=this._drawDatabase,this.resize=this._resizeDatabase;break;case"box":this.draw=this._drawBox,this.resize=this._resizeBox;break;case"circle":this.draw=this._drawCircle,this.resize=this._resizeCircle;break;case"ellipse":this.draw=this._drawEllipse,this.resize=this._resizeEllipse;break;case"image":this.draw=this._drawImage,this.resize=this._resizeImage;break;case"text":this.draw=this._drawText,this.resize=this._resizeText;break;case"dot":this.draw=this._drawDot,this.resize=this._resizeShape;break;case"square":this.draw=this._drawSquare,this.resize=this._resizeShape;break;case"triangle":this.draw=this._drawTriangle,this.resize=this._resizeShape;break;case"triangleDown":this.draw=this._drawTriangleDown,this.resize=this._resizeShape;break;case"star":this.draw=this._drawStar,this.resize=this._resizeShape;break;default:this.draw=this._drawEllipse,this.resize=this._resizeEllipse}this._reset()}},s.prototype.select=function(){this.selected=!0,this._reset()},s.prototype.unselect=function(){this.selected=!1,this._reset()},s.prototype.clearSizeCache=function(){this._reset()},s.prototype._reset=function(){this.width=void 0,this.height=void 0},s.prototype.getTitle=function(){return"function"==typeof this.title?this.title():this.title},s.prototype.distanceToBorder=function(t,e){var i=1;switch(this.width||this.resize(t),this.options.shape){case"circle":case"dot":return this.options.radius+i;case"ellipse":var s=this.width/2,o=this.height/2,n=Math.sin(e)*s,r=Math.cos(e)*o;return s*o/Math.sqrt(n*n+r*r);case"box":case"image":case"text":default:return this.width?Math.min(Math.abs(this.width/2/Math.cos(e)),Math.abs(this.height/2/Math.sin(e)))+i:0}},s.prototype._setForce=function(t,e){this.fx=t,this.fy=e},s.prototype._addForce=function(t,e){this.fx+=t,this.fy+=e},s.prototype.discreteStep=function(t){if(!this.xFixed){var e=this.damping*this.vx,i=(this.fx-e)/this.options.mass;this.vx+=i*t,this.x+=this.vx*t}if(!this.yFixed){var s=this.damping*this.vy,o=(this.fy-s)/this.options.mass;this.vy+=o*t,this.y+=this.vy*t}},s.prototype.discreteStepLimited=function(t,e){if(this.xFixed)this.fx=0;else{var i=this.damping*this.vx,s=(this.fx-i)/this.options.mass;this.vx+=s*t,this.vx=Math.abs(this.vx)>e?this.vx>0?e:-e:this.vx,this.x+=this.vx*t}if(this.yFixed)this.fy=0;else{var o=this.damping*this.vy,n=(this.fy-o)/this.options.mass;this.vy+=n*t,this.vy=Math.abs(this.vy)>e?this.vy>0?e:-e:this.vy,this.y+=this.vy*t}},s.prototype.isFixed=function(){return this.xFixed&&this.yFixed},s.prototype.isMoving=function(t){var e=Math.sqrt(Math.pow(this.vx,2)+Math.pow(this.vy,2));return e>t},s.prototype.isSelected=function(){return this.selected},s.prototype.getValue=function(){return this.value},s.prototype.getDistance=function(t,e){var i=this.x-t,s=this.y-e;return Math.sqrt(i*i+s*s)},s.prototype.setValueRange=function(t,e){if(!this.radiusFixed&&void 0!==this.value)if(e==t)this.options.radius=(this.options.radiusMin+this.options.radiusMax)/2;else{var i=(this.options.radiusMax-this.options.radiusMin)/(e-t);this.options.radius=(this.value-t)*i+this.options.radiusMin}this.baseRadiusValue=this.options.radius},s.prototype.draw=function(){throw"Draw method not initialized for node"},s.prototype.resize=function(){throw"Resize method not initialized for node"},s.prototype.isOverlappingWith=function(t){return this.leftt.left&&this.topt.top},s.prototype._resizeImage=function(){if(!this.width||!this.height){var t,e;if(this.value){this.options.radius=this.baseRadiusValue;var i=this.imageObj.height/this.imageObj.width;void 0!==i?(t=this.options.radius||this.imageObj.width,e=this.options.radius*i||this.imageObj.height):(t=0,e=0)}else t=this.imageObj.width,e=this.imageObj.height;this.width=t,this.height=e,this.growthIndicator=0,this.width>0&&this.height>0&&(this.width+=Math.min(this.clusterSize-1,this.maxNodeSizeIncrements)*this.clusterSizeWidthFactor,this.height+=Math.min(this.clusterSize-1,this.maxNodeSizeIncrements)*this.clusterSizeHeightFactor,this.options.radius+=Math.min(this.clusterSize-1,this.maxNodeSizeIncrements)*this.clusterSizeRadiusFactor,this.growthIndicator=this.width-t)}},s.prototype._drawImage=function(t){this._resizeImage(t),this.left=this.x-this.width/2,this.top=this.y-this.height/2;var e;if(0!=this.imageObj.width){if(this.clusterSize>1){var i=this.clusterSize>1?10:0;i*=this.networkScaleInv,i=Math.min(.2*this.width,i),t.globalAlpha=.5,t.drawImage(this.imageObj,this.left-i,this.top-i,this.width+2*i,this.height+2*i)}t.globalAlpha=1,t.drawImage(this.imageObj,this.left,this.top,this.width,this.height),e=this.y+this.height/2}else e=this.y;this._label(t,this.label,this.x,e,void 0,"top")},s.prototype._resizeBox=function(t){if(!this.width){var e=5,i=this.getTextSize(t);this.width=i.width+2*e,this.height=i.height+2*e,this.width+=.5*Math.min(this.clusterSize-1,this.maxNodeSizeIncrements)*this.clusterSizeWidthFactor,this.height+=.5*Math.min(this.clusterSize-1,this.maxNodeSizeIncrements)*this.clusterSizeHeightFactor,this.growthIndicator=this.width-(i.width+2*e)}},s.prototype._drawBox=function(t){this._resizeBox(t),this.left=this.x-this.width/2,this.top=this.y-this.height/2;var e=2.5,i=this.options.borderWidth,s=this.options.borderWidthSelected||2*this.options.borderWidth;t.strokeStyle=this.selected?this.options.color.highlight.border:this.hover?this.options.color.hover.border:this.options.color.border,this.clusterSize>1&&(t.lineWidth=(this.selected?s:i)+(this.clusterSize>1?e:0),t.lineWidth*=this.networkScaleInv,t.lineWidth=Math.min(this.width,t.lineWidth),t.roundRect(this.left-2*t.lineWidth,this.top-2*t.lineWidth,this.width+4*t.lineWidth,this.height+4*t.lineWidth,this.options.radius),t.stroke()),t.lineWidth=(this.selected?s:i)+(this.clusterSize>1?e:0),t.lineWidth*=this.networkScaleInv,t.lineWidth=Math.min(this.width,t.lineWidth),t.fillStyle=this.selected?this.options.color.highlight.background:this.options.color.background,t.roundRect(this.left,this.top,this.width,this.height,this.options.radius),t.fill(),t.stroke(),this._label(t,this.label,this.x,this.y)},s.prototype._resizeDatabase=function(t){if(!this.width){var e=5,i=this.getTextSize(t),s=i.width+2*e;this.width=s,this.height=s,this.width+=Math.min(this.clusterSize-1,this.maxNodeSizeIncrements)*this.clusterSizeWidthFactor,this.height+=Math.min(this.clusterSize-1,this.maxNodeSizeIncrements)*this.clusterSizeHeightFactor,this.options.radius+=Math.min(this.clusterSize-1,this.maxNodeSizeIncrements)*this.clusterSizeRadiusFactor,this.growthIndicator=this.width-s}},s.prototype._drawDatabase=function(t){this._resizeDatabase(t),this.left=this.x-this.width/2,this.top=this.y-this.height/2;var e=2.5,i=this.options.borderWidth,s=this.options.borderWidthSelected||2*this.options.borderWidth;t.strokeStyle=this.selected?this.options.color.highlight.border:this.hover?this.options.color.hover.border:this.options.color.border,this.clusterSize>1&&(t.lineWidth=(this.selected?s:i)+(this.clusterSize>1?e:0),t.lineWidth*=this.networkScaleInv,t.lineWidth=Math.min(this.width,t.lineWidth),t.database(this.x-this.width/2-2*t.lineWidth,this.y-.5*this.height-2*t.lineWidth,this.width+4*t.lineWidth,this.height+4*t.lineWidth),t.stroke()),t.lineWidth=(this.selected?s:i)+(this.clusterSize>1?e:0),t.lineWidth*=this.networkScaleInv,t.lineWidth=Math.min(this.width,t.lineWidth),t.fillStyle=this.selected?this.options.color.highlight.background:this.hover?this.options.color.hover.background:this.options.color.background,t.database(this.x-this.width/2,this.y-.5*this.height,this.width,this.height),t.fill(),t.stroke(),this._label(t,this.label,this.x,this.y)},s.prototype._resizeCircle=function(t){if(!this.width){var e=5,i=this.getTextSize(t),s=Math.max(i.width,i.height)+2*e;this.options.radius=s/2,this.width=s,this.height=s,this.options.radius+=.5*Math.min(this.clusterSize-1,this.maxNodeSizeIncrements)*this.clusterSizeRadiusFactor,this.growthIndicator=this.options.radius-.5*s}},s.prototype._drawCircle=function(t){this._resizeCircle(t),this.left=this.x-this.width/2,this.top=this.y-this.height/2;var e=2.5,i=this.options.borderWidth,s=this.options.borderWidthSelected||2*this.options.borderWidth;t.strokeStyle=this.selected?this.options.color.highlight.border:this.hover?this.options.color.hover.border:this.options.color.border,this.clusterSize>1&&(t.lineWidth=(this.selected?s:i)+(this.clusterSize>1?e:0),t.lineWidth*=this.networkScaleInv,t.lineWidth=Math.min(this.width,t.lineWidth),t.circle(this.x,this.y,this.options.radius+2*t.lineWidth),t.stroke()),t.lineWidth=(this.selected?s:i)+(this.clusterSize>1?e:0),t.lineWidth*=this.networkScaleInv,t.lineWidth=Math.min(this.width,t.lineWidth),t.fillStyle=this.selected?this.options.color.highlight.background:this.hover?this.options.color.hover.background:this.options.color.background,t.circle(this.x,this.y,this.options.radius),t.fill(),t.stroke(),this._label(t,this.label,this.x,this.y)},s.prototype._resizeEllipse=function(t){if(!this.width){var e=this.getTextSize(t);this.width=1.5*e.width,this.height=2*e.height,this.width1&&(t.lineWidth=(this.selected?s:i)+(this.clusterSize>1?e:0),t.lineWidth*=this.networkScaleInv,t.lineWidth=Math.min(this.width,t.lineWidth),t.ellipse(this.left-2*t.lineWidth,this.top-2*t.lineWidth,this.width+4*t.lineWidth,this.height+4*t.lineWidth),t.stroke()),t.lineWidth=(this.selected?s:i)+(this.clusterSize>1?e:0),t.lineWidth*=this.networkScaleInv,t.lineWidth=Math.min(this.width,t.lineWidth),t.fillStyle=this.selected?this.options.color.highlight.background:this.hover?this.options.color.hover.background:this.options.color.background,t.ellipse(this.left,this.top,this.width,this.height),t.fill(),t.stroke(),this._label(t,this.label,this.x,this.y)},s.prototype._drawDot=function(t){this._drawShape(t,"circle")},s.prototype._drawTriangle=function(t){this._drawShape(t,"triangle")},s.prototype._drawTriangleDown=function(t){this._drawShape(t,"triangleDown")},s.prototype._drawSquare=function(t){this._drawShape(t,"square")},s.prototype._drawStar=function(t){this._drawShape(t,"star")},s.prototype._resizeShape=function(){if(!this.width){this.options.radius=this.baseRadiusValue;var t=2*this.options.radius;this.width=t,this.height=t,this.width+=Math.min(this.clusterSize-1,this.maxNodeSizeIncrements)*this.clusterSizeWidthFactor,this.height+=Math.min(this.clusterSize-1,this.maxNodeSizeIncrements)*this.clusterSizeHeightFactor,this.options.radius+=.5*Math.min(this.clusterSize-1,this.maxNodeSizeIncrements)*this.clusterSizeRadiusFactor,this.growthIndicator=this.width-t}},s.prototype._drawShape=function(t,e){this._resizeShape(t),this.left=this.x-this.width/2,this.top=this.y-this.height/2;var i=2.5,s=this.options.borderWidth,o=this.options.borderWidthSelected||2*this.options.borderWidth,n=2;switch(e){case"dot":n=2;break;case"square":n=2;break;case"triangle":n=3;break;case"triangleDown":n=3;break;case"star":n=4}t.strokeStyle=this.selected?this.options.color.highlight.border:this.hover?this.options.color.hover.border:this.options.color.border,this.clusterSize>1&&(t.lineWidth=(this.selected?o:s)+(this.clusterSize>1?i:0),t.lineWidth*=this.networkScaleInv,t.lineWidth=Math.min(this.width,t.lineWidth),t[e](this.x,this.y,this.options.radius+n*t.lineWidth),t.stroke()),t.lineWidth=(this.selected?o:s)+(this.clusterSize>1?i:0),t.lineWidth*=this.networkScaleInv,t.lineWidth=Math.min(this.width,t.lineWidth),t.fillStyle=this.selected?this.options.color.highlight.background:this.hover?this.options.color.hover.background:this.options.color.background,t[e](this.x,this.y,this.options.radius),t.fill(),t.stroke(),this.label&&this._label(t,this.label,this.x,this.y+this.height/2,void 0,"top",!0) +},s.prototype._resizeText=function(t){if(!this.width){var e=5,i=this.getTextSize(t);this.width=i.width+2*e,this.height=i.height+2*e,this.width+=Math.min(this.clusterSize-1,this.maxNodeSizeIncrements)*this.clusterSizeWidthFactor,this.height+=Math.min(this.clusterSize-1,this.maxNodeSizeIncrements)*this.clusterSizeHeightFactor,this.options.radius+=Math.min(this.clusterSize-1,this.maxNodeSizeIncrements)*this.clusterSizeRadiusFactor,this.growthIndicator=this.width-(i.width+2*e)}},s.prototype._drawText=function(t){this._resizeText(t),this.left=this.x-this.width/2,this.top=this.y-this.height/2,this._label(t,this.label,this.x,this.y)},s.prototype._label=function(t,e,i,s,o,n,r){if(e&&Number(this.options.fontSize)*this.networkScale>this.fontDrawThreshold){t.font=(this.selected?"bold ":"")+this.options.fontSize+"px "+this.options.fontFace,t.fillStyle=this.options.fontColor||"black",t.textAlign=o||"center",t.textBaseline=n||"middle";var a=e.split("\n"),h=a.length,d=Number(this.options.fontSize)+4,l=s+(1-h)/2*d;1==r&&(l=s+(1-h)/(2*d));for(var c=0;h>c;c++)t.fillText(a[c],i,l),l+=d}},s.prototype.getTextSize=function(t){if(void 0!==this.label){t.font=(this.selected?"bold ":"")+this.options.fontSize+"px "+this.options.fontFace;for(var e=this.label.split("\n"),i=(Number(this.options.fontSize)+4)*e.length,s=0,o=0,n=e.length;n>o;o++)s=Math.max(s,t.measureText(e[o]).width);return{width:s,height:i}}return{width:0,height:0}},s.prototype.inArea=function(){return void 0!==this.width?this.x+this.width*this.networkScaleInv>=this.canvasTopLeft.x&&this.x-this.width*this.networkScaleInv=this.canvasTopLeft.y&&this.y-this.height*this.networkScaleInv=this.canvasTopLeft.x&&this.x=this.canvasTopLeft.y&&this.ys&&(n=s-e-this.padding),no&&(r=o-i-this.padding),ri;i++)if(e.id===r.nodes[i].id){o=r.nodes[i];break}for(o||(o={id:e.id},t.node&&(o.attr=a(o.attr,t.node))),i=n.length-1;i>=0;i--){var h=n[i];h.nodes||(h.nodes=[]),-1==h.nodes.indexOf(o)&&h.nodes.push(o)}e.attr&&(o.attr=a(o.attr,e.attr))}function l(t,e){if(t.edges||(t.edges=[]),t.edges.push(e),t.edge){var i=a({},t.edge);e.attr=a(i,e.attr)}}function c(t,e,i,s,o){var n={from:e,to:i,type:s};return t.edge&&(n.attr=a({},t.edge)),n.attr=a(n.attr||{},o),n}function p(){for(k=C.NULL,L="";" "==O||" "==O||"\n"==O||"\r"==O;)o();do{var t=!1;if("#"==O){for(var e=T-1;" "==D.charAt(e)||" "==D.charAt(e);)e--;if("\n"==D.charAt(e)||""==D.charAt(e)){for(;""!=O&&"\n"!=O;)o();t=!0}}if("/"==O&&"/"==n()){for(;""!=O&&"\n"!=O;)o();t=!0}if("/"==O&&"*"==n()){for(;""!=O;){if("*"==O&&"/"==n()){o(),o();break}o()}t=!0}for(;" "==O||" "==O||"\n"==O||"\r"==O;)o()}while(t);if(""==O)return void(k=C.DELIMITER);var i=O+n();if(E[i])return k=C.DELIMITER,L=i,o(),void o();if(E[O])return k=C.DELIMITER,L=O,void o();if(r(O)||"-"==O){for(L+=O,o();r(O);)L+=O,o();return"false"==L?L=!1:"true"==L?L=!0:isNaN(Number(L))||(L=Number(L)),void(k=C.IDENTIFIER)}if('"'==O){for(o();""!=O&&('"'!=O||'"'==O&&'"'==n());)L+=O,'"'==O&&o(),o();if('"'!=O)throw x('End of string " expected');return o(),void(k=C.IDENTIFIER)}for(k=C.UNKNOWN;""!=O;)L+=O,o();throw new SyntaxError('Syntax error in part "'+w(L,30)+'"')}function u(){var t={};if(s(),p(),"strict"==L&&(t.strict=!0,p()),("graph"==L||"digraph"==L)&&(t.type=L,p()),k==C.IDENTIFIER&&(t.id=L,p()),"{"!=L)throw x("Angle bracket { expected");if(p(),f(t),"}"!=L)throw x("Angle bracket } expected");if(p(),""!==L)throw x("End of file expected");return p(),delete t.node,delete t.edge,delete t.graph,t}function f(t){for(;""!==L&&"}"!=L;)m(t),";"==L&&p()}function m(t){var e=g(t);if(e)return void b(t,e);var i=v(t);if(!i){if(k!=C.IDENTIFIER)throw x("Identifier expected");var s=L;if(p(),"="==L){if(p(),k!=C.IDENTIFIER)throw x("Identifier expected");t[s]=L,p()}else y(t,s)}}function g(t){var e=null;if("subgraph"==L&&(e={},e.type="subgraph",p(),k==C.IDENTIFIER&&(e.id=L,p())),"{"==L){if(p(),e||(e={}),e.parent=t,e.node=t.node,e.edge=t.edge,e.graph=t.graph,f(e),"}"!=L)throw x("Angle bracket } expected");p(),delete e.node,delete e.edge,delete e.graph,delete e.parent,t.subgraphs||(t.subgraphs=[]),t.subgraphs.push(e)}return e}function v(t){return"node"==L?(p(),t.node=_(),"node"):"edge"==L?(p(),t.edge=_(),"edge"):"graph"==L?(p(),t.graph=_(),"graph"):null}function y(t,e){var i={id:e},s=_();s&&(i.attr=s),d(t,i),b(t,e)}function b(t,e){for(;"->"==L||"--"==L;){var i,s=L;p();var o=g(t);if(o)i=o;else{if(k!=C.IDENTIFIER)throw x("Identifier or subgraph expected");i=L,d(t,{id:i}),p()}var n=_(),r=c(t,e,i,s,n);l(t,r),e=i}}function _(){for(var t=null;"["==L;){for(p(),t={};""!==L&&"]"!=L;){if(k!=C.IDENTIFIER)throw x("Attribute name expected");var e=L;if(p(),"="!=L)throw x("Equal sign = expected");if(p(),k!=C.IDENTIFIER)throw x("Attribute value expected");var i=L;h(t,e,i),p(),","==L&&p()}if("]"!=L)throw x("Bracket ] expected");p()}return t}function x(t){return new SyntaxError(t+', got "'+w(L,30)+'" (char '+T+")")}function w(t,e){return t.length<=e?t:t.substr(0,27)+"..."}function S(t,e,i){t instanceof Array?t.forEach(function(t){e instanceof Array?e.forEach(function(e){i(t,e)}):i(t,e)}):e instanceof Array?e.forEach(function(e){i(t,e)}):i(t,e)}function M(t){function e(t){var e={from:t.from,to:t.to};return a(e,t.attr),e.style="->"==t.type?"arrow":"line",e}var s=i(t),o={nodes:[],edges:[],options:{}};return s.nodes&&s.nodes.forEach(function(t){var e={id:t.id,label:String(t.label||t.id)};a(e,t.attr),e.image&&(e.shape="image"),o.nodes.push(e)}),s.edges&&s.edges.forEach(function(t){var i,s;i=t.from instanceof Object?t.from.nodes:{id:t.from},s=t.to instanceof Object?t.to.nodes:{id:t.to},t.from instanceof Object&&t.from.edges&&t.from.edges.forEach(function(t){var i=e(t);o.edges.push(i)}),S(i,s,function(i,s){var n=c(o,i.id,s.id,t.type,t.attr),r=e(n);o.edges.push(r)}),t.to instanceof Object&&t.to.edges&&t.to.edges.forEach(function(t){var i=e(t);o.edges.push(i)})}),s.attr&&(o.options=s.attr),o}var C={NULL:0,DELIMITER:1,IDENTIFIER:2,UNKNOWN:3},E={"{":!0,"}":!0,"[":!0,"]":!0,";":!0,"=":!0,",":!0,"->":!0,"--":!0},D="",T=0,O="",L="",k=C.NULL,N=/[a-zA-Z_0-9.:#]/;e.parseDOT=i,e.DOTToGraph=M},function(t,e){function i(t,e){var i=[],s=[];this.options={edges:{inheritColor:!0},nodes:{allowedToMove:!1,parseColor:!1}},void 0!==e&&(this.options.nodes.allowedToMove=e.allowedToMove|!1,this.options.nodes.parseColor=e.parseColor|!1,this.options.edges.inheritColor=e.inheritColor|!0);for(var o=t.edges,n=t.nodes,r=0;r=s&&(s=864e5),e=new Date(e.valueOf()-.05*s),i=new Date(i.valueOf()+.05*s)}(null!==e||null!==i)&&this.range.setRange(e,i)},s.prototype.setWindow=function(t,e){if(1==arguments.length){var i=arguments[0];this.range.setRange(i.start,i.end)}else this.range.setRange(t,e)},s.prototype.getWindow=function(){var t=this.range.getRange();return{start:new Date(t.start),end:new Date(t.end)}},s.prototype.redraw=function(){var t=!1,e=this.options,i=this.props,s=this.dom;if(s){s.root.className="vis timeline root "+e.orientation,s.root.style.maxHeight=r.option.asSize(e.maxHeight,""),s.root.style.minHeight=r.option.asSize(e.minHeight,""),s.root.style.width=r.option.asSize(e.width,""),i.border.left=(s.centerContainer.offsetWidth-s.centerContainer.clientWidth)/2,i.border.right=i.border.left,i.border.top=(s.centerContainer.offsetHeight-s.centerContainer.clientHeight)/2,i.border.bottom=i.border.top;var o=s.root.offsetHeight-s.root.clientHeight,n=s.root.offsetWidth-s.root.clientWidth;i.center.height=s.center.offsetHeight,i.left.height=s.left.offsetHeight,i.right.height=s.right.offsetHeight,i.top.height=s.top.clientHeight||-i.border.top,i.bottom.height=s.bottom.clientHeight||-i.border.bottom;var a=Math.max(i.left.height,i.center.height,i.right.height),h=i.top.height+a+i.bottom.height+o+i.border.top+i.border.bottom;s.root.style.height=r.option.asSize(e.height,h+"px"),i.root.height=s.root.offsetHeight,i.background.height=i.root.height-o;var d=i.root.height-i.top.height-i.bottom.height-o;i.centerContainer.height=d,i.leftContainer.height=d,i.rightContainer.height=i.leftContainer.height,i.root.width=s.root.offsetWidth,i.background.width=i.root.width-n,i.left.width=s.leftContainer.clientWidth||-i.border.left,i.leftContainer.width=i.left.width,i.right.width=s.rightContainer.clientWidth||-i.border.right,i.rightContainer.width=i.right.width;var l=i.root.width-i.left.width-i.right.width-n;i.center.width=l,i.centerContainer.width=l,i.top.width=l,i.bottom.width=l,s.background.style.height=i.background.height+"px",s.backgroundVertical.style.height=i.background.height+"px",s.backgroundHorizontal.style.height=i.centerContainer.height+"px",s.centerContainer.style.height=i.centerContainer.height+"px",s.leftContainer.style.height=i.leftContainer.height+"px",s.rightContainer.style.height=i.rightContainer.height+"px",s.background.style.width=i.background.width+"px",s.backgroundVertical.style.width=i.centerContainer.width+"px",s.backgroundHorizontal.style.width=i.background.width+"px",s.centerContainer.style.width=i.center.width+"px",s.top.style.width=i.top.width+"px",s.bottom.style.width=i.bottom.width+"px",s.background.style.left="0",s.background.style.top="0",s.backgroundVertical.style.left=i.left.width+"px",s.backgroundVertical.style.top="0",s.backgroundHorizontal.style.left="0",s.backgroundHorizontal.style.top=i.top.height+"px",s.centerContainer.style.left=i.left.width+"px",s.centerContainer.style.top=i.top.height+"px",s.leftContainer.style.left="0",s.leftContainer.style.top=i.top.height+"px",s.rightContainer.style.left=i.left.width+i.center.width+"px",s.rightContainer.style.top=i.top.height+"px",s.top.style.left=i.left.width+"px",s.top.style.top="0",s.bottom.style.left=i.left.width+"px",s.bottom.style.top=i.top.height+i.centerContainer.height+"px",this._updateScrollTop();var c=this.props.scrollTop;"bottom"==e.orientation&&(c+=Math.max(this.props.centerContainer.height-this.props.center.height-this.props.border.top-this.props.border.bottom,0)),s.center.style.left="0",s.center.style.top=c+"px",s.left.style.left="0",s.left.style.top=c+"px",s.right.style.left="0",s.right.style.top=c+"px";var p=0==this.props.scrollTop?"hidden":"",u=this.props.scrollTop==this.props.scrollTopMin?"hidden":"";s.shadowTop.style.visibility=p,s.shadowBottom.style.visibility=u,s.shadowTopLeft.style.visibility=p,s.shadowBottomLeft.style.visibility=u,s.shadowTopRight.style.visibility=p,s.shadowBottomRight.style.visibility=u,this.components.forEach(function(e){t=e.redraw()||t}),t&&this.redraw()}},s.prototype.repaint=function(){throw new Error("Function repaint is deprecated. Use redraw instead.")},s.prototype._toTime=function(t){var e=this.range.conversion(this.props.center.width);return new Date(t/e.scale+e.offset)},s.prototype._toGlobalTime=function(t){var e=this.range.conversion(this.props.root.width);return new Date(t/e.scale+e.offset)},s.prototype._toScreen=function(t){var e=this.range.conversion(this.props.center.width);return(t.valueOf()-e.offset)*e.scale},s.prototype._toGlobalScreen=function(t){var e=this.range.conversion(this.props.root.width);return(t.valueOf()-e.offset)*e.scale},s.prototype._initAutoResize=function(){1==this.options.autoResize?this._startAutoResize():this._stopAutoResize()},s.prototype._startAutoResize=function(){var t=this;this._stopAutoResize(),this._onResize=function(){return 1!=t.options.autoResize?void t._stopAutoResize():void(t.dom.root&&(t.dom.root.clientWidth!=t.props.lastWidth||t.dom.root.clientHeight!=t.props.lastHeight)&&(t.props.lastWidth=t.dom.root.clientWidth,t.props.lastHeight=t.dom.root.clientHeight,t.emit("change")))},r.addEventListener(window,"resize",this._onResize),this.watchTimer=setInterval(this._onResize,1e3)},s.prototype._stopAutoResize=function(){this.watchTimer&&(clearInterval(this.watchTimer),this.watchTimer=void 0),r.removeEventListener(window,"resize",this._onResize),this._onResize=null},s.prototype._onTouch=function(){this.touch.allowDragging=!0},s.prototype._onPinch=function(){this.touch.allowDragging=!1},s.prototype._onDragStart=function(){this.touch.initialScrollTop=this.props.scrollTop},s.prototype._onDrag=function(t){if(this.touch.allowDragging){var e=t.gesture.deltaY,i=this._getScrollTop(),s=this._setScrollTop(this.touch.initialScrollTop+e);s!=i&&this.redraw()}},s.prototype._setScrollTop=function(t){return this.props.scrollTop=t,this._updateScrollTop(),this.props.scrollTop},s.prototype._updateScrollTop=function(){var t=Math.min(this.props.centerContainer.height-this.props.center.height,0);return t!=this.props.scrollTopMin&&("bottom"==this.options.orientation&&(this.props.scrollTop+=t-this.props.scrollTopMin),this.props.scrollTopMin=t),this.props.scrollTop>0&&(this.props.scrollTop=0),this.props.scrollTops;s++){var o=s%2===0?1.3*i:.5*i;this.lineTo(t+o*Math.sin(2*s*Math.PI/10),e-o*Math.cos(2*s*Math.PI/10))}this.closePath()},CanvasRenderingContext2D.prototype.roundRect=function(t,e,i,s,o){var n=Math.PI/180;0>i-2*o&&(o=i/2),0>s-2*o&&(o=s/2),this.beginPath(),this.moveTo(t+o,e),this.lineTo(t+i-o,e),this.arc(t+i-o,e+o,o,270*n,360*n,!1),this.lineTo(t+i,e+s-o),this.arc(t+i-o,e+s-o,o,0,90*n,!1),this.lineTo(t+o,e+s),this.arc(t+o,e+s-o,o,90*n,180*n,!1),this.lineTo(t,e+o),this.arc(t+o,e+o,o,180*n,270*n,!1)},CanvasRenderingContext2D.prototype.ellipse=function(t,e,i,s){var o=.5522848,n=i/2*o,r=s/2*o,a=t+i,h=e+s,d=t+i/2,l=e+s/2;this.beginPath(),this.moveTo(t,l),this.bezierCurveTo(t,l-r,d-n,e,d,e),this.bezierCurveTo(d+n,e,a,l-r,a,l),this.bezierCurveTo(a,l+r,d+n,h,d,h),this.bezierCurveTo(d-n,h,t,l+r,t,l)},CanvasRenderingContext2D.prototype.database=function(t,e,i,s){var o=1/3,n=i,r=s*o,a=.5522848,h=n/2*a,d=r/2*a,l=t+n,c=e+r,p=t+n/2,u=e+r/2,f=e+(s-r/2),m=e+s;this.beginPath(),this.moveTo(l,u),this.bezierCurveTo(l,u+d,p+h,c,p,c),this.bezierCurveTo(p-h,c,t,u+d,t,u),this.bezierCurveTo(t,u-d,p-h,e,p,e),this.bezierCurveTo(p+h,e,l,u-d,l,u),this.lineTo(l,f),this.bezierCurveTo(l,f+d,p+h,m,p,m),this.bezierCurveTo(p-h,m,t,f+d,t,f),this.lineTo(t,u)},CanvasRenderingContext2D.prototype.arrow=function(t,e,i,s){var o=t-s*Math.cos(i),n=e-s*Math.sin(i),r=t-.9*s*Math.cos(i),a=e-.9*s*Math.sin(i),h=o+s/3*Math.cos(i+.5*Math.PI),d=n+s/3*Math.sin(i+.5*Math.PI),l=o+s/3*Math.cos(i-.5*Math.PI),c=n+s/3*Math.sin(i-.5*Math.PI);this.beginPath(),this.moveTo(t,e),this.lineTo(h,d),this.lineTo(r,a),this.lineTo(l,c),this.closePath()},CanvasRenderingContext2D.prototype.dashedLine=function(t,e,i,s,o){o||(o=[10,5]),0==p&&(p=.001);var n=o.length;this.moveTo(t,e);for(var r=i-t,a=s-e,h=a/r,d=Math.sqrt(r*r+a*a),l=0,c=!0;d>=.1;){var p=o[l++%n];p>d&&(p=d);var u=Math.sqrt(p*p/(1+h*h));0>r&&(u=-u),t+=u,e+=h*u,this[c?"lineTo":"moveTo"](t,e),d-=p,c=!c}})},function(t,e,i){var s=i(56),o=i(50),n=i(51),r=i(52),a=i(53),h=i(54),d=i(55);e._loadMixin=function(t){for(var e in t)t.hasOwnProperty(e)&&(this[e]=t[e])},e._clearMixin=function(t){for(var e in t)t.hasOwnProperty(e)&&(this[e]=void 0)},e._loadPhysicsSystem=function(){this._loadMixin(s),this._loadSelectedForceSolver(),1==this.constants.configurePhysics&&this._loadPhysicsConfiguration()},e._loadClusterSystem=function(){this.clusterSession=0,this.hubThreshold=5,this._loadMixin(o)},e._loadSectorSystem=function(){this.sectors={},this.activeSector=["default"],this.sectors.active={},this.sectors.active["default"]={nodes:{},edges:{},nodeIndices:[],formationScale:1,drawingNode:void 0},this.sectors.frozen={},this.sectors.support={nodes:{},edges:{},nodeIndices:[],formationScale:1,drawingNode:void 0},this.nodeIndices=this.sectors.active["default"].nodeIndices,this._loadMixin(n)},e._loadSelectionSystem=function(){this.selectionObj={nodes:{},edges:{}},this._loadMixin(r)},e._loadManipulationSystem=function(){this.blockConnectingEdgeSelection=!1,this.forceAppendSelection=!1,1==this.constants.dataManipulation.enabled?(void 0===this.manipulationDiv&&(this.manipulationDiv=document.createElement("div"),this.manipulationDiv.className="network-manipulationDiv",this.manipulationDiv.id="network-manipulationDiv",this.manipulationDiv.style.display=1==this.editMode?"block":"none",this.containerElement.insertBefore(this.manipulationDiv,this.frame)),void 0===this.editModeDiv&&(this.editModeDiv=document.createElement("div"),this.editModeDiv.className="network-manipulation-editMode",this.editModeDiv.id="network-manipulation-editMode",this.editModeDiv.style.display=1==this.editMode?"none":"block",this.containerElement.insertBefore(this.editModeDiv,this.frame)),void 0===this.closeDiv&&(this.closeDiv=document.createElement("div"),this.closeDiv.className="network-manipulation-closeDiv",this.closeDiv.id="network-manipulation-closeDiv",this.closeDiv.style.display=this.manipulationDiv.style.display,this.containerElement.insertBefore(this.closeDiv,this.frame)),this._loadMixin(a),this._createManipulatorBar()):void 0!==this.manipulationDiv&&(this._createManipulatorBar(),this.containerElement.removeChild(this.manipulationDiv),this.containerElement.removeChild(this.editModeDiv),this.containerElement.removeChild(this.closeDiv),this.manipulationDiv=void 0,this.editModeDiv=void 0,this.closeDiv=void 0,this._clearMixin(a))},e._loadNavigationControls=function(){this._loadMixin(h),this._cleanNavigation(),1==this.constants.navigation.enabled&&this._loadNavigationElements()},e._loadHierarchySystem=function(){this._loadMixin(d)}},function(t){function e(t){return t?i(t):void 0}function i(t){for(var i in e.prototype)t[i]=e.prototype[i];return t}t.exports=e,e.prototype.on=e.prototype.addEventListener=function(t,e){return this._callbacks=this._callbacks||{},(this._callbacks[t]=this._callbacks[t]||[]).push(e),this},e.prototype.once=function(t,e){function i(){s.off(t,i),e.apply(this,arguments)}var s=this;return this._callbacks=this._callbacks||{},i.fn=e,this.on(t,i),this},e.prototype.off=e.prototype.removeListener=e.prototype.removeAllListeners=e.prototype.removeEventListener=function(t,e){if(this._callbacks=this._callbacks||{},0==arguments.length)return this._callbacks={},this;var i=this._callbacks[t];if(!i)return this;if(1==arguments.length)return delete this._callbacks[t],this;for(var s,o=0;os;++s)i[s].apply(this,e)}return this},e.prototype.listeners=function(t){return this._callbacks=this._callbacks||{},this._callbacks[t]||[]},e.prototype.hasListeners=function(t){return!!this.listeners(t).length}},function(t,e,i){var s;(function(t,o){(function(n){function r(t,e,i){switch(arguments.length){case 2:return null!=t?t:e;case 3:return null!=t?t:null!=e?e:i;default:throw new Error("Implement me")}}function a(){return{empty:!1,unusedTokens:[],unusedInput:[],overflow:-2,charsLeftOver:0,nullInput:!1,invalidMonth:null,invalidFormat:!1,userInvalidated:!1,iso:!1}}function h(t,e){function i(){ve.suppressDeprecationWarnings===!1&&"undefined"!=typeof console&&console.warn&&console.warn("Deprecation warning: "+t)}var s=!0;return f(function(){return s&&(i(),s=!1),e.apply(this,arguments)},e)}function d(t,e){return function(i){return v(t.call(this,i),e)}}function l(t,e){return function(i){return this.lang().ordinal(t.call(this,i),e)}}function c(){}function p(t){L(t),f(this,t)}function u(t){var e=S(t),i=e.year||0,s=e.quarter||0,o=e.month||0,n=e.week||0,r=e.day||0,a=e.hour||0,h=e.minute||0,d=e.second||0,l=e.millisecond||0;this._milliseconds=+l+1e3*d+6e4*h+36e5*a,this._days=+r+7*n,this._months=+o+3*s+12*i,this._data={},this._bubble()}function f(t,e){for(var i in e)e.hasOwnProperty(i)&&(t[i]=e[i]);return e.hasOwnProperty("toString")&&(t.toString=e.toString),e.hasOwnProperty("valueOf")&&(t.valueOf=e.valueOf),t}function m(t){var e,i={};for(e in t)t.hasOwnProperty(e)&&ke.hasOwnProperty(e)&&(i[e]=t[e]);return i}function g(t){return 0>t?Math.ceil(t):Math.floor(t)}function v(t,e,i){for(var s=""+Math.abs(t),o=t>=0;s.lengths;s++)(i&&t[s]!==e[s]||!i&&C(t[s])!==C(e[s]))&&r++;return r+n}function w(t){if(t){var e=t.toLowerCase().replace(/(.)s$/,"$1");t=ri[t]||ai[e]||e}return t}function S(t){var e,i,s={};for(i in t)t.hasOwnProperty(i)&&(e=w(i),e&&(s[e]=t[i]));return s}function M(t){var e,i;if(0===t.indexOf("week"))e=7,i="day";else{if(0!==t.indexOf("month"))return;e=12,i="month"}ve[t]=function(s,o){var r,a,h=ve.fn._lang[t],d=[];if("number"==typeof s&&(o=s,s=n),a=function(t){var e=ve().utc().set(i,t);return h.call(ve.fn._lang,e,s||"")},null!=o)return a(o);for(r=0;e>r;r++)d.push(a(r));return d}}function C(t){var e=+t,i=0;return 0!==e&&isFinite(e)&&(i=e>=0?Math.floor(e):Math.ceil(e)),i}function E(t,e){return new Date(Date.UTC(t,e+1,0)).getUTCDate()}function D(t,e,i){return re(ve([t,11,31+e-i]),e,i).week}function T(t){return O(t)?366:365}function O(t){return t%4===0&&t%100!==0||t%400===0}function L(t){var e;t._a&&-2===t._pf.overflow&&(e=t._a[Me]<0||t._a[Me]>11?Me:t._a[Ce]<1||t._a[Ce]>E(t._a[Se],t._a[Me])?Ce:t._a[Ee]<0||t._a[Ee]>23?Ee:t._a[De]<0||t._a[De]>59?De:t._a[Te]<0||t._a[Te]>59?Te:t._a[Oe]<0||t._a[Oe]>999?Oe:-1,t._pf._overflowDayOfYear&&(Se>e||e>Ce)&&(e=Ce),t._pf.overflow=e)}function k(t){return null==t._isValid&&(t._isValid=!isNaN(t._d.getTime())&&t._pf.overflow<0&&!t._pf.empty&&!t._pf.invalidMonth&&!t._pf.nullInput&&!t._pf.invalidFormat&&!t._pf.userInvalidated,t._strict&&(t._isValid=t._isValid&&0===t._pf.charsLeftOver&&0===t._pf.unusedTokens.length)),t._isValid}function N(t){return t?t.toLowerCase().replace("_","-"):t}function I(t,e){return e._isUTC?ve(t).zone(e._offset||0):ve(t).local()}function A(t,e){return e.abbr=t,Le[t]||(Le[t]=new c),Le[t].set(e),Le[t]}function z(t){delete Le[t]}function P(t){var e,s,o,n,r=0,a=function(t){if(!Le[t]&&Ne)try{i(57)("./"+t)}catch(e){}return Le[t]};if(!t)return ve.fn._lang;if(!b(t)){if(s=a(t))return s;t=[t]}for(;r0;){if(s=a(n.slice(0,e).join("-")))return s;if(o&&o.length>=e&&x(n,o,!0)>=e-1)break;e--}r++}return ve.fn._lang}function R(t){return t.match(/\[[\s\S]/)?t.replace(/^\[|\]$/g,""):t.replace(/\\/g,"")}function F(t){var e,i,s=t.match(Pe);for(e=0,i=s.length;i>e;e++)s[e]=pi[s[e]]?pi[s[e]]:R(s[e]);return function(o){var n="";for(e=0;i>e;e++)n+=s[e]instanceof Function?s[e].call(o,t):s[e];return n +}}function H(t,e){return t.isValid()?(e=Y(e,t.lang()),hi[e]||(hi[e]=F(e)),hi[e](t)):t.lang().invalidDate()}function Y(t,e){function i(t){return e.longDateFormat(t)||t}var s=5;for(Re.lastIndex=0;s>=0&&Re.test(t);)t=t.replace(Re,i),Re.lastIndex=0,s-=1;return t}function B(t,e){var i,s=e._strict;switch(t){case"Q":return qe;case"DDDD":return Ke;case"YYYY":case"GGGG":case"gggg":return s?$e:Ye;case"Y":case"G":case"g":return Qe;case"YYYYYY":case"YYYYY":case"GGGGG":case"ggggg":return s?Je:Be;case"S":if(s)return qe;case"SS":if(s)return Ze;case"SSS":if(s)return Ke;case"DDD":return He;case"MMM":case"MMMM":case"dd":case"ddd":case"dddd":return Ge;case"a":case"A":return P(e._l)._meridiemParse;case"X":return Ue;case"Z":case"ZZ":return je;case"T":return Ve;case"SSSS":return We;case"MM":case"DD":case"YY":case"GG":case"gg":case"HH":case"hh":case"mm":case"ss":case"ww":case"WW":return s?Ze:Fe;case"M":case"D":case"d":case"H":case"h":case"m":case"s":case"w":case"W":case"e":case"E":return Fe;case"Do":return Xe;default:return i=new RegExp(K(Z(t.replace("\\","")),"i"))}}function W(t){t=t||"";var e=t.match(je)||[],i=e[e.length-1]||[],s=(i+"").match(oi)||["-",0,0],o=+(60*s[1])+C(s[2]);return"+"===s[0]?-o:o}function G(t,e,i){var s,o=i._a;switch(t){case"Q":null!=e&&(o[Me]=3*(C(e)-1));break;case"M":case"MM":null!=e&&(o[Me]=C(e)-1);break;case"MMM":case"MMMM":s=P(i._l).monthsParse(e),null!=s?o[Me]=s:i._pf.invalidMonth=e;break;case"D":case"DD":null!=e&&(o[Ce]=C(e));break;case"Do":null!=e&&(o[Ce]=C(parseInt(e,10)));break;case"DDD":case"DDDD":null!=e&&(i._dayOfYear=C(e));break;case"YY":o[Se]=ve.parseTwoDigitYear(e);break;case"YYYY":case"YYYYY":case"YYYYYY":o[Se]=C(e);break;case"a":case"A":i._isPm=P(i._l).isPM(e);break;case"H":case"HH":case"h":case"hh":o[Ee]=C(e);break;case"m":case"mm":o[De]=C(e);break;case"s":case"ss":o[Te]=C(e);break;case"S":case"SS":case"SSS":case"SSSS":o[Oe]=C(1e3*("0."+e));break;case"X":i._d=new Date(1e3*parseFloat(e));break;case"Z":case"ZZ":i._useUTC=!0,i._tzm=W(e);break;case"dd":case"ddd":case"dddd":s=P(i._l).weekdaysParse(e),null!=s?(i._w=i._w||{},i._w.d=s):i._pf.invalidWeekday=e;break;case"w":case"ww":case"W":case"WW":case"d":case"e":case"E":t=t.substr(0,1);case"gggg":case"GGGG":case"GGGGG":t=t.substr(0,2),e&&(i._w=i._w||{},i._w[t]=C(e));break;case"gg":case"GG":i._w=i._w||{},i._w[t]=ve.parseTwoDigitYear(e)}}function j(t){var e,i,s,o,n,a,h,d;e=t._w,null!=e.GG||null!=e.W||null!=e.E?(n=1,a=4,i=r(e.GG,t._a[Se],re(ve(),1,4).year),s=r(e.W,1),o=r(e.E,1)):(d=P(t._l),n=d._week.dow,a=d._week.doy,i=r(e.gg,t._a[Se],re(ve(),n,a).year),s=r(e.w,1),null!=e.d?(o=e.d,n>o&&++s):o=null!=e.e?e.e+n:n),h=ae(i,s,o,a,n),t._a[Se]=h.year,t._dayOfYear=h.dayOfYear}function V(t){var e,i,s,o,n=[];if(!t._d){for(s=X(t),t._w&&null==t._a[Ce]&&null==t._a[Me]&&j(t),t._dayOfYear&&(o=r(t._a[Se],s[Se]),t._dayOfYear>T(o)&&(t._pf._overflowDayOfYear=!0),i=ie(o,0,t._dayOfYear),t._a[Me]=i.getUTCMonth(),t._a[Ce]=i.getUTCDate()),e=0;3>e&&null==t._a[e];++e)t._a[e]=n[e]=s[e];for(;7>e;e++)t._a[e]=n[e]=null==t._a[e]?2===e?1:0:t._a[e];t._d=(t._useUTC?ie:ee).apply(null,n),null!=t._tzm&&t._d.setUTCMinutes(t._d.getUTCMinutes()+t._tzm)}}function U(t){var e;t._d||(e=S(t._i),t._a=[e.year,e.month,e.day,e.hour,e.minute,e.second,e.millisecond],V(t))}function X(t){var e=new Date;return t._useUTC?[e.getUTCFullYear(),e.getUTCMonth(),e.getUTCDate()]:[e.getFullYear(),e.getMonth(),e.getDate()]}function q(t){if(t._f===ve.ISO_8601)return void J(t);t._a=[],t._pf.empty=!0;var e,i,s,o,n,r=P(t._l),a=""+t._i,h=a.length,d=0;for(s=Y(t._f,r).match(Pe)||[],e=0;e0&&t._pf.unusedInput.push(n),a=a.slice(a.indexOf(i)+i.length),d+=i.length),pi[o]?(i?t._pf.empty=!1:t._pf.unusedTokens.push(o),G(o,i,t)):t._strict&&!i&&t._pf.unusedTokens.push(o);t._pf.charsLeftOver=h-d,a.length>0&&t._pf.unusedInput.push(a),t._isPm&&t._a[Ee]<12&&(t._a[Ee]+=12),t._isPm===!1&&12===t._a[Ee]&&(t._a[Ee]=0),V(t),L(t)}function Z(t){return t.replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g,function(t,e,i,s,o){return e||i||s||o})}function K(t){return t.replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&")}function $(t){var e,i,s,o,n;if(0===t._f.length)return t._pf.invalidFormat=!0,void(t._d=new Date(0/0));for(o=0;on)&&(s=n,i=e));f(t,i||e)}function J(t){var e,i,s=t._i,o=ti.exec(s);if(o){for(t._pf.iso=!0,e=0,i=ii.length;i>e;e++)if(ii[e][1].exec(s)){t._f=ii[e][0]+(o[6]||" ");break}for(e=0,i=si.length;i>e;e++)if(si[e][1].exec(s)){t._f+=si[e][0];break}s.match(je)&&(t._f+="Z"),q(t)}else t._isValid=!1}function Q(t){J(t),t._isValid===!1&&(delete t._isValid,ve.createFromInputFallback(t))}function te(t){var e=t._i,i=Ie.exec(e);e===n?t._d=new Date:i?t._d=new Date(+i[1]):"string"==typeof e?Q(t):b(e)?(t._a=e.slice(0),V(t)):_(e)?t._d=new Date(+e):"object"==typeof e?U(t):"number"==typeof e?t._d=new Date(e):ve.createFromInputFallback(t)}function ee(t,e,i,s,o,n,r){var a=new Date(t,e,i,s,o,n,r);return 1970>t&&a.setFullYear(t),a}function ie(t){var e=new Date(Date.UTC.apply(null,arguments));return 1970>t&&e.setUTCFullYear(t),e}function se(t,e){if("string"==typeof t)if(isNaN(t)){if(t=e.weekdaysParse(t),"number"!=typeof t)return null}else t=parseInt(t,10);return t}function oe(t,e,i,s,o){return o.relativeTime(e||1,!!i,t,s)}function ne(t,e,i){var s=we(Math.abs(t)/1e3),o=we(s/60),n=we(o/60),r=we(n/24),a=we(r/365),h=s0,h[4]=i,oe.apply({},h)}function re(t,e,i){var s,o=i-e,n=i-t.day();return n>o&&(n-=7),o-7>n&&(n+=7),s=ve(t).add("d",n),{week:Math.ceil(s.dayOfYear()/7),year:s.year()}}function ae(t,e,i,s,o){var n,r,a=ie(t,0,1).getUTCDay();return a=0===a?7:a,i=null!=i?i:o,n=o-a+(a>s?7:0)-(o>a?7:0),r=7*(e-1)+(i-o)+n+1,{year:r>0?t:t-1,dayOfYear:r>0?r:T(t-1)+r}}function he(t){var e=t._i,i=t._f;return null===e||i===n&&""===e?ve.invalid({nullInput:!0}):("string"==typeof e&&(t._i=e=P().preparse(e)),ve.isMoment(e)?(t=m(e),t._d=new Date(+e._d)):i?b(i)?$(t):q(t):te(t),new p(t))}function de(t,e){var i,s;if(1===e.length&&b(e[0])&&(e=e[0]),!e.length)return ve();for(i=e[0],s=1;s=0?"+":"-";return e+v(Math.abs(t),6)},gg:function(){return v(this.weekYear()%100,2)},gggg:function(){return v(this.weekYear(),4)},ggggg:function(){return v(this.weekYear(),5)},GG:function(){return v(this.isoWeekYear()%100,2)},GGGG:function(){return v(this.isoWeekYear(),4)},GGGGG:function(){return v(this.isoWeekYear(),5)},e:function(){return this.weekday()},E:function(){return this.isoWeekday()},a:function(){return this.lang().meridiem(this.hours(),this.minutes(),!0)},A:function(){return this.lang().meridiem(this.hours(),this.minutes(),!1)},H:function(){return this.hours()},h:function(){return this.hours()%12||12},m:function(){return this.minutes()},s:function(){return this.seconds()},S:function(){return C(this.milliseconds()/100)},SS:function(){return v(C(this.milliseconds()/10),2)},SSS:function(){return v(this.milliseconds(),3)},SSSS:function(){return v(this.milliseconds(),3)},Z:function(){var t=-this.zone(),e="+";return 0>t&&(t=-t,e="-"),e+v(C(t/60),2)+":"+v(C(t)%60,2)},ZZ:function(){var t=-this.zone(),e="+";return 0>t&&(t=-t,e="-"),e+v(C(t/60),2)+v(C(t)%60,2)},z:function(){return this.zoneAbbr()},zz:function(){return this.zoneName()},X:function(){return this.unix()},Q:function(){return this.quarter()}},ui=["months","monthsShort","weekdays","weekdaysShort","weekdaysMin"];li.length;)be=li.pop(),pi[be+"o"]=l(pi[be],be);for(;ci.length;)be=ci.pop(),pi[be+be]=d(pi[be],2);for(pi.DDDD=d(pi.DDD,3),f(c.prototype,{set:function(t){var e,i;for(i in t)e=t[i],"function"==typeof e?this[i]=e:this["_"+i]=e},_months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),months:function(t){return this._months[t.month()]},_monthsShort:"Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),monthsShort:function(t){return this._monthsShort[t.month()]},monthsParse:function(t){var e,i,s;for(this._monthsParse||(this._monthsParse=[]),e=0;12>e;e++)if(this._monthsParse[e]||(i=ve.utc([2e3,e]),s="^"+this.months(i,"")+"|^"+this.monthsShort(i,""),this._monthsParse[e]=new RegExp(s.replace(".",""),"i")),this._monthsParse[e].test(t))return e},_weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),weekdays:function(t){return this._weekdays[t.day()]},_weekdaysShort:"Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),weekdaysShort:function(t){return this._weekdaysShort[t.day()]},_weekdaysMin:"Su_Mo_Tu_We_Th_Fr_Sa".split("_"),weekdaysMin:function(t){return this._weekdaysMin[t.day()]},weekdaysParse:function(t){var e,i,s;for(this._weekdaysParse||(this._weekdaysParse=[]),e=0;7>e;e++)if(this._weekdaysParse[e]||(i=ve([2e3,1]).day(e),s="^"+this.weekdays(i,"")+"|^"+this.weekdaysShort(i,"")+"|^"+this.weekdaysMin(i,""),this._weekdaysParse[e]=new RegExp(s.replace(".",""),"i")),this._weekdaysParse[e].test(t))return e},_longDateFormat:{LT:"h:mm A",L:"MM/DD/YYYY",LL:"MMMM D YYYY",LLL:"MMMM D YYYY LT",LLLL:"dddd, MMMM D YYYY LT"},longDateFormat:function(t){var e=this._longDateFormat[t];return!e&&this._longDateFormat[t.toUpperCase()]&&(e=this._longDateFormat[t.toUpperCase()].replace(/MMMM|MM|DD|dddd/g,function(t){return t.slice(1)}),this._longDateFormat[t]=e),e},isPM:function(t){return"p"===(t+"").toLowerCase().charAt(0)},_meridiemParse:/[ap]\.?m?\.?/i,meridiem:function(t,e,i){return t>11?i?"pm":"PM":i?"am":"AM"},_calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},calendar:function(t,e){var i=this._calendar[t];return"function"==typeof i?i.apply(e):i},_relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},relativeTime:function(t,e,i,s){var o=this._relativeTime[i];return"function"==typeof o?o(t,e,i,s):o.replace(/%d/i,t)},pastFuture:function(t,e){var i=this._relativeTime[t>0?"future":"past"];return"function"==typeof i?i(e):i.replace(/%s/i,e)},ordinal:function(t){return this._ordinal.replace("%d",t)},_ordinal:"%d",preparse:function(t){return t},postformat:function(t){return t},week:function(t){return re(t,this._week.dow,this._week.doy).week},_week:{dow:0,doy:6},_invalidDate:"Invalid date",invalidDate:function(){return this._invalidDate}}),ve=function(t,e,i,s){var o;return"boolean"==typeof i&&(s=i,i=n),o={},o._isAMomentObject=!0,o._i=t,o._f=e,o._l=i,o._strict=s,o._isUTC=!1,o._pf=a(),he(o)},ve.suppressDeprecationWarnings=!1,ve.createFromInputFallback=h("moment construction falls back to js Date. This is discouraged and will be removed in upcoming major release. Please refer to https://github.com/moment/moment/issues/1407 for more info.",function(t){t._d=new Date(t._i)}),ve.min=function(){var t=[].slice.call(arguments,0);return de("isBefore",t)},ve.max=function(){var t=[].slice.call(arguments,0);return de("isAfter",t)},ve.utc=function(t,e,i,s){var o;return"boolean"==typeof i&&(s=i,i=n),o={},o._isAMomentObject=!0,o._useUTC=!0,o._isUTC=!0,o._l=i,o._i=t,o._f=e,o._strict=s,o._pf=a(),he(o).utc()},ve.unix=function(t){return ve(1e3*t)},ve.duration=function(t,e){var i,s,o,n=t,r=null;return ve.isDuration(t)?n={ms:t._milliseconds,d:t._days,M:t._months}:"number"==typeof t?(n={},e?n[e]=t:n.milliseconds=t):(r=Ae.exec(t))?(i="-"===r[1]?-1:1,n={y:0,d:C(r[Ce])*i,h:C(r[Ee])*i,m:C(r[De])*i,s:C(r[Te])*i,ms:C(r[Oe])*i}):(r=ze.exec(t))&&(i="-"===r[1]?-1:1,o=function(t){var e=t&&parseFloat(t.replace(",","."));return(isNaN(e)?0:e)*i},n={y:o(r[2]),M:o(r[3]),d:o(r[4]),h:o(r[5]),m:o(r[6]),s:o(r[7]),w:o(r[8])}),s=new u(n),ve.isDuration(t)&&t.hasOwnProperty("_lang")&&(s._lang=t._lang),s},ve.version=_e,ve.defaultFormat=ei,ve.ISO_8601=function(){},ve.momentProperties=ke,ve.updateOffset=function(){},ve.relativeTimeThreshold=function(t,e){return di[t]===n?!1:(di[t]=e,!0)},ve.lang=function(t,e){var i;return t?(e?A(N(t),e):null===e?(z(t),t="en"):Le[t]||P(t),i=ve.duration.fn._lang=ve.fn._lang=P(t),i._abbr):ve.fn._lang._abbr},ve.langData=function(t){return t&&t._lang&&t._lang._abbr&&(t=t._lang._abbr),P(t)},ve.isMoment=function(t){return t instanceof p||null!=t&&t.hasOwnProperty("_isAMomentObject")},ve.isDuration=function(t){return t instanceof u},be=ui.length-1;be>=0;--be)M(ui[be]);ve.normalizeUnits=function(t){return w(t)},ve.invalid=function(t){var e=ve.utc(0/0);return null!=t?f(e._pf,t):e._pf.userInvalidated=!0,e},ve.parseZone=function(){return ve.apply(null,arguments).parseZone()},ve.parseTwoDigitYear=function(t){return C(t)+(C(t)>68?1900:2e3)},f(ve.fn=p.prototype,{clone:function(){return ve(this)},valueOf:function(){return+this._d+6e4*(this._offset||0)},unix:function(){return Math.floor(+this/1e3)},toString:function(){return this.clone().lang("en").format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ")},toDate:function(){return this._offset?new Date(+this):this._d},toISOString:function(){var t=ve(this).utc();return 00:!1},parsingFlags:function(){return f({},this._pf)},invalidAt:function(){return this._pf.overflow},utc:function(){return this.zone(0)},local:function(){return this.zone(0),this._isUTC=!1,this},format:function(t){var e=H(this,t||ve.defaultFormat);return this.lang().postformat(e)},add:function(t,e){var i;return i="string"==typeof t&&"string"==typeof e?ve.duration(isNaN(+e)?+t:+e,isNaN(+e)?e:t):"string"==typeof t?ve.duration(+e,t):ve.duration(t,e),y(this,i,1),this},subtract:function(t,e){var i;return i="string"==typeof t&&"string"==typeof e?ve.duration(isNaN(+e)?+t:+e,isNaN(+e)?e:t):"string"==typeof t?ve.duration(+e,t):ve.duration(t,e),y(this,i,-1),this},diff:function(t,e,i){var s,o,n=I(t,this),r=6e4*(this.zone()-n.zone());return e=w(e),"year"===e||"month"===e?(s=432e5*(this.daysInMonth()+n.daysInMonth()),o=12*(this.year()-n.year())+(this.month()-n.month()),o+=(this-ve(this).startOf("month")-(n-ve(n).startOf("month")))/s,o-=6e4*(this.zone()-ve(this).startOf("month").zone()-(n.zone()-ve(n).startOf("month").zone()))/s,"year"===e&&(o/=12)):(s=this-n,o="second"===e?s/1e3:"minute"===e?s/6e4:"hour"===e?s/36e5:"day"===e?(s-r)/864e5:"week"===e?(s-r)/6048e5:s),i?o:g(o)},from:function(t,e){return ve.duration(this.diff(t)).lang(this.lang()._abbr).humanize(!e)},fromNow:function(t){return this.from(ve(),t)},calendar:function(t){var e=t||ve(),i=I(e,this).startOf("day"),s=this.diff(i,"days",!0),o=-6>s?"sameElse":-1>s?"lastWeek":0>s?"lastDay":1>s?"sameDay":2>s?"nextDay":7>s?"nextWeek":"sameElse";return this.format(this.lang().calendar(o,this))},isLeapYear:function(){return O(this.year())},isDST:function(){return this.zone()+ve(t).startOf(e)},isBefore:function(t,e){return e="undefined"!=typeof e?e:"millisecond",+this.clone().startOf(e)<+ve(t).startOf(e)},isSame:function(t,e){return e=e||"ms",+this.clone().startOf(e)===+I(t,this).startOf(e)},min:h("moment().min is deprecated, use moment.min instead. https://github.com/moment/moment/issues/1548",function(t){return t=ve.apply(null,arguments),this>t?this:t}),max:h("moment().max is deprecated, use moment.max instead. https://github.com/moment/moment/issues/1548",function(t){return t=ve.apply(null,arguments),t>this?this:t}),zone:function(t,e){var i=this._offset||0;return null==t?this._isUTC?i:this._d.getTimezoneOffset():("string"==typeof t&&(t=W(t)),Math.abs(t)<16&&(t=60*t),this._offset=t,this._isUTC=!0,i!==t&&(!e||this._changeInProgress?y(this,ve.duration(i-t,"m"),1,!1):this._changeInProgress||(this._changeInProgress=!0,ve.updateOffset(this,!0),this._changeInProgress=null)),this)},zoneAbbr:function(){return this._isUTC?"UTC":""},zoneName:function(){return this._isUTC?"Coordinated Universal Time":""},parseZone:function(){return this._tzm?this.zone(this._tzm):"string"==typeof this._i&&this.zone(this._i),this},hasAlignedHourOffset:function(t){return t=t?ve(t).zone():0,(this.zone()-t)%60===0},daysInMonth:function(){return E(this.year(),this.month())},dayOfYear:function(t){var e=we((ve(this).startOf("day")-ve(this).startOf("year"))/864e5)+1;return null==t?e:this.add("d",t-e)},quarter:function(t){return null==t?Math.ceil((this.month()+1)/3):this.month(3*(t-1)+this.month()%3)},weekYear:function(t){var e=re(this,this.lang()._week.dow,this.lang()._week.doy).year;return null==t?e:this.add("y",t-e)},isoWeekYear:function(t){var e=re(this,1,4).year;return null==t?e:this.add("y",t-e)},week:function(t){var e=this.lang().week(this);return null==t?e:this.add("d",7*(t-e))},isoWeek:function(t){var e=re(this,1,4).week;return null==t?e:this.add("d",7*(t-e))},weekday:function(t){var e=(this.day()+7-this.lang()._week.dow)%7;return null==t?e:this.add("d",t-e)},isoWeekday:function(t){return null==t?this.day()||7:this.day(this.day()%7?t:t-7)},isoWeeksInYear:function(){return D(this.year(),1,4)},weeksInYear:function(){var t=this._lang._week;return D(this.year(),t.dow,t.doy)},get:function(t){return t=w(t),this[t]()},set:function(t,e){return t=w(t),"function"==typeof this[t]&&this[t](e),this},lang:function(t){return t===n?this._lang:(this._lang=P(t),this)}}),ve.fn.millisecond=ve.fn.milliseconds=ue("Milliseconds",!1),ve.fn.second=ve.fn.seconds=ue("Seconds",!1),ve.fn.minute=ve.fn.minutes=ue("Minutes",!1),ve.fn.hour=ve.fn.hours=ue("Hours",!0),ve.fn.date=ue("Date",!0),ve.fn.dates=h("dates accessor is deprecated. Use date instead.",ue("Date",!0)),ve.fn.year=ue("FullYear",!0),ve.fn.years=h("years accessor is deprecated. Use year instead.",ue("FullYear",!0)),ve.fn.days=ve.fn.day,ve.fn.months=ve.fn.month,ve.fn.weeks=ve.fn.week,ve.fn.isoWeeks=ve.fn.isoWeek,ve.fn.quarters=ve.fn.quarter,ve.fn.toJSON=ve.fn.toISOString,f(ve.duration.fn=u.prototype,{_bubble:function(){var t,e,i,s,o=this._milliseconds,n=this._days,r=this._months,a=this._data;a.milliseconds=o%1e3,t=g(o/1e3),a.seconds=t%60,e=g(t/60),a.minutes=e%60,i=g(e/60),a.hours=i%24,n+=g(i/24),a.days=n%30,r+=g(n/30),a.months=r%12,s=g(r/12),a.years=s},weeks:function(){return g(this.days()/7)},valueOf:function(){return this._milliseconds+864e5*this._days+this._months%12*2592e6+31536e6*C(this._months/12)},humanize:function(t){var e=+this,i=ne(e,!t,this.lang());return t&&(i=this.lang().pastFuture(e,i)),this.lang().postformat(i)},add:function(t,e){var i=ve.duration(t,e);return this._milliseconds+=i._milliseconds,this._days+=i._days,this._months+=i._months,this._bubble(),this},subtract:function(t,e){var i=ve.duration(t,e);return this._milliseconds-=i._milliseconds,this._days-=i._days,this._months-=i._months,this._bubble(),this},get:function(t){return t=w(t),this[t.toLowerCase()+"s"]()},as:function(t){return t=w(t),this["as"+t.charAt(0).toUpperCase()+t.slice(1)+"s"]()},lang:ve.fn.lang,toIsoString:function(){var t=Math.abs(this.years()),e=Math.abs(this.months()),i=Math.abs(this.days()),s=Math.abs(this.hours()),o=Math.abs(this.minutes()),n=Math.abs(this.seconds()+this.milliseconds()/1e3);return this.asSeconds()?(this.asSeconds()<0?"-":"")+"P"+(t?t+"Y":"")+(e?e+"M":"")+(i?i+"D":"")+(s||o||n?"T":"")+(s?s+"H":"")+(o?o+"M":"")+(n?n+"S":""):"P0D"}});for(be in ni)ni.hasOwnProperty(be)&&(me(be,ni[be]),fe(be.toLowerCase()));me("Weeks",6048e5),ve.duration.fn.asMonths=function(){return(+this-31536e6*this.years())/2592e6+12*this.years()},ve.lang("en",{ordinal:function(t){var e=t%10,i=1===C(t%100/10)?"th":1===e?"st":2===e?"nd":3===e?"rd":"th";return t+i}}),Ne?o.exports=ve:(s=function(t,e,i){return i.config&&i.config()&&i.config().noGlobal===!0&&(xe.moment=ye),ve}.call(e,i,e,o),!(s!==n&&(o.exports=s)),ge(!0))}).call(this)}).call(e,function(){return this}(),i(61)(t))},function(t,e,i){var s;!function(o,n){"use strict";function r(){a.READY||(w.determineEventTypes(),x.each(a.gestures,function(t){M.register(t)}),w.onTouch(a.DOCUMENT,v,M.detect),w.onTouch(a.DOCUMENT,y,M.detect),a.READY=!0)}var a=function C(t,e){return new C.Instance(t,e||{})};a.VERSION="1.1.3",a.defaults={behavior:{userSelect:"none",touchAction:"pan-y",touchCallout:"none",contentZooming:"none",userDrag:"none",tapHighlightColor:"rgba(0,0,0,0)"}},a.DOCUMENT=document,a.HAS_POINTEREVENTS=navigator.pointerEnabled||navigator.msPointerEnabled,a.HAS_TOUCHEVENTS="ontouchstart"in o,a.IS_MOBILE=/mobile|tablet|ip(ad|hone|od)|android|silk/i.test(navigator.userAgent),a.NO_MOUSEEVENTS=a.HAS_TOUCHEVENTS&&a.IS_MOBILE||a.HAS_POINTEREVENTS,a.CALCULATE_INTERVAL=25;var h={},d=a.DIRECTION_DOWN="down",l=a.DIRECTION_LEFT="left",c=a.DIRECTION_UP="up",p=a.DIRECTION_RIGHT="right",u=a.POINTER_MOUSE="mouse",f=a.POINTER_TOUCH="touch",m=a.POINTER_PEN="pen",g=a.EVENT_START="start",v=a.EVENT_MOVE="move",y=a.EVENT_END="end",b=a.EVENT_RELEASE="release",_=a.EVENT_TOUCH="touch";a.READY=!1,a.plugins=a.plugins||{},a.gestures=a.gestures||{};var x=a.utils={extend:function(t,e,i){for(var s in e)!e.hasOwnProperty(s)||t[s]!==n&&i||(t[s]=e[s]);return t},on:function(t,e,i){t.addEventListener(e,i,!1)},off:function(t,e,i){t.removeEventListener(e,i,!1)},each:function(t,e,i){var s,o;if("forEach"in t)t.forEach(e,i);else if(t.length!==n){for(s=0,o=t.length;o>s;s++)if(e.call(i,t[s],s,t)===!1)return}else for(s in t)if(t.hasOwnProperty(s)&&e.call(i,t[s],s,t)===!1)return},inStr:function(t,e){return t.indexOf(e)>-1},inArray:function(t,e){if(t.indexOf){var i=t.indexOf(e);return-1===i?!1:i}for(var s=0,o=t.length;o>s;s++)if(t[s]===e)return s;return!1},toArray:function(t){return Array.prototype.slice.call(t,0)},hasParent:function(t,e){for(;t;){if(t==e)return!0;t=t.parentNode}return!1},getCenter:function(t){var e=[],i=[],s=[],o=[],n=Math.min,r=Math.max;return 1===t.length?{pageX:t[0].pageX,pageY:t[0].pageY,clientX:t[0].clientX,clientY:t[0].clientY}:(x.each(t,function(t){e.push(t.pageX),i.push(t.pageY),s.push(t.clientX),o.push(t.clientY)}),{pageX:(n.apply(Math,e)+r.apply(Math,e))/2,pageY:(n.apply(Math,i)+r.apply(Math,i))/2,clientX:(n.apply(Math,s)+r.apply(Math,s))/2,clientY:(n.apply(Math,o)+r.apply(Math,o))/2})},getVelocity:function(t,e,i){return{x:Math.abs(e/t)||0,y:Math.abs(i/t)||0}},getAngle:function(t,e){var i=e.clientX-t.clientX,s=e.clientY-t.clientY;return 180*Math.atan2(s,i)/Math.PI},getDirection:function(t,e){var i=Math.abs(t.clientX-e.clientX),s=Math.abs(t.clientY-e.clientY);return i>=s?t.clientX-e.clientX>0?l:p:t.clientY-e.clientY>0?c:d},getDistance:function(t,e){var i=e.clientX-t.clientX,s=e.clientY-t.clientY;return Math.sqrt(i*i+s*s)},getScale:function(t,e){return t.length>=2&&e.length>=2?this.getDistance(e[0],e[1])/this.getDistance(t[0],t[1]):1},getRotation:function(t,e){return t.length>=2&&e.length>=2?this.getAngle(e[1],e[0])-this.getAngle(t[1],t[0]):0},isVertical:function(t){return t==c||t==d},setPrefixedCss:function(t,e,i,s){var o=["","Webkit","Moz","O","ms"];e=x.toCamelCase(e);for(var n=0;n0&&this.started&&(r=v),this.started=!0;var d=this.collectEventData(i,r,o,t);return e!=y&&s.call(M,d),a&&(d.changedLength=h,d.eventType=a,s.call(M,d),d.eventType=r,delete d.changedLength),r==y&&(s.call(M,d),this.started=!1),r},determineEventTypes:function(){var t;return t=a.HAS_POINTEREVENTS?o.PointerEvent?["pointerdown","pointermove","pointerup pointercancel lostpointercapture"]:["MSPointerDown","MSPointerMove","MSPointerUp MSPointerCancel MSLostPointerCapture"]:a.NO_MOUSEEVENTS?["touchstart","touchmove","touchend touchcancel"]:["touchstart mousedown","touchmove mousemove","touchend touchcancel mouseup"],h[g]=t[0],h[v]=t[1],h[y]=t[2],h},getTouchList:function(t,e){if(a.HAS_POINTEREVENTS)return S.getTouchList();if(t.touches){if(e==v)return t.touches;var i=[],s=[].concat(x.toArray(t.touches),x.toArray(t.changedTouches)),o=[];return x.each(s,function(t){x.inArray(i,t.identifier)===!1&&o.push(t),i.push(t.identifier)}),o}return t.identifier=1,[t]},collectEventData:function(t,e,i,s){var o=f;return x.inStr(s.type,"mouse")||S.matchType(u,s)?o=u:S.matchType(m,s)&&(o=m),{center:x.getCenter(i),timeStamp:Date.now(),target:s.target,touches:i,eventType:e,pointerType:o,srcEvent:s,preventDefault:function(){var t=this.srcEvent;t.preventManipulation&&t.preventManipulation(),t.preventDefault&&t.preventDefault()},stopPropagation:function(){this.srcEvent.stopPropagation()},stopDetect:function(){return M.stopDetect()}}}},S=a.PointerEvent={pointers:{},getTouchList:function(){var t=[];return x.each(this.pointers,function(e){t.push(e)}),t},updatePointer:function(t,e){t==y||t!=y&&1!==e.buttons?delete this.pointers[e.pointerId]:(e.identifier=e.pointerId,this.pointers[e.pointerId]=e)},matchType:function(t,e){if(!e.pointerType)return!1;var i=e.pointerType,s={};return s[u]=i===(e.MSPOINTER_TYPE_MOUSE||u),s[f]=i===(e.MSPOINTER_TYPE_TOUCH||f),s[m]=i===(e.MSPOINTER_TYPE_PEN||m),s[t]},reset:function(){this.pointers={}}},M=a.detection={gestures:[],current:null,previous:null,stopped:!1,startDetect:function(t,e){this.current||(this.stopped=!1,this.current={inst:t,startEvent:x.extend({},e),lastEvent:!1,lastCalcEvent:!1,futureCalcEvent:!1,lastCalcData:{},name:""},this.detect(e))},detect:function(t){if(this.current&&!this.stopped){t=this.extendEventData(t);var e=this.current.inst,i=e.options;return x.each(this.gestures,function(s){!this.stopped&&e.enabled&&i[s.name]&&s.handler.call(s,t,e)},this),this.current&&(this.current.lastEvent=t),t.eventType==y&&this.stopDetect(),t}},stopDetect:function(){this.previous=x.extend({},this.current),this.current=null,this.stopped=!0},getCalculatedData:function(t,e,i,s,o){var n=this.current,r=!1,h=n.lastCalcEvent,d=n.lastCalcData;h&&t.timeStamp-h.timeStamp>a.CALCULATE_INTERVAL&&(e=h.center,i=t.timeStamp-h.timeStamp,s=t.center.clientX-h.center.clientX,o=t.center.clientY-h.center.clientY,r=!0),(t.eventType==_||t.eventType==b)&&(n.futureCalcEvent=t),(!n.lastCalcEvent||r)&&(d.velocity=x.getVelocity(i,s,o),d.angle=x.getAngle(e,t.center),d.direction=x.getDirection(e,t.center),n.lastCalcEvent=n.futureCalcEvent||t,n.futureCalcEvent=t),t.velocityX=d.velocity.x,t.velocityY=d.velocity.y,t.interimAngle=d.angle,t.interimDirection=d.direction +},extendEventData:function(t){var e=this.current,i=e.startEvent,s=e.lastEvent||i;(t.eventType==_||t.eventType==b)&&(i.touches=[],x.each(t.touches,function(t){i.touches.push({clientX:t.clientX,clientY:t.clientY})}));var o=t.timeStamp-i.timeStamp,n=t.center.clientX-i.center.clientX,r=t.center.clientY-i.center.clientY;return this.getCalculatedData(t,s.center,o,n,r),x.extend(t,{startEvent:i,deltaTime:o,deltaX:n,deltaY:r,distance:x.getDistance(i.center,t.center),angle:x.getAngle(i.center,t.center),direction:x.getDirection(i.center,t.center),scale:x.getScale(i.touches,t.touches),rotation:x.getRotation(i.touches,t.touches)}),t},register:function(t){var e=t.defaults||{};return e[t.name]===n&&(e[t.name]=!0),x.extend(a.defaults,e,!0),t.index=t.index||1e3,this.gestures.push(t),this.gestures.sort(function(t,e){return t.indexe.index?1:0}),this.gestures}};a.Instance=function(t,e){var i=this;r(),this.element=t,this.enabled=!0,x.each(e,function(t,i){delete e[i],e[x.toCamelCase(i)]=t}),this.options=x.extend(x.extend({},a.defaults),e||{}),this.options.behavior&&x.toggleBehavior(this.element,this.options.behavior,!0),this.eventStartHandler=w.onTouch(t,g,function(t){i.enabled&&t.eventType==g?M.startDetect(i,t):t.eventType==_&&M.detect(t)}),this.eventHandlers=[]},a.Instance.prototype={on:function(t,e){var i=this;return w.on(i.element,t,e,function(t){i.eventHandlers.push({gesture:t,handler:e})}),i},off:function(t,e){var i=this;return w.off(i.element,t,e,function(t){var s=x.inArray({gesture:t,handler:e});s!==!1&&i.eventHandlers.splice(s,1)}),i},trigger:function(t,e){e||(e={});var i=a.DOCUMENT.createEvent("Event");i.initEvent(t,!0,!0),i.gesture=e;var s=this.element;return x.hasParent(e.target,s)&&(s=e.target),s.dispatchEvent(i),this},enable:function(t){return this.enabled=t,this},dispose:function(){var t,e;for(x.toggleBehavior(this.element,this.options.behavior,!1),t=-1;e=this.eventHandlers[++t];)x.off(this.element,e.gesture,e.handler);return this.eventHandlers=[],w.off(this.element,h[g],this.eventStartHandler),null}},function(t){function e(e,s){var o=M.current;if(!(s.options.dragMaxTouches>0&&e.touches.length>s.options.dragMaxTouches))switch(e.eventType){case g:i=!1;break;case v:if(e.distance0)){var r=Math.abs(s.options.dragMinDistance/e.distance);n.pageX+=e.deltaX*r,n.pageY+=e.deltaY*r,n.clientX+=e.deltaX*r,n.clientY+=e.deltaY*r,e=M.extendEventData(e)}(o.lastEvent.dragLockToAxis||s.options.dragLockToAxis&&s.options.dragLockMinDistance<=e.distance)&&(e.dragLockToAxis=!0);var a=o.lastEvent.direction;e.dragLockToAxis&&a!==e.direction&&(e.direction=x.isVertical(a)?e.deltaY<0?c:d:e.deltaX<0?l:p),i||(s.trigger(t+"start",e),i=!0),s.trigger(t,e),s.trigger(t+e.direction,e);var h=x.isVertical(e.direction);(s.options.dragBlockVertical&&h||s.options.dragBlockHorizontal&&!h)&&e.preventDefault();break;case b:i&&e.changedLength<=s.options.dragMaxTouches&&(s.trigger(t+"end",e),i=!1);break;case y:i=!1}}var i=!1;a.gestures.Drag={name:t,index:50,handler:e,defaults:{dragMinDistance:10,dragDistanceCorrection:!0,dragMaxTouches:1,dragBlockHorizontal:!1,dragBlockVertical:!1,dragLockToAxis:!1,dragLockMinDistance:25}}}("drag"),a.gestures.Gesture={name:"gesture",index:1337,handler:function(t,e){e.trigger(this.name,t)}},function(t){function e(e,s){var o=s.options,n=M.current;switch(e.eventType){case g:clearTimeout(i),n.name=t,i=setTimeout(function(){n&&n.name==t&&s.trigger(t,e)},o.holdTimeout);break;case v:e.distance>o.holdThreshold&&clearTimeout(i);break;case b:clearTimeout(i)}}var i;a.gestures.Hold={name:t,index:10,defaults:{holdTimeout:500,holdThreshold:2},handler:e}}("hold"),a.gestures.Release={name:"release",index:1/0,handler:function(t,e){t.eventType==b&&e.trigger(this.name,t)}},a.gestures.Swipe={name:"swipe",index:40,defaults:{swipeMinTouches:1,swipeMaxTouches:1,swipeVelocityX:.6,swipeVelocityY:.6},handler:function(t,e){if(t.eventType==b){var i=t.touches.length,s=e.options;if(is.swipeMaxTouches)return;(t.velocityX>s.swipeVelocityX||t.velocityY>s.swipeVelocityY)&&(e.trigger(this.name,t),e.trigger(this.name+t.direction,t))}}},function(t){function e(e,s){var o,n,r=s.options,a=M.current,h=M.previous;switch(e.eventType){case g:i=!1;break;case v:i=i||e.distance>r.tapMaxDistance;break;case y:!x.inStr(e.srcEvent.type,"cancel")&&e.deltaTimes.options.transformMinRotation&&s.trigger("rotate",e),o>s.options.transformMinScale&&(s.trigger("pinch",e),s.trigger("pinch"+(e.scale<1?"in":"out"),e));break;case b:i&&e.changedLength<2&&(s.trigger(t+"end",e),i=!1)}}var i=!1;a.gestures.Transform={name:t,index:45,defaults:{transformMinScale:.01,transformMinRotation:1},handler:e}}("transform"),s=function(){return a}.call(e,i,e,t),!(s!==n&&(t.exports=s))}(window)},function(t){function e(t,e,i){return t.addEventListener?t.addEventListener(e,i,!1):void t.attachEvent("on"+e,i)}function i(t){return"keypress"==t.type?String.fromCharCode(t.which):_[t.which]?_[t.which]:x[t.which]?x[t.which]:String.fromCharCode(t.which).toLowerCase()}function s(t){var e=t.target||t.srcElement,i=e.tagName;return(" "+e.className+" ").indexOf(" mousetrap ")>-1?!1:"INPUT"==i||"SELECT"==i||"TEXTAREA"==i||e.contentEditable&&"true"==e.contentEditable}function o(t,e){return t.sort().join(",")===e.sort().join(",")}function n(t){t=t||{};var e,i=!1;for(e in E)t[e]?i=!0:E[e]=0;i||(T=!1)}function r(t,e,i,s,n){var r,a,h=[];if(!M[t])return[];for("keyup"==i&&c(t)&&(e=[t]),r=0;r95&&112>t||_.hasOwnProperty(t)&&(y[_[t]]=t)}return y}function f(t,e,i){return i||(i=u()[t]?"keydown":"keypress"),"keypress"==i&&e.length&&(i="keydown"),i}function m(t,e,s,o){E[t]=0,o||(o=f(e[0],[]));var r,a=function(){T=o,++E[t],p()},d=function(t){h(s,t),"keyup"!==o&&(D=i(t)),setTimeout(n,10)};for(r=0;r1)return m(t,d,e,i);for(h="+"===t?["+"]:t.split("+"),n=0;n":".","?":"/","|":"\\"},S={option:"alt",command:"meta","return":"enter",escape:"esc"},M={},C={},E={},D=!1,T=!1,O=1;20>O;++O)_[111+O]="f"+O;for(O=0;9>=O;++O)_[O+96]=O;e(document,"keypress",l),e(document,"keydown",l),e(document,"keyup",l);var L={bind:function(t,e,i){return v(t instanceof Array?t:[t],e,i),C[t+":"+i]=e,this},unbind:function(t,e){return C[t+":"+e]&&(delete C[t+":"+e],this.bind(t,function(){},e)),this},trigger:function(t,e){return C[t+":"+e](),this},reset:function(){return M={},C={},this}};t.exports=L},function(t,e){e.startWithClustering=function(){this.clusterToFit(this.constants.clustering.initialMaxNodes,!0),this.updateLabels(),this.stabilize&&this._stabilize(),this.start()},e.clusterToFit=function(t,e){for(var i=this.nodeIndices.length,s=50,o=0;i>t&&s>o;)o%3==0?(this.forceAggregateHubs(!0),this.normalizeClusterLevels()):this.increaseClusterLevel(),i=this.nodeIndices.length,o+=1;o>0&&1==e&&this.repositionNodes(),this._updateCalculationNodes()},e.openCluster=function(t){var e=this.moving;if(t.clusterSize>this.constants.clustering.sectorThreshold&&this._nodeInActiveArea(t)&&("default"!=this._sector()||1!=this.nodeIndices.length)){this._addSector(t);for(var i=0;this.nodeIndices.lengthi;)this.decreaseClusterLevel(),i+=1}else this._expandClusterNode(t,!1,!0),this._updateNodeIndexList(),this._updateDynamicEdges(),this._updateCalculationNodes(),this.updateLabels();this.moving!=e&&this.start()},e.updateClustersDefault=function(){1==this.constants.clustering.enabled&&this.updateClusters(0,!1,!1)},e.increaseClusterLevel=function(){this.updateClusters(-1,!1,!0)},e.decreaseClusterLevel=function(){this.updateClusters(1,!1,!0)},e.updateClusters=function(t,e,i,s){var o=this.moving,n=this.nodeIndices.length;this.previousScale>this.scale&&0==t&&this._collapseSector(),this.previousScale>this.scale||-1==t?this._formClusters(i):(this.previousScalethis.scale||-1==t)&&(this._aggregateHubs(i),this._updateNodeIndexList()),(this.previousScale>this.scale||-1==t)&&(this.handleChains(),this._updateNodeIndexList()),this.previousScale=this.scale,this._updateDynamicEdges(),this.updateLabels(),this.nodeIndices.lengththis.constants.clustering.chainThreshold&&this._reduceAmountOfChains(1-this.constants.clustering.chainThreshold/t)},e._aggregateHubs=function(t){this._getHubSize(),this._formClustersByHub(t,!1)},e.forceAggregateHubs=function(t){var e=this.moving,i=this.nodeIndices.length;this._aggregateHubs(!0),this._updateNodeIndexList(),this._updateDynamicEdges(),this.updateLabels(),this.nodeIndices.length!=i&&(this.clusterSession+=1),(0==t||void 0===t)&&this.moving!=e&&this.start()},e._openClustersBySize=function(){for(var t in this.nodes)if(this.nodes.hasOwnProperty(t)){var e=this.nodes[t];1==e.inView()&&(e.width*this.scale>this.constants.clustering.screenSizeThreshold*this.frame.canvas.clientWidth||e.height*this.scale>this.constants.clustering.screenSizeThreshold*this.frame.canvas.clientHeight)&&this.openCluster(e)}},e._openClusters=function(t,e){for(var i=0;i1&&(t.clusterSizei)){var r=n.from,a=n.to;n.to.options.mass>n.from.options.mass&&(r=n.to,a=n.from),1==a.dynamicEdgesLength?this._addToCluster(r,a,!1):1==r.dynamicEdgesLength&&this._addToCluster(a,r,!1)}}},e._forceClustersByZoom=function(){for(var t in this.nodes)if(this.nodes.hasOwnProperty(t)){var e=this.nodes[t];if(1==e.dynamicEdgesLength&&0!=e.dynamicEdges.length){var i=e.dynamicEdges[0],s=i.toId==e.id?this.nodes[i.fromId]:this.nodes[i.toId];e.id!=s.id&&(s.options.mass>e.options.mass?this._addToCluster(s,e,!0):this._addToCluster(e,s,!0))}}},e._clusterToSmallestNeighbour=function(t){for(var e=-1,i=null,s=0;so.clusterSessions.length&&(e=o.clusterSessions.length,i=o)}null!=o&&void 0!==this.nodes[o.id]&&this._addToCluster(o,t,!0)},e._formClustersByHub=function(t,e){for(var i in this.nodes)this.nodes.hasOwnProperty(i)&&this._formClusterFromHub(this.nodes[i],t,e)},e._formClusterFromHub=function(t,e,i,s){if(void 0===s&&(s=0),t.dynamicEdgesLength>=this.hubThreshold&&0==i||t.dynamicEdgesLength==this.hubThreshold&&1==i){for(var o,n,r,a=this.constants.clustering.clusterEdgeThreshold/this.scale,h=!1,d=[],l=t.dynamicEdges.length,c=0;l>c;c++)d.push(t.dynamicEdges[c].id);if(0==e)for(h=!1,c=0;l>c;c++){var p=this.edges[d[c]];if(void 0!==p&&p.connected&&p.toId!=p.fromId&&(o=p.to.x-p.from.x,n=p.to.y-p.from.y,r=Math.sqrt(o*o+n*n),a>r)){h=!0;break}}if(!e&&h||e)for(c=0;l>c;c++)if(p=this.edges[d[c]],void 0!==p){var u=this.nodes[p.fromId==t.id?p.toId:p.fromId];u.dynamicEdges.length<=this.hubThreshold+s&&u.id!=t.id&&this._addToCluster(t,u,e)}}},e._addToCluster=function(t,e,i){t.containedNodes[e.id]=e;for(var s=0;s1)for(var s=0;s1&&(e.label="[".concat(String(e.clusterSize),"]"))}for(t in this.nodes)this.nodes.hasOwnProperty(t)&&(e=this.nodes[t],1==e.clusterSize&&(e.label=void 0!==e.originalLabel?e.originalLabel:String(e.id)))},e.normalizeClusterLevels=function(){var t,e=0,i=1e9,s=0;for(t in this.nodes)this.nodes.hasOwnProperty(t)&&(s=this.nodes[t].clusterSessions.length,s>e&&(e=s),i>s&&(i=s));if(e-i>this.constants.clustering.clusterLevelDifference){var o=this.nodeIndices.length,n=e-this.constants.clustering.clusterLevelDifference;for(t in this.nodes)this.nodes.hasOwnProperty(t)&&this.nodes[t].clusterSessions.lengths&&(s=n.dynamicEdgesLength),t+=n.dynamicEdgesLength,e+=Math.pow(n.dynamicEdgesLength,2),i+=1}t/=i,e/=i;var r=e-Math.pow(t,2),a=Math.sqrt(r);this.hubThreshold=Math.floor(t+2*a),this.hubThreshold>s&&(this.hubThreshold=s)},e._reduceAmountOfChains=function(t){this.hubThreshold=2;var e=Math.floor(this.nodeIndices.length*t);for(var i in this.nodes)this.nodes.hasOwnProperty(i)&&2==this.nodes[i].dynamicEdgesLength&&this.nodes[i].dynamicEdges.length>=2&&e>0&&(this._formClusterFromHub(this.nodes[i],!0,!0,1),e-=1)},e._getChainFraction=function(){var t=0,e=0;for(var i in this.nodes)this.nodes.hasOwnProperty(i)&&(2==this.nodes[i].dynamicEdgesLength&&this.nodes[i].dynamicEdges.length>=2&&(t+=1),e+=1);return t/e}},function(t,e,i){var s=i(1);e._putDataInSector=function(){this.sectors.active[this._sector()].nodes=this.nodes,this.sectors.active[this._sector()].edges=this.edges,this.sectors.active[this._sector()].nodeIndices=this.nodeIndices},e._switchToSector=function(t,e){void 0===e||"active"==e?this._switchToActiveSector(t):this._switchToFrozenSector(t)},e._switchToActiveSector=function(t){this.nodeIndices=this.sectors.active[t].nodeIndices,this.nodes=this.sectors.active[t].nodes,this.edges=this.sectors.active[t].edges},e._switchToSupportSector=function(){this.nodeIndices=this.sectors.support.nodeIndices,this.nodes=this.sectors.support.nodes,this.edges=this.sectors.support.edges},e._switchToFrozenSector=function(t){this.nodeIndices=this.sectors.frozen[t].nodeIndices,this.nodes=this.sectors.frozen[t].nodes,this.edges=this.sectors.frozen[t].edges},e._loadLatestSector=function(){this._switchToSector(this._sector())},e._sector=function(){return this.activeSector[this.activeSector.length-1]},e._previousSector=function(){if(this.activeSector.length>1)return this.activeSector[this.activeSector.length-2];throw new TypeError("there are not enough sectors in the this.activeSector array.")},e._setActiveSector=function(t){this.activeSector.push(t)},e._forgetLastSector=function(){this.activeSector.pop()},e._createNewSector=function(t){this.sectors.active[t]={nodes:{},edges:{},nodeIndices:[],formationScale:this.scale,drawingNode:void 0},this.sectors.active[t].drawingNode=new Node({id:t,color:{background:"#eaefef",border:"495c5e"}},{},{},this.constants),this.sectors.active[t].drawingNode.clusterSize=2},e._deleteActiveSector=function(t){delete this.sectors.active[t]},e._deleteFrozenSector=function(t){delete this.sectors.frozen[t]},e._freezeSector=function(t){this.sectors.frozen[t]=this.sectors.active[t],this._deleteActiveSector(t)},e._activateSector=function(t){this.sectors.active[t]=this.sectors.frozen[t],this._deleteFrozenSector(t)},e._mergeThisWithFrozen=function(t){for(var e in this.nodes)this.nodes.hasOwnProperty(e)&&(this.sectors.frozen[t].nodes[e]=this.nodes[e]);for(var i in this.edges)this.edges.hasOwnProperty(i)&&(this.sectors.frozen[t].edges[i]=this.edges[i]);for(var s=0;s1?this[t](s[0],s[1]):this[t](e)}this._loadLatestSector()},e._doInSupportSector=function(t,e){if(void 0===e)this._switchToSupportSector(),this[t]();else{this._switchToSupportSector();var i=Array.prototype.splice.call(arguments,1);i.length>1?this[t](i[0],i[1]):this[t](e)}this._loadLatestSector()},e._doInAllFrozenSectors=function(t,e){if(void 0===e)for(var i in this.sectors.frozen)this.sectors.frozen.hasOwnProperty(i)&&(this._switchToFrozenSector(i),this[t]());else for(var i in this.sectors.frozen)if(this.sectors.frozen.hasOwnProperty(i)){this._switchToFrozenSector(i);var s=Array.prototype.splice.call(arguments,1);s.length>1?this[t](s[0],s[1]):this[t](e)}this._loadLatestSector()},e._doInAllSectors=function(t,e){var i=Array.prototype.splice.call(arguments,1);void 0===e?(this._doInAllActiveSectors(t),this._doInAllFrozenSectors(t)):i.length>1?(this._doInAllActiveSectors(t,i[0],i[1]),this._doInAllFrozenSectors(t,i[0],i[1])):(this._doInAllActiveSectors(t,e),this._doInAllFrozenSectors(t,e))},e._clearNodeIndexList=function(){var t=this._sector();this.sectors.active[t].nodeIndices=[],this.nodeIndices=this.sectors.active[t].nodeIndices},e._drawSectorNodes=function(t,e){var i,s=1e9,o=-1e9,n=1e9,r=-1e9;for(var a in this.sectors[e])if(this.sectors[e].hasOwnProperty(a)&&void 0!==this.sectors[e][a].drawingNode){this._switchToSector(a,e),s=1e9,o=-1e9,n=1e9,r=-1e9;for(var h in this.nodes)this.nodes.hasOwnProperty(h)&&(i=this.nodes[h],i.resize(t),n>i.x-.5*i.width&&(n=i.x-.5*i.width),ri.y-.5*i.height&&(s=i.y-.5*i.height),o0?this.nodes[i[i.length-1]]:null},e._getEdgesOverlappingWith=function(t,e){var i=this.edges;for(var s in i)i.hasOwnProperty(s)&&i[s].isOverlappingWith(t)&&e.push(s)},e._getAllEdgesOverlappingWith=function(t){var e=[];return this._doInAllActiveSectors("_getEdgesOverlappingWith",t,e),e},e._getEdgeAt=function(t){var e=this._pointerToPositionObject(t),i=this._getAllEdgesOverlappingWith(e);return i.length>0?this.edges[i[i.length-1]]:null},e._addToSelection=function(t){t instanceof s?this.selectionObj.nodes[t.id]=t:this.selectionObj.edges[t.id]=t},e._addToHover=function(t){t instanceof s?this.hoverObj.nodes[t.id]=t:this.hoverObj.edges[t.id]=t},e._removeFromSelection=function(t){t instanceof s?delete this.selectionObj.nodes[t.id]:delete this.selectionObj.edges[t.id]},e._unselectAll=function(t){void 0===t&&(t=!1);for(var e in this.selectionObj.nodes)this.selectionObj.nodes.hasOwnProperty(e)&&this.selectionObj.nodes[e].unselect();for(var i in this.selectionObj.edges)this.selectionObj.edges.hasOwnProperty(i)&&this.selectionObj.edges[i].unselect();this.selectionObj={nodes:{},edges:{}},0==t&&this.emit("select",this.getSelection())},e._unselectClusters=function(t){void 0===t&&(t=!1);for(var e in this.selectionObj.nodes)this.selectionObj.nodes.hasOwnProperty(e)&&this.selectionObj.nodes[e].clusterSize>1&&(this.selectionObj.nodes[e].unselect(),this._removeFromSelection(this.selectionObj.nodes[e]));0==t&&this.emit("select",this.getSelection())},e._getSelectedNodeCount=function(){var t=0;for(var e in this.selectionObj.nodes)this.selectionObj.nodes.hasOwnProperty(e)&&(t+=1);return t},e._getSelectedNode=function(){for(var t in this.selectionObj.nodes)if(this.selectionObj.nodes.hasOwnProperty(t))return this.selectionObj.nodes[t];return null},e._getSelectedEdge=function(){for(var t in this.selectionObj.edges)if(this.selectionObj.edges.hasOwnProperty(t))return this.selectionObj.edges[t];return null},e._getSelectedEdgeCount=function(){var t=0;for(var e in this.selectionObj.edges)this.selectionObj.edges.hasOwnProperty(e)&&(t+=1);return t},e._getSelectedObjectCount=function(){var t=0;for(var e in this.selectionObj.nodes)this.selectionObj.nodes.hasOwnProperty(e)&&(t+=1);for(var i in this.selectionObj.edges)this.selectionObj.edges.hasOwnProperty(i)&&(t+=1);return t},e._selectionIsEmpty=function(){for(var t in this.selectionObj.nodes)if(this.selectionObj.nodes.hasOwnProperty(t))return!1;for(var e in this.selectionObj.edges)if(this.selectionObj.edges.hasOwnProperty(e))return!1;return!0},e._clusterInSelection=function(){for(var t in this.selectionObj.nodes)if(this.selectionObj.nodes.hasOwnProperty(t)&&this.selectionObj.nodes[t].clusterSize>1)return!0;return!1},e._selectConnectedEdges=function(t){for(var e=0;ee;e++){s=t[e];var o=this.nodes[s]; +if(!o)throw new RangeError('Node with id "'+s+'" not found');this._selectObject(o,!0,!0)}console.log("setSelection is deprecated. Please use selectNodes instead."),this.redraw()},e.selectNodes=function(t,e){var i,s,o;if(!t||void 0==t.length)throw"Selection must be an array with ids";for(this._unselectAll(!0),i=0,s=t.length;s>i;i++){o=t[i];var n=this.nodes[o];if(!n)throw new RangeError('Node with id "'+o+'" not found');this._selectObject(n,!0,!0,e)}this.redraw()},e.selectEdges=function(t){var e,i,s;if(!t||void 0==t.length)throw"Selection must be an array with ids";for(this._unselectAll(!0),e=0,i=t.length;i>e;e++){s=t[e];var o=this.edges[s];if(!o)throw new RangeError('Edge with id "'+s+'" not found');this._selectObject(o,!0,!0,highlightEdges)}this.redraw()},e._updateSelection=function(){for(var t in this.selectionObj.nodes)this.selectionObj.nodes.hasOwnProperty(t)&&(this.nodes.hasOwnProperty(t)||delete this.selectionObj.nodes[t]);for(var e in this.selectionObj.edges)this.selectionObj.edges.hasOwnProperty(e)&&(this.edges.hasOwnProperty(e)||delete this.selectionObj.edges[e])}},function(t,e,i){var s=i(1),o=i(36),n=i(33);e._clearManipulatorBar=function(){for(;this.manipulationDiv.hasChildNodes();)this.manipulationDiv.removeChild(this.manipulationDiv.firstChild)},e._restoreOverloadedFunctions=function(){for(var t in this.cachedFunctions)this.cachedFunctions.hasOwnProperty(t)&&(this[t]=this.cachedFunctions[t])},e._toggleEditMode=function(){this.editMode=!this.editMode;var t=document.getElementById("network-manipulationDiv"),e=document.getElementById("network-manipulation-closeDiv"),i=document.getElementById("network-manipulation-editMode");1==this.editMode?(t.style.display="block",e.style.display="block",i.style.display="none",e.onclick=this._toggleEditMode.bind(this)):(t.style.display="none",e.style.display="none",i.style.display="block",e.onclick=null),this._createManipulatorBar()},e._createManipulatorBar=function(){if(this.boundFunction&&this.off("select",this.boundFunction),void 0!==this.edgeBeingEdited&&(this.edgeBeingEdited._disableControlNodes(),this.edgeBeingEdited=void 0,this.selectedControlNode=null,this.controlNodesActive=!1),this._restoreOverloadedFunctions(),this.freezeSimulation=!1,this.blockConnectingEdgeSelection=!1,this.forceAppendSelection=!1,1==this.editMode){for(;this.manipulationDiv.hasChildNodes();)this.manipulationDiv.removeChild(this.manipulationDiv.firstChild);this.manipulationDiv.innerHTML=""+this.constants.labels.add+"
"+this.constants.labels.link+"",1==this._getSelectedNodeCount()&&this.triggerFunctions.edit?this.manipulationDiv.innerHTML+="
"+this.constants.labels.editNode+"":1==this._getSelectedEdgeCount()&&0==this._getSelectedNodeCount()&&(this.manipulationDiv.innerHTML+="
"+this.constants.labels.editEdge+""),0==this._selectionIsEmpty()&&(this.manipulationDiv.innerHTML+="
"+this.constants.labels.del+"");var t=document.getElementById("network-manipulate-addNode");t.onclick=this._createAddNodeToolbar.bind(this);var e=document.getElementById("network-manipulate-connectNode");if(e.onclick=this._createAddEdgeToolbar.bind(this),1==this._getSelectedNodeCount()&&this.triggerFunctions.edit){var i=document.getElementById("network-manipulate-editNode");i.onclick=this._editNode.bind(this)}else if(1==this._getSelectedEdgeCount()&&0==this._getSelectedNodeCount()){var i=document.getElementById("network-manipulate-editEdge");i.onclick=this._createEditEdgeToolbar.bind(this)}if(0==this._selectionIsEmpty()){var s=document.getElementById("network-manipulate-delete");s.onclick=this._deleteSelected.bind(this)}var o=document.getElementById("network-manipulation-closeDiv");o.onclick=this._toggleEditMode.bind(this),this.boundFunction=this._createManipulatorBar.bind(this),this.on("select",this.boundFunction)}else{this.editModeDiv.innerHTML=""+this.constants.labels.edit+"";var n=document.getElementById("network-manipulate-editModeButton");n.onclick=this._toggleEditMode.bind(this)}},e._createAddNodeToolbar=function(){this._clearManipulatorBar(),this.boundFunction&&this.off("select",this.boundFunction),this.manipulationDiv.innerHTML=""+this.constants.labels.back+"
"+this.constants.labels.addDescription+"";var t=document.getElementById("network-manipulate-back");t.onclick=this._createManipulatorBar.bind(this),this.boundFunction=this._addNode.bind(this),this.on("select",this.boundFunction)},e._createAddEdgeToolbar=function(){this._clearManipulatorBar(),this._unselectAll(!0),this.freezeSimulation=!0,this.boundFunction&&this.off("select",this.boundFunction),this._unselectAll(),this.forceAppendSelection=!1,this.blockConnectingEdgeSelection=!0,this.manipulationDiv.innerHTML=""+this.constants.labels.back+"
"+this.constants.labels.linkDescription+"";var t=document.getElementById("network-manipulate-back");t.onclick=this._createManipulatorBar.bind(this),this.boundFunction=this._handleConnect.bind(this),this.on("select",this.boundFunction),this.cachedFunctions._handleTouch=this._handleTouch,this.cachedFunctions._handleOnRelease=this._handleOnRelease,this._handleTouch=this._handleConnect,this._handleOnRelease=this._finishConnect,this._redraw()},e._createEditEdgeToolbar=function(){this._clearManipulatorBar(),this.controlNodesActive=!0,this.boundFunction&&this.off("select",this.boundFunction),this.edgeBeingEdited=this._getSelectedEdge(),this.edgeBeingEdited._enableControlNodes(),this.manipulationDiv.innerHTML=""+this.constants.labels.back+"
"+this.constants.labels.editEdgeDescription+"";var t=document.getElementById("network-manipulate-back");t.onclick=this._createManipulatorBar.bind(this),this.cachedFunctions._handleTouch=this._handleTouch,this.cachedFunctions._handleOnRelease=this._handleOnRelease,this.cachedFunctions._handleTap=this._handleTap,this.cachedFunctions._handleDragStart=this._handleDragStart,this.cachedFunctions._handleOnDrag=this._handleOnDrag,this._handleTouch=this._selectControlNode,this._handleTap=function(){},this._handleOnDrag=this._controlNodeDrag,this._handleDragStart=function(){},this._handleOnRelease=this._releaseControlNode,this._redraw()},e._selectControlNode=function(t){this.edgeBeingEdited.controlNodes.from.unselect(),this.edgeBeingEdited.controlNodes.to.unselect(),this.selectedControlNode=this.edgeBeingEdited._getSelectedControlNode(this._XconvertDOMtoCanvas(t.x),this._YconvertDOMtoCanvas(t.y)),null!==this.selectedControlNode&&(this.selectedControlNode.select(),this.freezeSimulation=!0),this._redraw()},e._controlNodeDrag=function(t){var e=this._getPointer(t.gesture.center);null!==this.selectedControlNode&&void 0!==this.selectedControlNode&&(this.selectedControlNode.x=this._XconvertDOMtoCanvas(e.x),this.selectedControlNode.y=this._YconvertDOMtoCanvas(e.y)),this._redraw()},e._releaseControlNode=function(t){var e=this._getNodeAt(t);null!=e?(1==this.edgeBeingEdited.controlNodes.from.selected&&(this._editEdge(e.id,this.edgeBeingEdited.to.id),this.edgeBeingEdited.controlNodes.from.unselect()),1==this.edgeBeingEdited.controlNodes.to.selected&&(this._editEdge(this.edgeBeingEdited.from.id,e.id),this.edgeBeingEdited.controlNodes.to.unselect())):this.edgeBeingEdited._restoreControlNodes(),this.freezeSimulation=!1,this._redraw()},e._handleConnect=function(t){if(0==this._getSelectedNodeCount()){var e=this._getNodeAt(t);null!=e&&(e.clusterSize>1?alert("Cannot create edges to a cluster."):(this._selectObject(e,!1),this.sectors.support.nodes.targetNode=new o({id:"targetNode"},{},{},this.constants),this.sectors.support.nodes.targetNode.x=e.x,this.sectors.support.nodes.targetNode.y=e.y,this.sectors.support.nodes.targetViaNode=new o({id:"targetViaNode"},{},{},this.constants),this.sectors.support.nodes.targetViaNode.x=e.x,this.sectors.support.nodes.targetViaNode.y=e.y,this.sectors.support.nodes.targetViaNode.parentEdgeId="connectionEdge",this.edges.connectionEdge=new n({id:"connectionEdge",from:e.id,to:this.sectors.support.nodes.targetNode.id},this,this.constants),this.edges.connectionEdge.from=e,this.edges.connectionEdge.connected=!0,this.edges.connectionEdge.smooth=!0,this.edges.connectionEdge.selected=!0,this.edges.connectionEdge.to=this.sectors.support.nodes.targetNode,this.edges.connectionEdge.via=this.sectors.support.nodes.targetViaNode,this.cachedFunctions._handleOnDrag=this._handleOnDrag,this._handleOnDrag=function(t){var e=this._getPointer(t.gesture.center);this.sectors.support.nodes.targetNode.x=this._XconvertDOMtoCanvas(e.x),this.sectors.support.nodes.targetNode.y=this._YconvertDOMtoCanvas(e.y),this.sectors.support.nodes.targetViaNode.x=.5*(this._XconvertDOMtoCanvas(e.x)+this.edges.connectionEdge.from.x),this.sectors.support.nodes.targetViaNode.y=this._YconvertDOMtoCanvas(e.y)},this.moving=!0,this.start()))}},e._finishConnect=function(t){if(1==this._getSelectedNodeCount()){this._handleOnDrag=this.cachedFunctions._handleOnDrag,delete this.cachedFunctions._handleOnDrag;var e=this.edges.connectionEdge.fromId;delete this.edges.connectionEdge,delete this.sectors.support.nodes.targetNode,delete this.sectors.support.nodes.targetViaNode;var i=this._getNodeAt(t);null!=i&&(i.clusterSize>1?alert("Cannot create edges to a cluster."):(this._createEdge(e,i.id),this._createManipulatorBar())),this._unselectAll()}},e._addNode=function(){if(this._selectionIsEmpty()&&1==this.editMode){var t=this._pointerToPositionObject(this.pointerPosition),e={id:s.randomUUID(),x:t.left,y:t.top,label:"new",allowedToMoveX:!0,allowedToMoveY:!0};if(this.triggerFunctions.add)if(2==this.triggerFunctions.add.length){var i=this;this.triggerFunctions.add(e,function(t){i.nodesData.add(t),i._createManipulatorBar(),i.moving=!0,i.start()})}else alert(this.constants.labels.addError),this._createManipulatorBar(),this.moving=!0,this.start();else this.nodesData.add(e),this._createManipulatorBar(),this.moving=!0,this.start()}},e._createEdge=function(t,e){if(1==this.editMode){var i={from:t,to:e};if(this.triggerFunctions.connect)if(2==this.triggerFunctions.connect.length){var s=this;this.triggerFunctions.connect(i,function(t){s.edgesData.add(t),s.moving=!0,s.start()})}else alert(this.constants.labels.linkError),this.moving=!0,this.start();else this.edgesData.add(i),this.moving=!0,this.start()}},e._editEdge=function(t,e){if(1==this.editMode){var i={id:this.edgeBeingEdited.id,from:t,to:e};if(this.triggerFunctions.editEdge)if(2==this.triggerFunctions.editEdge.length){var s=this;this.triggerFunctions.editEdge(i,function(t){s.edgesData.update(t),s.moving=!0,s.start()})}else alert(this.constants.labels.linkError),this.moving=!0,this.start();else this.edgesData.update(i),this.moving=!0,this.start()}},e._editNode=function(){if(this.triggerFunctions.edit&&1==this.editMode){var t=this._getSelectedNode(),e={id:t.id,label:t.label,group:t.options.group,shape:t.options.shape,color:{background:t.options.color.background,border:t.options.color.border,highlight:{background:t.options.color.highlight.background,border:t.options.color.highlight.border}}};if(2==this.triggerFunctions.edit.length){var i=this;this.triggerFunctions.edit(e,function(t){i.nodesData.update(t),i._createManipulatorBar(),i.moving=!0,i.start()})}else alert(this.constants.labels.editError)}else alert(this.constants.labels.editBoundError)},e._deleteSelected=function(){if(!this._selectionIsEmpty()&&1==this.editMode)if(this._clusterInSelection())alert(this.constants.labels.deleteClusterError);else{var t=this.getSelectedNodes(),e=this.getSelectedEdges();if(this.triggerFunctions.del){var i=this,s={nodes:t,edges:e};(this.triggerFunctions.del.length=2)?this.triggerFunctions.del(s,function(t){i.edgesData.remove(t.edges),i.nodesData.remove(t.nodes),i._unselectAll(),i.moving=!0,i.start()}):alert(this.constants.labels.deleteError)}else this.edgesData.remove(e),this.nodesData.remove(t),this._unselectAll(),this.moving=!0,this.start()}}},function(t,e,i){var s=i(1),o=i(41);e._cleanNavigation=function(){var t=document.getElementById("network-navigation_wrapper");null!=t&&this.containerElement.removeChild(t),document.onmouseup=null},e._loadNavigationElements=function(){this._cleanNavigation(),this.navigationDivs={};var t=["up","down","left","right","zoomIn","zoomOut","zoomExtends"],e=["_moveUp","_moveDown","_moveLeft","_moveRight","_zoomIn","_zoomOut","zoomExtent"];this.navigationDivs.wrapper=document.createElement("div"),this.navigationDivs.wrapper.id="network-navigation_wrapper",this.navigationDivs.wrapper.style.position="absolute",this.navigationDivs.wrapper.style.width=this.frame.canvas.clientWidth+"px",this.navigationDivs.wrapper.style.height=this.frame.canvas.clientHeight+"px",this.containerElement.insertBefore(this.navigationDivs.wrapper,this.frame);for(var i=this,s=0;s0){"RL"==this.constants.hierarchicalLayout.direction||"DU"==this.constants.hierarchicalLayout.direction?this.constants.hierarchicalLayout.levelSeparation*=-1:this.constants.hierarchicalLayout.levelSeparation=Math.abs(this.constants.hierarchicalLayout.levelSeparation),"RL"==this.constants.hierarchicalLayout.direction||"LR"==this.constants.hierarchicalLayout.direction?1==this.constants.smoothCurves.enabled&&(this.constants.smoothCurves.type="vertical"):1==this.constants.smoothCurves.enabled&&(this.constants.smoothCurves.type="horizontal");var t,e,i=0,s=!1,o=!1;for(e in this.nodes)this.nodes.hasOwnProperty(e)&&(t=this.nodes[e],-1!=t.level?s=!0:o=!0,is&&(n.xFixed=!1,n.x=i[n.level].minPos,r=!0):n.yFixed&&n.level>s&&(n.yFixed=!1,n.y=i[n.level].minPos,r=!0),1==r&&(i[n.level].minPos+=i[n.level].nodeSpacing,n.edges.length>1&&this._placeBranchNodes(n.edges,n.id,i,n.level))}},e._setLevel=function(t,e,i){for(var s=0;st)&&(o.level=t,e.length>1&&this._setLevel(t+1,o.edges,o.id))}},e._restoreNodes=function(){for(var t in this.nodes)this.nodes.hasOwnProperty(t)&&(this.nodes[t].xFixed=!1,this.nodes[t].yFixed=!1)}},function(t,e,i){function s(){this.constants.smoothCurves.enabled=!this.constants.smoothCurves.enabled;var t=document.getElementById("graph_toggleSmooth");t.style.background=1==this.constants.smoothCurves.enabled?"#A4FF56":"#FF8532",this._configureSmoothCurves(!1)}function o(){for(var t in this.calculationNodes)this.calculationNodes.hasOwnProperty(t)&&(this.calculationNodes[t].vx=0,this.calculationNodes[t].vy=0,this.calculationNodes[t].fx=0,this.calculationNodes[t].fy=0);1==this.constants.hierarchicalLayout.enabled?(this._setupHierarchicalLayout(),a.call(this,"graph_H_nd",1,"physics_hierarchicalRepulsion_nodeDistance"),a.call(this,"graph_H_cg",1,"physics_centralGravity"),a.call(this,"graph_H_sc",1,"physics_springConstant"),a.call(this,"graph_H_sl",1,"physics_springLength"),a.call(this,"graph_H_damp",1,"physics_damping")):this.repositionNodes(),this.moving=!0,this.start()}function n(){var t="No options are required, default values used.",e=[],i=document.getElementById("graph_physicsMethod1"),s=document.getElementById("graph_physicsMethod2");if(1==i.checked){if(this.constants.physics.barnesHut.gravitationalConstant!=this.backupConstants.physics.barnesHut.gravitationalConstant&&e.push("gravitationalConstant: "+this.constants.physics.barnesHut.gravitationalConstant),this.constants.physics.centralGravity!=this.backupConstants.physics.barnesHut.centralGravity&&e.push("centralGravity: "+this.constants.physics.centralGravity),this.constants.physics.springLength!=this.backupConstants.physics.barnesHut.springLength&&e.push("springLength: "+this.constants.physics.springLength),this.constants.physics.springConstant!=this.backupConstants.physics.barnesHut.springConstant&&e.push("springConstant: "+this.constants.physics.springConstant),this.constants.physics.damping!=this.backupConstants.physics.barnesHut.damping&&e.push("damping: "+this.constants.physics.damping),0!=e.length){t="var options = {",t+="physics: {barnesHut: {";for(var o=0;othis.constants.clustering.clusterThreshold&&1==this.constants.clustering.enabled&&this.clusterToFit(this.constants.clustering.reduceToNodes,!1),this._calculateForces())},e._calculateForces=function(){this._calculateGravitationalForces(),this._calculateNodeForces(),this.constants.physics.springConstant>0&&(1==this.constants.smoothCurves.enabled&&1==this.constants.smoothCurves.dynamic?this._calculateSpringForcesWithSupport():1==this.constants.physics.hierarchicalRepulsion.enabled?this._calculateHierarchicalSpringForces():this._calculateSpringForces())},e._updateCalculationNodes=function(){if(1==this.constants.smoothCurves.enabled&&1==this.constants.smoothCurves.dynamic){this.calculationNodes={},this.calculationNodeIndices=[];for(var t in this.nodes)this.nodes.hasOwnProperty(t)&&(this.calculationNodes[t]=this.nodes[t]);var e=this.sectors.support.nodes;for(var i in e)e.hasOwnProperty(i)&&(this.edges.hasOwnProperty(e[i].parentEdgeId)?this.calculationNodes[i]=e[i]:e[i]._setForce(0,0));for(var s in this.calculationNodes)this.calculationNodes.hasOwnProperty(s)&&this.calculationNodeIndices.push(s)}else this.calculationNodes=this.nodes,this.calculationNodeIndices=this.nodeIndices},e._calculateGravitationalForces=function(){var t,e,i,s,o,n=this.calculationNodes,r=this.constants.physics.centralGravity,a=0;for(o=0;oSimulation Mode:Barnes HutRepulsionHierarchical
Options:
',this.containerElement.parentElement.insertBefore(this.physicsConfiguration,this.containerElement),this.optionsDiv=document.createElement("div"),this.optionsDiv.style.fontSize="14px",this.optionsDiv.style.fontFamily="verdana",this.containerElement.parentElement.insertBefore(this.optionsDiv,this.containerElement); var e;e=document.getElementById("graph_BH_gc"),e.onchange=a.bind(this,"graph_BH_gc",-1,"physics_barnesHut_gravitationalConstant"),e=document.getElementById("graph_BH_cg"),e.onchange=a.bind(this,"graph_BH_cg",1,"physics_centralGravity"),e=document.getElementById("graph_BH_sc"),e.onchange=a.bind(this,"graph_BH_sc",1,"physics_springConstant"),e=document.getElementById("graph_BH_sl"),e.onchange=a.bind(this,"graph_BH_sl",1,"physics_springLength"),e=document.getElementById("graph_BH_damp"),e.onchange=a.bind(this,"graph_BH_damp",1,"physics_damping"),e=document.getElementById("graph_R_nd"),e.onchange=a.bind(this,"graph_R_nd",1,"physics_repulsion_nodeDistance"),e=document.getElementById("graph_R_cg"),e.onchange=a.bind(this,"graph_R_cg",1,"physics_centralGravity"),e=document.getElementById("graph_R_sc"),e.onchange=a.bind(this,"graph_R_sc",1,"physics_springConstant"),e=document.getElementById("graph_R_sl"),e.onchange=a.bind(this,"graph_R_sl",1,"physics_springLength"),e=document.getElementById("graph_R_damp"),e.onchange=a.bind(this,"graph_R_damp",1,"physics_damping"),e=document.getElementById("graph_H_nd"),e.onchange=a.bind(this,"graph_H_nd",1,"physics_hierarchicalRepulsion_nodeDistance"),e=document.getElementById("graph_H_cg"),e.onchange=a.bind(this,"graph_H_cg",1,"physics_centralGravity"),e=document.getElementById("graph_H_sc"),e.onchange=a.bind(this,"graph_H_sc",1,"physics_springConstant"),e=document.getElementById("graph_H_sl"),e.onchange=a.bind(this,"graph_H_sl",1,"physics_springLength"),e=document.getElementById("graph_H_damp"),e.onchange=a.bind(this,"graph_H_damp",1,"physics_damping"),e=document.getElementById("graph_H_direction"),e.onchange=a.bind(this,"graph_H_direction",t,"hierarchicalLayout_direction"),e=document.getElementById("graph_H_levsep"),e.onchange=a.bind(this,"graph_H_levsep",1,"hierarchicalLayout_levelSeparation"),e=document.getElementById("graph_H_nspac"),e.onchange=a.bind(this,"graph_H_nspac",1,"hierarchicalLayout_nodeSpacing");var i=document.getElementById("graph_physicsMethod1"),d=document.getElementById("graph_physicsMethod2"),l=document.getElementById("graph_physicsMethod3");d.checked=!0,this.constants.physics.barnesHut.enabled&&(i.checked=!0),this.constants.hierarchicalLayout.enabled&&(l.checked=!0);var c=document.getElementById("graph_toggleSmooth"),p=document.getElementById("graph_repositionNodes"),u=document.getElementById("graph_generateOptions");c.onclick=s.bind(this),p.onclick=o.bind(this),u.onclick=n.bind(this),c.style.background=1==this.constants.smoothCurves&&0==this.constants.dynamicSmoothCurves?"#A4FF56":"#FF8532",r.apply(this),i.onchange=r.bind(this),d.onchange=r.bind(this),l.onchange=r.bind(this)}},e._overWriteGraphConstants=function(t,e){var i=t.split("_");1==i.length?this.constants[i[0]]=e:2==i.length?this.constants[i[0]][i[1]]=e:3==i.length&&(this.constants[i[0]][i[1]][i[2]]=e)}},function(t,e,i){function s(t){return i(o(t))}function o(t){return n[t]||function(){throw new Error("Cannot find module '"+t+"'.")}()}var n={};s.keys=function(){return Object.keys(n)},s.resolve=o,t.exports=s},function(t,e){e._calculateNodeForces=function(){var t,e,i,s,o,n,r,a,h,d,l,c=this.calculationNodes,p=this.calculationNodeIndices,u=-2/3,f=4/3,m=this.constants.physics.repulsion.nodeDistance,g=m;for(d=0;di&&(r=.5*g>i?1:v*i+f,r*=0==n?1:1+n*this.constants.clustering.forceAmplification,r/=i,s=t*r,o=e*r,a.fx-=s,a.fy-=o,h.fx+=s,h.fy+=o)}}},function(t,e){e._calculateNodeForces=function(){var t,e,i,s,o,n,r,a,h,d,l=this.calculationNodes,c=this.calculationNodeIndices,p=this.constants.physics.hierarchicalRepulsion.nodeDistance;for(h=0;hi?-Math.pow(u*i,2)+Math.pow(u*p,2):0,0==i?i=.01:n/=i,s=t*n,o=e*n,r.fx-=s,r.fy-=o,a.fx+=s,a.fy+=o}},e._calculateHierarchicalSpringForces=function(){for(var t,e,i,s,o,n,r,a,h,d=this.edges,l=this.calculationNodes,c=this.calculationNodeIndices,p=0;pn;n++)t=e[i[n]],t.options.mass>0&&(this._getForceContribution(o.root.children.NW,t),this._getForceContribution(o.root.children.NE,t),this._getForceContribution(o.root.children.SW,t),this._getForceContribution(o.root.children.SE,t))}},e._getForceContribution=function(t,e){if(t.childrenCount>0){var i,s,o;if(i=t.centerOfMass.x-e.x,s=t.centerOfMass.y-e.y,o=Math.sqrt(i*i+s*s),o*t.calcSize>this.constants.physics.barnesHut.theta){0==o&&(o=.1*Math.random(),i=o);var n=this.constants.physics.barnesHut.gravitationalConstant*t.mass*e.options.mass/(o*o*o),r=i*n,a=s*n;e.fx+=r,e.fy+=a}else if(4==t.childrenCount)this._getForceContribution(t.children.NW,e),this._getForceContribution(t.children.NE,e),this._getForceContribution(t.children.SW,e),this._getForceContribution(t.children.SE,e);else if(t.children.data.id!=e.id){0==o&&(o=.5*Math.random(),i=o);var n=this.constants.physics.barnesHut.gravitationalConstant*t.mass*e.options.mass/(o*o*o),r=i*n,a=s*n;e.fx+=r,e.fy+=a}}},e._formBarnesHutTree=function(t,e){for(var i,s=e.length,o=Number.MAX_VALUE,n=Number.MAX_VALUE,r=-Number.MAX_VALUE,a=-Number.MAX_VALUE,h=0;s>h;h++){var d=t[e[h]].x,l=t[e[h]].y;t[e[h]].options.mass>0&&(o>d&&(o=d),d>r&&(r=d),n>l&&(n=l),l>a&&(a=l))}var c=Math.abs(r-o)-Math.abs(a-n);c>0?(n-=.5*c,a+=.5*c):(o+=.5*c,r-=.5*c);var p=1e-5,u=Math.max(p,Math.abs(r-o)),f=.5*u,m=.5*(o+r),g=.5*(n+a),v={root:{centerOfMass:{x:0,y:0},mass:0,range:{minX:m-f,maxX:m+f,minY:g-f,maxY:g+f},size:u,calcSize:1/u,children:{data:null},maxWidth:0,level:0,childrenCount:4}};for(this._splitBranch(v.root),h=0;s>h;h++)i=t[e[h]],i.options.mass>0&&this._placeInTree(v.root,i);this.barnesHutTree=v},e._updateBranchMass=function(t,e){var i=t.mass+e.options.mass,s=1/i;t.centerOfMass.x=t.centerOfMass.x*t.mass+e.x*e.options.mass,t.centerOfMass.x*=s,t.centerOfMass.y=t.centerOfMass.y*t.mass+e.y*e.options.mass,t.centerOfMass.y*=s,t.mass=i;var o=Math.max(Math.max(e.height,e.radius),e.width);t.maxWidth=t.maxWidthe.x?t.children.NW.range.maxY>e.y?this._placeInRegion(t,e,"NW"):this._placeInRegion(t,e,"SW"):t.children.NW.range.maxY>e.y?this._placeInRegion(t,e,"NE"):this._placeInRegion(t,e,"SE")},e._placeInRegion=function(t,e,i){switch(t.children[i].childrenCount){case 0:t.children[i].children.data=e,t.children[i].childrenCount=1,this._updateBranchMass(t.children[i],e);break;case 1:t.children[i].children.data.x==e.x&&t.children[i].children.data.y==e.y?(e.x+=Math.random(),e.y+=Math.random()):(this._splitBranch(t.children[i]),this._placeInTree(t.children[i],e));break;case 4:this._placeInTree(t.children[i],e)}},e._splitBranch=function(t){var e=null;1==t.childrenCount&&(e=t.children.data,t.mass=0,t.centerOfMass.x=0,t.centerOfMass.y=0),t.childrenCount=4,t.children.data=null,this._insertRegion(t,"NW"),this._insertRegion(t,"NE"),this._insertRegion(t,"SW"),this._insertRegion(t,"SE"),null!=e&&this._placeInTree(t,e)},e._insertRegion=function(t,e){var i,s,o,n,r=.5*t.size;switch(e){case"NW":i=t.range.minX,s=t.range.minX+r,o=t.range.minY,n=t.range.minY+r;break;case"NE":i=t.range.minX+r,s=t.range.maxX,o=t.range.minY,n=t.range.minY+r;break;case"SW":i=t.range.minX,s=t.range.minX+r,o=t.range.minY+r,n=t.range.maxY;break;case"SE":i=t.range.minX+r,s=t.range.maxX,o=t.range.minY+r,n=t.range.maxY}t.children[e]={centerOfMass:{x:0,y:0},mass:0,range:{minX:i,maxX:s,minY:o,maxY:n},size:.5*t.size,calcSize:2*t.calcSize,children:{data:null},maxWidth:0,level:t.level+1,childrenCount:0}},e._drawTree=function(t,e){void 0!==this.barnesHutTree&&(t.lineWidth=1,this._drawBranch(this.barnesHutTree.root,t,e))},e._drawBranch=function(t,e,i){void 0===i&&(i="#FF0000"),4==t.childrenCount&&(this._drawBranch(t.children.NW,e),this._drawBranch(t.children.NE,e),this._drawBranch(t.children.SE,e),this._drawBranch(t.children.SW,e)),e.strokeStyle=i,e.beginPath(),e.moveTo(t.range.minX,t.range.minY),e.lineTo(t.range.maxX,t.range.minY),e.stroke(),e.beginPath(),e.moveTo(t.range.maxX,t.range.minY),e.lineTo(t.range.maxX,t.range.maxY),e.stroke(),e.beginPath(),e.moveTo(t.range.maxX,t.range.maxY),e.lineTo(t.range.minX,t.range.maxY),e.stroke(),e.beginPath(),e.moveTo(t.range.minX,t.range.maxY),e.lineTo(t.range.minX,t.range.minY),e.stroke()}},function(t){t.exports=function(t){return t.webpackPolyfill||(t.deprecate=function(){},t.paths=[],t.children=[],t.webpackPolyfill=1),t}}])}); //# sourceMappingURL=vis.map \ No newline at end of file diff --git a/examples/network/ex.html b/examples/network/ex.html new file mode 100644 index 00000000..15c0d6b7 --- /dev/null +++ b/examples/network/ex.html @@ -0,0 +1,128 @@ + + + + Network | Basic usage + + + + + + + + +
+ + + + + diff --git a/lib/network/Network.js b/lib/network/Network.js index 743e9b16..ac0476bb 100644 --- a/lib/network/Network.js +++ b/lib/network/Network.js @@ -1349,9 +1349,8 @@ Network.prototype._addNodes = function(ids) { var data = this.nodesData.get(id); var node = new Node(data, this.images, this.groups, this.constants); this.nodes[id] = node; // note: this may replace an existing node - if ((node.xFixed == false || node.yFixed == false) && (node.x === null || node.y === null)) { - var radius = 10 * 0.1*ids.length; + var radius = 10 * 0.1*ids.length + 10; var angle = 2 * Math.PI * Math.random(); if (node.xFixed == false) {node.x = radius * Math.cos(angle);} if (node.yFixed == false) {node.y = radius * Math.sin(angle);} @@ -1952,7 +1951,7 @@ Network.prototype._isMoving = function(vmin) { * * @private */ -Network.prototype._discreteStepNodes = function() { +Network.prototype._discreteStepNodes = function(checkMovement) { var interval = this.physicsDiscreteStepsize; var nodes = this.nodes; var nodeId; @@ -1975,7 +1974,7 @@ Network.prototype._discreteStepNodes = function() { } } - if (nodesPresent == true) { + if (nodesPresent == true && (checkMovement === undefined || checkMovement == true)) { var vminCorrected = this.constants.minVelocity / Math.max(this.scale,0.05); if (vminCorrected > 0.5*this.constants.maxVelocity) { this.moving = true; @@ -2002,7 +2001,7 @@ Network.prototype._physicsTick = function() { this._doInAllActiveSectors("_initializeForceCalculation"); this._doInAllActiveSectors("_discreteStepNodes"); if (this.constants.smoothCurves.enabled == true && this.constants.smoothCurves.dynamic == true) { - this._doInSupportSector("_discreteStepNodes"); + this._doInSupportSector("_discreteStepNodes", false); } this._findCenter(this._getRange()) } diff --git a/lib/network/Node.js b/lib/network/Node.js index e59af3a2..4c7d1e8c 100644 --- a/lib/network/Node.js +++ b/lib/network/Node.js @@ -386,9 +386,10 @@ Node.prototype.isFixed = function() { * @param {number} vmin the minimum velocity considered as "moving" * @return {boolean} true if moving, false if it has no velocity */ -// TODO: replace this method with calculating the kinetic energy Node.prototype.isMoving = function(vmin) { - return (Math.abs(this.vx) > vmin || Math.abs(this.vy) > vmin); + var velocity = Math.sqrt(Math.pow(this.vx,2) + Math.pow(this.vy,2)); +// this.velocity = Math.sqrt(Math.pow(this.vx,2) + Math.pow(this.vy,2)) + return (velocity > vmin); }; /**